diff options
Diffstat (limited to 'drivers/pnp/pnpbios/bioscalls.c')
-rw-r--r-- | drivers/pnp/pnpbios/bioscalls.c | 45 |
1 files changed, 18 insertions, 27 deletions
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index 6b7583f497d0..a1f0b0ba2bfe 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c | |||
@@ -31,15 +31,6 @@ static struct { | |||
31 | } pnp_bios_callpoint; | 31 | } pnp_bios_callpoint; |
32 | 32 | ||
33 | 33 | ||
34 | /* The PnP BIOS entries in the GDT */ | ||
35 | #define PNP_GDT (GDT_ENTRY_PNPBIOS_BASE * 8) | ||
36 | |||
37 | #define PNP_CS32 (PNP_GDT+0x00) /* segment for calling fn */ | ||
38 | #define PNP_CS16 (PNP_GDT+0x08) /* code segment for BIOS */ | ||
39 | #define PNP_DS (PNP_GDT+0x10) /* data segment for BIOS */ | ||
40 | #define PNP_TS1 (PNP_GDT+0x18) /* transfer data segment */ | ||
41 | #define PNP_TS2 (PNP_GDT+0x20) /* another data segment */ | ||
42 | |||
43 | /* | 34 | /* |
44 | * These are some opcodes for a "static asmlinkage" | 35 | * These are some opcodes for a "static asmlinkage" |
45 | * As this code is *not* executed inside the linux kernel segment, but in a | 36 | * As this code is *not* executed inside the linux kernel segment, but in a |
@@ -67,16 +58,11 @@ __asm__( | |||
67 | ".previous \n" | 58 | ".previous \n" |
68 | ); | 59 | ); |
69 | 60 | ||
70 | #define Q_SET_SEL(cpu, selname, address, size) \ | ||
71 | do { \ | ||
72 | set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], __va((u32)(address))); \ | ||
73 | set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \ | ||
74 | } while(0) | ||
75 | |||
76 | #define Q2_SET_SEL(cpu, selname, address, size) \ | 61 | #define Q2_SET_SEL(cpu, selname, address, size) \ |
77 | do { \ | 62 | do { \ |
78 | set_base(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], (u32)(address)); \ | 63 | struct desc_struct *gdt = get_cpu_gdt_table((cpu)); \ |
79 | set_limit(per_cpu(cpu_gdt_table,cpu)[(selname) >> 3], size); \ | 64 | set_base(gdt[(selname) >> 3], (u32)(address)); \ |
65 | set_limit(gdt[(selname) >> 3], size); \ | ||
80 | } while(0) | 66 | } while(0) |
81 | 67 | ||
82 | static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; | 68 | static struct desc_struct bad_bios_desc = { 0, 0x00409200 }; |
@@ -115,8 +101,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, | |||
115 | return PNP_FUNCTION_NOT_SUPPORTED; | 101 | return PNP_FUNCTION_NOT_SUPPORTED; |
116 | 102 | ||
117 | cpu = get_cpu(); | 103 | cpu = get_cpu(); |
118 | save_desc_40 = per_cpu(cpu_gdt_table,cpu)[0x40 / 8]; | 104 | save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8]; |
119 | per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = bad_bios_desc; | 105 | get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc; |
120 | 106 | ||
121 | /* On some boxes IRQ's during PnP BIOS calls are deadly. */ | 107 | /* On some boxes IRQ's during PnP BIOS calls are deadly. */ |
122 | spin_lock_irqsave(&pnp_bios_lock, flags); | 108 | spin_lock_irqsave(&pnp_bios_lock, flags); |
@@ -158,7 +144,7 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, | |||
158 | ); | 144 | ); |
159 | spin_unlock_irqrestore(&pnp_bios_lock, flags); | 145 | spin_unlock_irqrestore(&pnp_bios_lock, flags); |
160 | 146 | ||
161 | per_cpu(cpu_gdt_table,cpu)[0x40 / 8] = save_desc_40; | 147 | get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40; |
162 | put_cpu(); | 148 | put_cpu(); |
163 | 149 | ||
164 | /* If we get here and this is set then the PnP BIOS faulted on us. */ | 150 | /* If we get here and this is set then the PnP BIOS faulted on us. */ |
@@ -290,12 +276,15 @@ int pnp_bios_dev_node_info(struct pnp_dev_node_info *data) | |||
290 | static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) | 276 | static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) |
291 | { | 277 | { |
292 | u16 status; | 278 | u16 status; |
279 | u16 tmp_nodenum; | ||
293 | if (!pnp_bios_present()) | 280 | if (!pnp_bios_present()) |
294 | return PNP_FUNCTION_NOT_SUPPORTED; | 281 | return PNP_FUNCTION_NOT_SUPPORTED; |
295 | if ( !boot && pnpbios_dont_use_current_config ) | 282 | if ( !boot && pnpbios_dont_use_current_config ) |
296 | return PNP_FUNCTION_NOT_SUPPORTED; | 283 | return PNP_FUNCTION_NOT_SUPPORTED; |
284 | tmp_nodenum = *nodenum; | ||
297 | status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0, | 285 | status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0, |
298 | nodenum, sizeof(char), data, 65536); | 286 | &tmp_nodenum, sizeof(tmp_nodenum), data, 65536); |
287 | *nodenum = tmp_nodenum; | ||
299 | return status; | 288 | return status; |
300 | } | 289 | } |
301 | 290 | ||
@@ -535,10 +524,12 @@ void pnpbios_calls_init(union pnp_bios_install_struct *header) | |||
535 | 524 | ||
536 | set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); | 525 | set_base(bad_bios_desc, __va((unsigned long)0x40 << 4)); |
537 | _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); | 526 | _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4)); |
538 | for(i=0; i < NR_CPUS; i++) | 527 | for (i = 0; i < NR_CPUS; i++) { |
539 | { | 528 | struct desc_struct *gdt = get_cpu_gdt_table(i); |
540 | Q2_SET_SEL(i, PNP_CS32, &pnp_bios_callfunc, 64 * 1024); | 529 | if (!gdt) |
541 | Q_SET_SEL(i, PNP_CS16, header->fields.pm16cseg, 64 * 1024); | 530 | continue; |
542 | Q_SET_SEL(i, PNP_DS, header->fields.pm16dseg, 64 * 1024); | 531 | set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc); |
543 | } | 532 | set_base(gdt[GDT_ENTRY_PNPBIOS_CS16], __va(header->fields.pm16cseg)); |
533 | set_base(gdt[GDT_ENTRY_PNPBIOS_DS], __va(header->fields.pm16dseg)); | ||
534 | } | ||
544 | } | 535 | } |