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