/root/src/xen/xen/arch/x86/ioport_emulate.c
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * ioport_emulate.c |
3 | | * |
4 | | * Handle I/O port access quirks of various platforms. |
5 | | */ |
6 | | |
7 | | #include <xen/init.h> |
8 | | #include <xen/sched.h> |
9 | | #include <xen/dmi.h> |
10 | | |
11 | | static void ioemul_handle_proliant_quirk( |
12 | | u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs) |
13 | 0 | { |
14 | 0 | uint16_t port = regs->dx; |
15 | 0 | uint8_t value = regs->al; |
16 | 0 |
|
17 | 0 | if ( (opcode != 0xee) || (port != 0xcd4) || !(value & 0x80) ) |
18 | 0 | return; |
19 | 0 |
|
20 | 0 | /* pushf */ |
21 | 0 | io_emul_stub[0] = 0x9c; |
22 | 0 | /* cli */ |
23 | 0 | io_emul_stub[1] = 0xfa; |
24 | 0 | /* out %al,%dx */ |
25 | 0 | io_emul_stub[2] = 0xee; |
26 | 0 | /* 1: in %dx,%al */ |
27 | 0 | io_emul_stub[3] = 0xec; |
28 | 0 | /* test $0x80,%al */ |
29 | 0 | io_emul_stub[4] = 0xa8; |
30 | 0 | io_emul_stub[5] = 0x80; |
31 | 0 | /* jnz 1b */ |
32 | 0 | io_emul_stub[6] = 0x75; |
33 | 0 | io_emul_stub[7] = 0xfb; |
34 | 0 | /* popf */ |
35 | 0 | io_emul_stub[8] = 0x9d; |
36 | 0 | /* ret */ |
37 | 0 | io_emul_stub[9] = 0xc3; |
38 | 0 | } |
39 | | |
40 | | static int __init proliant_quirk(struct dmi_system_id *d) |
41 | 0 | { |
42 | 0 | ioemul_handle_quirk = ioemul_handle_proliant_quirk; |
43 | 0 | return 0; |
44 | 0 | } |
45 | | |
46 | | /* This table is the set of system-specific I/O emulation hooks. */ |
47 | | static struct dmi_system_id __initdata ioport_quirks_tbl[] = { |
48 | | /* |
49 | | * I/O emulation hook for certain HP ProLiant servers with |
50 | | * 'special' SMM goodness. |
51 | | */ |
52 | | { |
53 | | .callback = proliant_quirk, |
54 | | .ident = "HP ProLiant DL3xx", |
55 | | .matches = { |
56 | | DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
57 | | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL3"), |
58 | | }, |
59 | | }, |
60 | | { |
61 | | .callback = proliant_quirk, |
62 | | .ident = "HP ProLiant DL5xx", |
63 | | .matches = { |
64 | | DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
65 | | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL5"), |
66 | | }, |
67 | | }, |
68 | | { |
69 | | .callback = proliant_quirk, |
70 | | .ident = "HP ProLiant DL7xx", |
71 | | .matches = { |
72 | | DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
73 | | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant DL7"), |
74 | | }, |
75 | | }, |
76 | | { |
77 | | .callback = proliant_quirk, |
78 | | .ident = "HP ProLiant ML3xx", |
79 | | .matches = { |
80 | | DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
81 | | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML3"), |
82 | | }, |
83 | | }, |
84 | | { |
85 | | .callback = proliant_quirk, |
86 | | .ident = "HP ProLiant ML5xx", |
87 | | .matches = { |
88 | | DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
89 | | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant ML5"), |
90 | | }, |
91 | | }, |
92 | | { |
93 | | .callback = proliant_quirk, |
94 | | .ident = "HP ProLiant BL2xx", |
95 | | .matches = { |
96 | | DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
97 | | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL2"), |
98 | | }, |
99 | | }, |
100 | | { |
101 | | .callback = proliant_quirk, |
102 | | .ident = "HP ProLiant BL4xx", |
103 | | .matches = { |
104 | | DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
105 | | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL4"), |
106 | | }, |
107 | | }, |
108 | | { |
109 | | .callback = proliant_quirk, |
110 | | .ident = "HP ProLiant BL6xx", |
111 | | .matches = { |
112 | | DMI_MATCH(DMI_BIOS_VENDOR, "HP"), |
113 | | DMI_MATCH(DMI_PRODUCT_NAME, "ProLiant BL6"), |
114 | | }, |
115 | | }, |
116 | | { } |
117 | | }; |
118 | | |
119 | | static int __init ioport_quirks_init(void) |
120 | 1 | { |
121 | 1 | dmi_check_system(ioport_quirks_tbl); |
122 | 1 | return 0; |
123 | 1 | } |
124 | | __initcall(ioport_quirks_init); |
125 | | |
126 | | /* |
127 | | * Local variables: |
128 | | * mode: C |
129 | | * c-file-style: "BSD" |
130 | | * c-basic-offset: 4 |
131 | | * tab-width: 4 |
132 | | * indent-tabs-mode: nil |
133 | | * End: |
134 | | */ |