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
ioemul_handle_proliant_quirk(u8 opcode,char * io_emul_stub,struct cpu_user_regs * regs)11 static void ioemul_handle_proliant_quirk(
12 u8 opcode, char *io_emul_stub, struct cpu_user_regs *regs)
13 {
14 uint16_t port = regs->dx;
15 uint8_t value = regs->al;
16
17 if ( (opcode != 0xee) || (port != 0xcd4) || !(value & 0x80) )
18 return;
19
20 /* pushf */
21 io_emul_stub[0] = 0x9c;
22 /* cli */
23 io_emul_stub[1] = 0xfa;
24 /* out %al,%dx */
25 io_emul_stub[2] = 0xee;
26 /* 1: in %dx,%al */
27 io_emul_stub[3] = 0xec;
28 /* test $0x80,%al */
29 io_emul_stub[4] = 0xa8;
30 io_emul_stub[5] = 0x80;
31 /* jnz 1b */
32 io_emul_stub[6] = 0x75;
33 io_emul_stub[7] = 0xfb;
34 /* popf */
35 io_emul_stub[8] = 0x9d;
36 /* ret */
37 io_emul_stub[9] = 0xc3;
38 }
39
proliant_quirk(struct dmi_system_id * d)40 static int __init proliant_quirk(struct dmi_system_id *d)
41 {
42 ioemul_handle_quirk = ioemul_handle_proliant_quirk;
43 return 0;
44 }
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
ioport_quirks_init(void)119 static int __init ioport_quirks_init(void)
120 {
121 dmi_check_system(ioport_quirks_tbl);
122 return 0;
123 }
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 */
135