diff options
Diffstat (limited to 'drivers/pnp/pnpbios/bioscalls.c')
-rw-r--r-- | drivers/pnp/pnpbios/bioscalls.c | 161 |
1 files changed, 44 insertions, 117 deletions
diff --git a/drivers/pnp/pnpbios/bioscalls.c b/drivers/pnp/pnpbios/bioscalls.c index d546f79d4d3b..5dba68fe33f5 100644 --- a/drivers/pnp/pnpbios/bioscalls.c +++ b/drivers/pnp/pnpbios/bioscalls.c | |||
@@ -1,6 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * bioscalls.c - the lowlevel layer of the PnPBIOS driver | 2 | * bioscalls.c - the lowlevel layer of the PnPBIOS driver |
3 | * | ||
4 | */ | 3 | */ |
5 | 4 | ||
6 | #include <linux/types.h> | 5 | #include <linux/types.h> |
@@ -52,7 +51,8 @@ __asm__(".text \n" | |||
52 | " pushl %eax \n" | 51 | " pushl %eax \n" |
53 | " lcallw *pnp_bios_callpoint\n" | 52 | " lcallw *pnp_bios_callpoint\n" |
54 | " addl $16, %esp \n" | 53 | " addl $16, %esp \n" |
55 | " lret \n" ".previous \n"); | 54 | " lret \n" |
55 | ".previous \n"); | ||
56 | 56 | ||
57 | #define Q2_SET_SEL(cpu, selname, address, size) \ | 57 | #define Q2_SET_SEL(cpu, selname, address, size) \ |
58 | do { \ | 58 | do { \ |
@@ -125,7 +125,8 @@ static inline u16 call_pnp_bios(u16 func, u16 arg1, u16 arg2, u16 arg3, | |||
125 | "popl %%es\n\t" | 125 | "popl %%es\n\t" |
126 | "popl %%ds\n\t" | 126 | "popl %%ds\n\t" |
127 | "popl %%esi\n\t" | 127 | "popl %%esi\n\t" |
128 | "popl %%edi\n\t" "popl %%ebp\n\t":"=a"(status) | 128 | "popl %%edi\n\t" |
129 | "popl %%ebp\n\t":"=a"(status) | ||
129 | :"0"((func) | (((u32) arg1) << 16)), | 130 | :"0"((func) | (((u32) arg1) << 16)), |
130 | "b"((arg2) | (((u32) arg3) << 16)), | 131 | "b"((arg2) | (((u32) arg3) << 16)), |
131 | "c"((arg4) | (((u32) arg5) << 16)), | 132 | "c"((arg4) | (((u32) arg5) << 16)), |
@@ -253,12 +254,12 @@ void pnpbios_print_status(const char *module, u16 status) | |||
253 | static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data) | 254 | static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data) |
254 | { | 255 | { |
255 | u16 status; | 256 | u16 status; |
257 | |||
256 | if (!pnp_bios_present()) | 258 | if (!pnp_bios_present()) |
257 | return PNP_FUNCTION_NOT_SUPPORTED; | 259 | return PNP_FUNCTION_NOT_SUPPORTED; |
258 | status = | 260 | status = call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, |
259 | call_pnp_bios(PNP_GET_NUM_SYS_DEV_NODES, 0, PNP_TS1, 2, PNP_TS1, | 261 | PNP_TS1, PNP_DS, 0, 0, data, |
260 | PNP_DS, 0, 0, data, sizeof(struct pnp_dev_node_info), | 262 | sizeof(struct pnp_dev_node_info), NULL, 0); |
261 | NULL, 0); | ||
262 | data->no_nodes &= 0xff; | 263 | data->no_nodes &= 0xff; |
263 | return status; | 264 | return status; |
264 | } | 265 | } |
@@ -266,6 +267,7 @@ static int __pnp_bios_dev_node_info(struct pnp_dev_node_info *data) | |||
266 | int pnp_bios_dev_node_info(struct pnp_dev_node_info *data) | 267 | int pnp_bios_dev_node_info(struct pnp_dev_node_info *data) |
267 | { | 268 | { |
268 | int status = __pnp_bios_dev_node_info(data); | 269 | int status = __pnp_bios_dev_node_info(data); |
270 | |||
269 | if (status) | 271 | if (status) |
270 | pnpbios_print_status("dev_node_info", status); | 272 | pnpbios_print_status("dev_node_info", status); |
271 | return status; | 273 | return status; |
@@ -285,27 +287,28 @@ int pnp_bios_dev_node_info(struct pnp_dev_node_info *data) | |||
285 | * or volatile current (0) config | 287 | * or volatile current (0) config |
286 | * Output: *nodenum=next node or 0xff if no more nodes | 288 | * Output: *nodenum=next node or 0xff if no more nodes |
287 | */ | 289 | */ |
288 | static int __pnp_bios_get_dev_node(u8 * nodenum, char boot, | 290 | static int __pnp_bios_get_dev_node(u8 *nodenum, char boot, |
289 | struct pnp_bios_node *data) | 291 | struct pnp_bios_node *data) |
290 | { | 292 | { |
291 | u16 status; | 293 | u16 status; |
292 | u16 tmp_nodenum; | 294 | u16 tmp_nodenum; |
295 | |||
293 | if (!pnp_bios_present()) | 296 | if (!pnp_bios_present()) |
294 | return PNP_FUNCTION_NOT_SUPPORTED; | 297 | return PNP_FUNCTION_NOT_SUPPORTED; |
295 | if (!boot && pnpbios_dont_use_current_config) | 298 | if (!boot && pnpbios_dont_use_current_config) |
296 | return PNP_FUNCTION_NOT_SUPPORTED; | 299 | return PNP_FUNCTION_NOT_SUPPORTED; |
297 | tmp_nodenum = *nodenum; | 300 | tmp_nodenum = *nodenum; |
298 | status = | 301 | status = call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, |
299 | call_pnp_bios(PNP_GET_SYS_DEV_NODE, 0, PNP_TS1, 0, PNP_TS2, | 302 | boot ? 2 : 1, PNP_DS, 0, &tmp_nodenum, |
300 | boot ? 2 : 1, PNP_DS, 0, &tmp_nodenum, | 303 | sizeof(tmp_nodenum), data, 65536); |
301 | sizeof(tmp_nodenum), data, 65536); | ||
302 | *nodenum = tmp_nodenum; | 304 | *nodenum = tmp_nodenum; |
303 | return status; | 305 | return status; |
304 | } | 306 | } |
305 | 307 | ||
306 | int pnp_bios_get_dev_node(u8 * nodenum, char boot, struct pnp_bios_node *data) | 308 | int pnp_bios_get_dev_node(u8 *nodenum, char boot, struct pnp_bios_node *data) |
307 | { | 309 | { |
308 | int status; | 310 | int status; |
311 | |||
309 | status = __pnp_bios_get_dev_node(nodenum, boot, data); | 312 | status = __pnp_bios_get_dev_node(nodenum, boot, data); |
310 | if (status) | 313 | if (status) |
311 | pnpbios_print_status("get_dev_node", status); | 314 | pnpbios_print_status("get_dev_node", status); |
@@ -322,19 +325,21 @@ static int __pnp_bios_set_dev_node(u8 nodenum, char boot, | |||
322 | struct pnp_bios_node *data) | 325 | struct pnp_bios_node *data) |
323 | { | 326 | { |
324 | u16 status; | 327 | u16 status; |
328 | |||
325 | if (!pnp_bios_present()) | 329 | if (!pnp_bios_present()) |
326 | return PNP_FUNCTION_NOT_SUPPORTED; | 330 | return PNP_FUNCTION_NOT_SUPPORTED; |
327 | if (!boot && pnpbios_dont_use_current_config) | 331 | if (!boot && pnpbios_dont_use_current_config) |
328 | return PNP_FUNCTION_NOT_SUPPORTED; | 332 | return PNP_FUNCTION_NOT_SUPPORTED; |
329 | status = | 333 | status = call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, |
330 | call_pnp_bios(PNP_SET_SYS_DEV_NODE, nodenum, 0, PNP_TS1, | 334 | boot ? 2 : 1, PNP_DS, 0, 0, data, 65536, NULL, |
331 | boot ? 2 : 1, PNP_DS, 0, 0, data, 65536, NULL, 0); | 335 | 0); |
332 | return status; | 336 | return status; |
333 | } | 337 | } |
334 | 338 | ||
335 | int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data) | 339 | int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data) |
336 | { | 340 | { |
337 | int status; | 341 | int status; |
342 | |||
338 | status = __pnp_bios_set_dev_node(nodenum, boot, data); | 343 | status = __pnp_bios_set_dev_node(nodenum, boot, data); |
339 | if (status) { | 344 | if (status) { |
340 | pnpbios_print_status("set_dev_node", status); | 345 | pnpbios_print_status("set_dev_node", status); |
@@ -348,68 +353,21 @@ int pnp_bios_set_dev_node(u8 nodenum, char boot, struct pnp_bios_node *data) | |||
348 | return status; | 353 | return status; |
349 | } | 354 | } |
350 | 355 | ||
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 | /* | 356 | /* |
383 | * Call PnP BIOS with function 0x05, "get docking station information" | 357 | * Call PnP BIOS with function 0x05, "get docking station information" |
384 | */ | 358 | */ |
385 | int pnp_bios_dock_station_info(struct pnp_docking_station_info *data) | 359 | int pnp_bios_dock_station_info(struct pnp_docking_station_info *data) |
386 | { | 360 | { |
387 | u16 status; | 361 | 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 | 362 | ||
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()) | 363 | if (!pnp_bios_present()) |
406 | return PNP_FUNCTION_NOT_SUPPORTED; | 364 | return PNP_FUNCTION_NOT_SUPPORTED; |
407 | status = | 365 | status = call_pnp_bios(PNP_GET_DOCKING_STATION_INFORMATION, 0, PNP_TS1, |
408 | call_pnp_bios(PNP_SET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, | 366 | PNP_DS, 0, 0, 0, 0, data, |
409 | 0, 0, 0, 0, info, *((u16 *) info), 0, 0); | 367 | sizeof(struct pnp_docking_station_info), NULL, |
368 | 0); | ||
410 | return status; | 369 | return status; |
411 | } | 370 | } |
412 | #endif | ||
413 | 371 | ||
414 | /* | 372 | /* |
415 | * Call PnP BIOS with function 0x0a, "get statically allocated resource | 373 | * Call PnP BIOS with function 0x0a, "get statically allocated resource |
@@ -418,57 +376,43 @@ static int pnp_bios_set_stat_res(char *info) | |||
418 | static int __pnp_bios_get_stat_res(char *info) | 376 | static int __pnp_bios_get_stat_res(char *info) |
419 | { | 377 | { |
420 | u16 status; | 378 | u16 status; |
379 | |||
421 | if (!pnp_bios_present()) | 380 | if (!pnp_bios_present()) |
422 | return PNP_FUNCTION_NOT_SUPPORTED; | 381 | return PNP_FUNCTION_NOT_SUPPORTED; |
423 | status = | 382 | status = call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, |
424 | call_pnp_bios(PNP_GET_STATIC_ALLOCED_RES_INFO, 0, PNP_TS1, PNP_DS, | 383 | PNP_DS, 0, 0, 0, 0, info, 65536, NULL, 0); |
425 | 0, 0, 0, 0, info, 65536, NULL, 0); | ||
426 | return status; | 384 | return status; |
427 | } | 385 | } |
428 | 386 | ||
429 | int pnp_bios_get_stat_res(char *info) | 387 | int pnp_bios_get_stat_res(char *info) |
430 | { | 388 | { |
431 | int status; | 389 | int status; |
390 | |||
432 | status = __pnp_bios_get_stat_res(info); | 391 | status = __pnp_bios_get_stat_res(info); |
433 | if (status) | 392 | if (status) |
434 | pnpbios_print_status("get_stat_res", status); | 393 | pnpbios_print_status("get_stat_res", status); |
435 | return status; | 394 | return status; |
436 | } | 395 | } |
437 | 396 | ||
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 | /* | 397 | /* |
455 | * Call PnP BIOS with function 0x40, "get isa pnp configuration structure" | 398 | * Call PnP BIOS with function 0x40, "get isa pnp configuration structure" |
456 | */ | 399 | */ |
457 | static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) | 400 | static int __pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) |
458 | { | 401 | { |
459 | u16 status; | 402 | u16 status; |
403 | |||
460 | if (!pnp_bios_present()) | 404 | if (!pnp_bios_present()) |
461 | return PNP_FUNCTION_NOT_SUPPORTED; | 405 | return PNP_FUNCTION_NOT_SUPPORTED; |
462 | status = | 406 | status = call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, |
463 | call_pnp_bios(PNP_GET_PNP_ISA_CONFIG_STRUC, 0, PNP_TS1, PNP_DS, 0, | 407 | 0, 0, 0, 0, data, |
464 | 0, 0, 0, data, sizeof(struct pnp_isa_config_struc), | 408 | sizeof(struct pnp_isa_config_struc), NULL, 0); |
465 | NULL, 0); | ||
466 | return status; | 409 | return status; |
467 | } | 410 | } |
468 | 411 | ||
469 | int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) | 412 | int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) |
470 | { | 413 | { |
471 | int status; | 414 | int status; |
415 | |||
472 | status = __pnp_bios_isapnp_config(data); | 416 | status = __pnp_bios_isapnp_config(data); |
473 | if (status) | 417 | if (status) |
474 | pnpbios_print_status("isapnp_config", status); | 418 | pnpbios_print_status("isapnp_config", status); |
@@ -481,18 +425,19 @@ int pnp_bios_isapnp_config(struct pnp_isa_config_struc *data) | |||
481 | static int __pnp_bios_escd_info(struct escd_info_struc *data) | 425 | static int __pnp_bios_escd_info(struct escd_info_struc *data) |
482 | { | 426 | { |
483 | u16 status; | 427 | u16 status; |
428 | |||
484 | if (!pnp_bios_present()) | 429 | if (!pnp_bios_present()) |
485 | return ESCD_FUNCTION_NOT_SUPPORTED; | 430 | return ESCD_FUNCTION_NOT_SUPPORTED; |
486 | status = | 431 | status = call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, |
487 | call_pnp_bios(PNP_GET_ESCD_INFO, 0, PNP_TS1, 2, PNP_TS1, 4, PNP_TS1, | 432 | PNP_TS1, PNP_DS, data, |
488 | PNP_DS, data, sizeof(struct escd_info_struc), NULL, | 433 | sizeof(struct escd_info_struc), NULL, 0); |
489 | 0); | ||
490 | return status; | 434 | return status; |
491 | } | 435 | } |
492 | 436 | ||
493 | int pnp_bios_escd_info(struct escd_info_struc *data) | 437 | int pnp_bios_escd_info(struct escd_info_struc *data) |
494 | { | 438 | { |
495 | int status; | 439 | int status; |
440 | |||
496 | status = __pnp_bios_escd_info(data); | 441 | status = __pnp_bios_escd_info(data); |
497 | if (status) | 442 | if (status) |
498 | pnpbios_print_status("escd_info", status); | 443 | pnpbios_print_status("escd_info", status); |
@@ -506,46 +451,28 @@ int pnp_bios_escd_info(struct escd_info_struc *data) | |||
506 | static int __pnp_bios_read_escd(char *data, u32 nvram_base) | 451 | static int __pnp_bios_read_escd(char *data, u32 nvram_base) |
507 | { | 452 | { |
508 | u16 status; | 453 | u16 status; |
454 | |||
509 | if (!pnp_bios_present()) | 455 | if (!pnp_bios_present()) |
510 | return ESCD_FUNCTION_NOT_SUPPORTED; | 456 | return ESCD_FUNCTION_NOT_SUPPORTED; |
511 | status = | 457 | status = call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, |
512 | call_pnp_bios(PNP_READ_ESCD, 0, PNP_TS1, PNP_TS2, PNP_DS, 0, 0, 0, | 458 | 0, data, 65536, __va(nvram_base), 65536); |
513 | data, 65536, __va(nvram_base), 65536); | ||
514 | return status; | 459 | return status; |
515 | } | 460 | } |
516 | 461 | ||
517 | int pnp_bios_read_escd(char *data, u32 nvram_base) | 462 | int pnp_bios_read_escd(char *data, u32 nvram_base) |
518 | { | 463 | { |
519 | int status; | 464 | int status; |
465 | |||
520 | status = __pnp_bios_read_escd(data, nvram_base); | 466 | status = __pnp_bios_read_escd(data, nvram_base); |
521 | if (status) | 467 | if (status) |
522 | pnpbios_print_status("read_escd", status); | 468 | pnpbios_print_status("read_escd", status); |
523 | return status; | 469 | return status; |
524 | } | 470 | } |
525 | 471 | ||
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) | 472 | void pnpbios_calls_init(union pnp_bios_install_struct *header) |
547 | { | 473 | { |
548 | int i; | 474 | int i; |
475 | |||
549 | spin_lock_init(&pnp_bios_lock); | 476 | spin_lock_init(&pnp_bios_lock); |
550 | pnp_bios_callpoint.offset = header->fields.pm16offset; | 477 | pnp_bios_callpoint.offset = header->fields.pm16offset; |
551 | pnp_bios_callpoint.segment = PNP_CS16; | 478 | pnp_bios_callpoint.segment = PNP_CS16; |