Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / pnp / pnpbios / bioscalls.c
1 /*
2  * bioscalls.c - the lowlevel layer of the PnPBIOS driver
3  *
4  */
5
6 #include <linux/types.h>
7 #include <linux/module.h>
8 #include <linux/init.h>
9 #include <linux/linkage.h>
10 #include <linux/kernel.h>
11 #include <linux/pnpbios.h>
12 #include <linux/device.h>
13 #include <linux/pnp.h>
14 #include <linux/mm.h>
15 #include <linux/smp.h>
16 #include <linux/slab.h>
17 #include <linux/kmod.h>
18 #include <linux/completion.h>
19 #include <linux/spinlock.h>
20
21 #include <asm/page.h>
22 #include <asm/desc.h>
23 #include <asm/system.h>
24 #include <asm/byteorder.h>
25
26 #include "pnpbios.h"
27
28 static struct {
29         u16     offset;
30         u16     segment;
31 } pnp_bios_callpoint;
32
33
34 /*
35  * These are some opcodes for a "static asmlinkage"
36  * As this code is *not* executed inside the linux kernel segment, but in a
37  * alias at offset 0, we need a far return that can not be compiled by
38  * default (please, prove me wrong! this is *really* ugly!)
39  * This is the only way to get the bios to return into the kernel code,
40  * because the bios code runs in 16 bit protected mode and therefore can only
41  * return to the caller if the call is within the first 64kB, and the linux
42  * kernel begins at offset 3GB...
43  */
44
45 asmlinkage void pnp_bios_callfunc(void);
46
47 __asm__(
48         ".text                  \n"
49         __ALIGN_STR "\n"
50         "pnp_bios_callfunc:\n"
51         "       pushl %edx      \n"
52         "       pushl %ecx      \n"
53         "       pushl %ebx      \n"
54         "       pushl %eax      \n"
55         "       lcallw *pnp_bios_callpoint\n"
56         "       addl $16, %esp  \n"
57         "       lret            \n"
58         ".previous              \n"
59 );
60
61 #define Q2_SET_SEL(cpu, selname, address, size) \
62 do { \
63 struct desc_struct *gdt = get_cpu_gdt_table((cpu)); \
64 set_base(gdt[(selname) >> 3], (u32)(address)); \
65 set_limit(gdt[(selname) >> 3], size); \
66 } while(0)
67
68 static struct desc_struct bad_bios_desc = { 0, 0x00409200 };
69
70 /*
71  * At some point we want to use this stack frame pointer to unwind
72  * after PnP BIOS oopses.
73  */
74
75 u32 pnp_bios_fault_esp;
76 u32 pnp_bios_fault_eip;
77 u32 pnp_bios_is_utter_crap = 0;
78
79 static spinlock_t pnp_bios_lock;
80
81
82 /*
83  * Support Functions
84  */
85
86 static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3,
87                                 u16 arg4, u16 arg5, u16 arg6, u16 arg7,
88                                 void *ts1_base, u32 ts1_size,
89                                 void *ts2_base, u32 ts2_size)
90 {
91         unsigned long flags;
92         u16 status;
93         struct desc_struct save_desc_40;
94         int cpu;
95
96         /*
97          * PnP BIOSes are generally not terribly re-entrant.
98          * Also, don't rely on them to save everything correctly.
99          */
100         if(pnp_bios_is_utter_crap)
101                 return PNP_FUNCTION_NOT_SUPPORTED;
102
103         cpu = get_cpu();
104         save_desc_40 = get_cpu_gdt_table(cpu)[0x40 / 8];
105         get_cpu_gdt_table(cpu)[0x40 / 8] = bad_bios_desc;
106
107         /* On some boxes IRQ's during PnP BIOS calls are deadly.  */
108         spin_lock_irqsave(&pnp_bios_lock, flags);
109
110         /* The lock prevents us bouncing CPU here */
111         if (ts1_size)
112                 Q2_SET_SEL(smp_processor_id(), PNP_TS1, ts1_base, ts1_size);
113         if (ts2_size)
114                 Q2_SET_SEL(smp_processor_id(), PNP_TS2, ts2_base, ts2_size);
115
116         __asm__ __volatile__(
117                 "pushl %%ebp\n\t"
118                 "pushl %%edi\n\t"
119                 "pushl %%esi\n\t"
120                 "pushl %%ds\n\t"
121                 "pushl %%es\n\t"
122                 "pushl %%fs\n\t"
123                 "pushl %%gs\n\t"
124                 "pushfl\n\t"
125                 "movl %%esp, pnp_bios_fault_esp\n\t"
126                 "movl $1f, pnp_bios_fault_eip\n\t"
127                 "lcall %5,%6\n\t"
128                 "1:popfl\n\t"
129                 "popl %%gs\n\t"
130                 "popl %%fs\n\t"
131                 "popl %%es\n\t"
132                 "popl %%ds\n\t"
133                 "popl %%esi\n\t"
134                 "popl %%edi\n\t"
135                 "popl %%ebp\n\t"
136                 : "=a" (status)
137                 : "0" ((func) | (((u32)arg1) << 16)),
138                   "b" ((arg2) | (((u32)arg3) << 16)),
139                   "c" ((arg4) | (((u32)arg5) << 16)),
140                   "d" ((arg6) | (((u32)arg7) << 16)),
141                   "i" (PNP_CS32),
142                   "i" (0)
143                 : "memory"
144         );
145         spin_unlock_irqrestore(&pnp_bios_lock, flags);
146
147         get_cpu_gdt_table(cpu)[0x40 / 8] = save_desc_40;
148         put_cpu();
149
150         /* If we get here and this is set then the PnP BIOS faulted on us. */
151         if(pnp_bios_is_utter_crap)
152         {
153                 printk(KERN_ERR "PnPBIOS: Warning! Your PnP BIOS caused a fatal error. Attempting to continue\n");
154                 printk(KERN_ERR "PnPBIOS: You may need to reboot with the \"pnpbios=off\" option to operate stably\n");
155                 printk(KERN_ERR "PnPBIOS: Check with your vendor for an updated BIOS\n");
156         }
157
158         return status;
159 }
160
161 void pnpbios_print_status(const char * module, u16 status)
162 {
163         switch(status) {
164         case PNP_SUCCESS:
165                 printk(KERN_ERR "PnPBIOS: %s: function successful\n", module);
166                 break;
167         case PNP_NOT_SET_STATICALLY:
168                 printk(KERN_ERR "PnPBIOS: %s: unable to set static resources\n", module);
169                 break;
170         case PNP_UNKNOWN_FUNCTION:
171                 printk(KERN_ERR "PnPBIOS: %s: invalid function number passed\n", module);
172                 break;
173         case PNP_FUNCTION_NOT_SUPPORTED:
174                 printk(KERN_ERR "PnPBIOS: %s: function not supported on this system\n", module);
175                 break;
176         case PNP_INVALID_HANDLE:
177                 printk(KERN_ERR "PnPBIOS: %s: invalid handle\n", module);
178                 break;
179         case PNP_BAD_PARAMETER:
180                 printk(KERN_ERR "PnPBIOS: %s: invalid parameters were passed\n", module);
181                 break;
182         case PNP_SET_FAILED:
183                 printk(KERN_ERR "PnPBIOS: %s: unable to set resources\n", module);
184                 break;
185         case PNP_EVENTS_NOT_PENDING:
186                 printk(KERN_ERR "PnPBIOS: %s: no events are pending\n", module);
187                 break;
188         case PNP_SYSTEM_NOT_DOCKED:
189                 printk(KERN_ERR "PnPBIOS: %s: the system is not docked\n", module);
190                 break;
191         case PNP_NO_ISA_PNP_CARDS:
192                 printk(KERN_ERR "PnPBIOS: %s: no isapnp cards are installed on this system\n", module);
193                 break;
194         case PNP_UNABLE_TO_DETERMINE_DOCK_CAPABILITIES:
195                 printk(KERN_ERR "PnPBIOS: %s: cannot determine the capabilities of the docking station\n", module);
196                 break;
197         case PNP_CONFIG_CHANGE_FAILED_NO_BATTERY:
198                 printk(KERN_ERR "PnPBIOS: %s: unable to undock, the system does not have a battery\n", module);
199                 break;
200         case PNP_CONFIG_CHANGE_FAILED_RESOURCE_CONFLICT:
201                 printk(KERN_ERR "PnPBIOS: %s: could not dock due to resource conflicts\n", module);
202                 break;
203         case PNP_BUFFER_TOO_SMALL:
204                 printk(KERN_ERR "PnPBIOS: %s: the buffer passed is too small\n", module);
205                 break;
206         case PNP_USE_ESCD_SUPPORT:
207                 printk(KERN_ERR "PnPBIOS: %s: use ESCD instead\n", module);
208                 break;
209         case PNP_MESSAGE_NOT_SUPPORTED:
210                 printk(KERN_ERR "PnPBIOS: %s: the message is unsupported\n", module);
211                 break;
212         case PNP_HARDWARE_ERROR:
213                 printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n", module);
214                 break;
215         default:
216                 printk(KERN_ERR "PnPBIOS: %s: unexpected status 0x%x\n", module, status);
217                 break;
218         }
219 }
220
221
222 /*
223  * PnP BIOS Low Level Calls
224  */
225
226 #define PNP_GET_NUM_SYS_DEV_NODES               0x00
227 #define PNP_GET_SYS_DEV_NODE                    0x01
228 #define PNP_SET_SYS_DEV_NODE                    0x02
229 #define PNP_GET_EVENT                           0x03
230 #define PNP_SEND_MESSAGE                        0x04
231 #define PNP_GET_DOCKING_STATION_INFORMATION     0x05
232 #define PNP_SET_STATIC_ALLOCED_RES_INFO         0x09
233 #define PNP_GET_STATIC_ALLOCED_RES_INFO         0x0a
234 #define PNP_GET_APM_ID_TABLE                    0x0b
235 #define PNP_GET_PNP_ISA_CONFIG_STRUC            0x40
236 #define PNP_GET_ESCD_INFO                       0x41
237 #define PNP_READ_ESCD                           0x42
238 #define PNP_WRITE_ESCD                          0x43
239
240 /*
241  * Call PnP BIOS with function 0x00, "get number of system device nodes"
242  */
243 static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
244 {
245         u16 status;
246         if (!pnp_bios_present())
247                 return PNP_FUNCTION_NOT_SUPPORTED;
248         status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, PNP_DS, 0, 0,
249                                data, sizeof(struct pnp_dev_node_info), NULL, 0);
250         data->no_nodes &= 0xff;
251         return status;
252 }
253
254 int pnp_bios_dev_node_info(struct pnp_dev_node_info *data)
255 {
256         int status = __pnp_bios_dev_node_info( data );
257         if ( status )
258                 pnpbios_print_status( "dev_node_info", status );
259         return status;
260 }
261
262 /*
263  * Note that some PnP BIOSes (e.g., on Sony Vaio laptops) die a horrible
264  * death if they are asked to access the "current" configuration.
265  * Therefore, if it's a matter of indifference, it's better to call
266  * get_dev_node() and set_dev_node() with boot=1 rather than with boot=0.
267  */
268
269 /* 
270  * Call PnP BIOS with function 0x01, "get system device node"
271  * Input: *nodenum = desired node,
272  *        boot = whether to get nonvolatile boot (!=0)
273  *               or volatile current (0) config
274  * Output: *nodenum=next node or 0xff if no more nodes
275  */
276 static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
277 {
278         u16 status;
279         u16 tmp_nodenum;
280         if (!pnp_bios_present())
281                 return PNP_FUNCTION_NOT_SUPPORTED;
282         if ( !boot && pnpbios_dont_use_current_config )
283                 return PNP_FUNCTION_NOT_SUPPORTED;
284         tmp_nodenum = *nodenum;
285         status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, boot ? 2 : 1, PNP_DS, 0,
286                                &tmp_nodenum, sizeof(tmp_nodenum), data, 65536);
287         *nodenum = tmp_nodenum;
288         return status;
289 }
290
291 int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data)
292 {
293         int status;
294         status =  __pnp_bios_get_dev_node( nodenum, boot, data );
295         if ( status )
296                 pnpbios_print_status( "get_dev_node", status );
297         return status;
298 }
299
300
301 /*
302  * Call PnP BIOS with function 0x02, "set system device node"
303  * Input: *nodenum = desired node, 
304  *        boot = whether to set nonvolatile boot (!=0)
305  *               or volatile current (0) config
306  */
307 static int __pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
308 {
309         u16 status;
310         if (!pnp_bios_present())
311                 return PNP_FUNCTION_NOT_SUPPORTED;
312         if ( !boot && pnpbios_dont_use_current_config )
313                 return PNP_FUNCTION_NOT_SUPPORTED;
314         status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, boot ? 2 : 1, PNP_DS, 0, 0,
315                                data, 65536, NULL, 0);
316         return status;
317 }
318
319 int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data)
320 {
321         int status;
322         status =  __pnp_bios_set_dev_node( nodenum, boot, data );
323         if ( status ) {
324                 pnpbios_print_status( "set_dev_node", status );
325                 return status;
326         }
327         if ( !boot ) { /* Update devlist */
328                 status =  pnp_bios_get_dev_node( &nodenum, boot, data );
329                 if ( status )
330                         return status;
331         }
332         return status;
333 }
334
335 #if needed
336 /*
337  * Call PnP BIOS with function 0x03, "get event"
338  */
339 static int pnp_bios_get_event(u16 *event)
340 {
341         u16 status;
342         if (!pnp_bios_present())
343                 return PNP_FUNCTION_NOT_SUPPORTED;
344         status = call_pnp_bios(PNP_GET_EVENT, 0, PNP_TS1, PNP_DS, 0, 0 ,0 ,0,
345                                event, sizeof(u16), NULL, 0);
346         return status;
347 }
348 #endif
349
350 #if needed
351 /*
352  * Call PnP BIOS with function 0x04, "send message"
353  */
354 static int pnp_bios_send_message(u16 message)
355 {
356         u16 status;
357         if (!pnp_bios_present())
358                 return PNP_FUNCTION_NOT_SUPPORTED;
359         status = call_pnp_bios(PNP_SEND_MESSAGE, message, PNP_DS, 0, 0, 0, 0, 0, 0, 0, 0, 0);
360         return status;
361 }
362 #endif
363
364 /*
365  * Call PnP BIOS with function 0x05, "get docking station information"
366  */
367 int pnp_bios_dock_station_info(struct pnp_docking_station_info *data)
368 {
369         u16 status;
370         if (!pnp_bios_present())
371                 return PNP_FUNCTION_NOT_SUPPORTED;
372         status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
373                                data, sizeof(struct pnp_docking_station_info), NULL, 0);
374         return status;
375 }
376
377 #if needed
378 /*
379  * Call PnP BIOS with function 0x09, "set statically allocated resource
380  * information"
381  */
382 static int pnp_bios_set_stat_res(char *info)
383 {
384         u16 status;
385         if (!pnp_bios_present())
386                 return PNP_FUNCTION_NOT_SUPPORTED;
387         status = call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
388                                info, *((u16 *) info), 0, 0);
389         return status;
390 }
391 #endif
392
393 /*
394  * Call PnP BIOS with function 0x0a, "get statically allocated resource
395  * information"
396  */
397 static int __pnp_bios_get_stat_res(char *info)
398 {
399         u16 status;
400         if (!pnp_bios_present())
401                 return PNP_FUNCTION_NOT_SUPPORTED;
402         status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
403                                info, 65536, NULL, 0);
404         return status;
405 }
406
407 int pnp_bios_get_stat_res(char *info)
408 {
409         int status;
410         status = __pnp_bios_get_stat_res( info );
411         if ( status )
412                 pnpbios_print_status( "get_stat_res", status );
413         return status;
414 }
415
416 #if needed
417 /*
418  * Call PnP BIOS with function 0x0b, "get APM id table"
419  */
420 static int pnp_bios_apm_id_table(char *table, u16 *size)
421 {
422         u16 status;
423         if (!pnp_bios_present())
424                 return PNP_FUNCTION_NOT_SUPPORTED;
425         status = call_pnp_bios(PNP_GET_APM_ID_TABLE, 0, PNP_TS2, 0, PNP_TS1, PNP_DS, 0, 0,
426                                table, *size, size, sizeof(u16));
427         return status;
428 }
429 #endif
430
431 /*
432  * Call PnP BIOS with function 0x40, "get isa pnp configuration structure"
433  */
434 static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
435 {
436         u16 status;
437         if (!pnp_bios_present())
438                 return PNP_FUNCTION_NOT_SUPPORTED;
439         status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, 0, 0, 0,
440                                data, sizeof(struct pnp_isa_config_struc), NULL, 0);
441         return status;
442 }
443
444 int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data)
445 {
446         int status;
447         status = __pnp_bios_isapnp_config( data );
448         if ( status )
449                 pnpbios_print_status( "isapnp_config", status );
450         return status;
451 }
452
453 /*
454  * Call PnP BIOS with function 0x41, "get ESCD info"
455  */
456 static int __pnp_bios_escd_info(struct escd_info_struc *data)
457 {
458         u16 status;
459         if (!pnp_bios_present())
460                 return ESCD_FUNCTION_NOT_SUPPORTED;
461         status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, PNP_DS,
462                                data, sizeof(struct escd_info_struc), NULL, 0);
463         return status;
464 }
465
466 int pnp_bios_escd_info(struct escd_info_struc *data)
467 {
468         int status;
469         status = __pnp_bios_escd_info( data );
470         if ( status )
471                 pnpbios_print_status( "escd_info", status );
472         return status;
473 }
474
475 /*
476  * Call PnP BIOS function 0x42, "read ESCD"
477  * nvram_base is determined by calling escd_info
478  */
479 static int __pnp_bios_read_escd(char *data, u32 nvram_base)
480 {
481         u16 status;
482         if (!pnp_bios_present())
483                 return ESCD_FUNCTION_NOT_SUPPORTED;
484         status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
485                                data, 65536, __va(nvram_base), 65536);
486         return status;
487 }
488
489 int pnp_bios_read_escd(char *data, u32 nvram_base)
490 {
491         int status;
492         status = __pnp_bios_read_escd( data, nvram_base );
493         if ( status )
494                 pnpbios_print_status( "read_escd", status );
495         return status;
496 }
497
498 #if needed
499 /*
500  * Call PnP BIOS function 0x43, "write ESCD"
501  */
502 static int pnp_bios_write_escd(char *data, u32 nvram_base)
503 {
504         u16 status;
505         if (!pnp_bios_present())
506                 return ESCD_FUNCTION_NOT_SUPPORTED;
507         status = call_pnp_bios(PNP_WRITE_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0,
508                                data, 65536, __va(nvram_base), 65536);
509         return status;
510 }
511 #endif
512
513
514 /*
515  * Initialization
516  */
517
518 void pnpbios_calls_init(union pnp_bios_install_struct *header)
519 {
520         int i;
521         spin_lock_init(&pnp_bios_lock);
522         pnp_bios_callpoint.offset = header->fields.pm16offset;
523         pnp_bios_callpoint.segment = PNP_CS16;
524
525         set_base(bad_bios_desc, __va((unsigned long)0x40 << 4));
526         _set_limit((char *)&bad_bios_desc, 4095 - (0x40 << 4));
527         for (i = 0; i < NR_CPUS; i++) {
528                 struct desc_struct *gdt = get_cpu_gdt_table(i);
529                 if (!gdt)
530                         continue;
531                 set_base(gdt[GDT_ENTRY_PNPBIOS_CS32], &pnp_bios_callfunc);
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         }
535 }