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