video-bios.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /* -*- linux-c -*- ------------------------------------------------------- *
  2. *
  3. * Copyright (C) 1991, 1992 Linus Torvalds
  4. * Copyright 2007 rPath, Inc. - All Rights Reserved
  5. *
  6. * This file is part of the Linux kernel, and is made available under
  7. * the terms of the GNU General Public License version 2.
  8. *
  9. * ----------------------------------------------------------------------- */
  10. /*
  11. * arch/i386/boot/video-bios.c
  12. *
  13. * Standard video BIOS modes
  14. *
  15. * We have two options for this; silent and scanned.
  16. */
  17. #include "boot.h"
  18. #include "video.h"
  19. __videocard video_bios;
  20. /* Set a conventional BIOS mode */
  21. static int set_bios_mode(u8 mode);
  22. static int bios_set_mode(struct mode_info *mi)
  23. {
  24. return set_bios_mode(mi->mode - VIDEO_FIRST_BIOS);
  25. }
  26. static int set_bios_mode(u8 mode)
  27. {
  28. u16 ax;
  29. u8 new_mode;
  30. ax = mode; /* AH=0x00 Set Video Mode */
  31. asm volatile(INT10
  32. : "+a" (ax)
  33. : : "ebx", "ecx", "edx", "esi", "edi");
  34. ax = 0x0f00; /* Get Current Video Mode */
  35. asm volatile(INT10
  36. : "+a" (ax)
  37. : : "ebx", "ecx", "edx", "esi", "edi");
  38. do_restore = 1; /* Assume video contents were lost */
  39. new_mode = ax & 0x7f; /* Not all BIOSes are clean with the top bit */
  40. if (new_mode == mode)
  41. return 0; /* Mode change OK */
  42. #ifndef _WAKEUP
  43. if (new_mode != boot_params.screen_info.orig_video_mode) {
  44. /* Mode setting failed, but we didn't end up where we
  45. started. That's bad. Try to revert to the original
  46. video mode. */
  47. ax = boot_params.screen_info.orig_video_mode;
  48. asm volatile(INT10
  49. : "+a" (ax)
  50. : : "ebx", "ecx", "edx", "esi", "edi");
  51. }
  52. #endif
  53. return -1;
  54. }
  55. static int bios_probe(void)
  56. {
  57. u8 mode;
  58. #ifdef _WAKEUP
  59. u8 saved_mode = 0x03;
  60. #else
  61. u8 saved_mode = boot_params.screen_info.orig_video_mode;
  62. #endif
  63. u16 crtc;
  64. struct mode_info *mi;
  65. int nmodes = 0;
  66. if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
  67. return 0;
  68. set_fs(0);
  69. crtc = vga_crtc();
  70. video_bios.modes = GET_HEAP(struct mode_info, 0);
  71. for (mode = 0x14; mode <= 0x7f; mode++) {
  72. if (!heap_free(sizeof(struct mode_info)))
  73. break;
  74. if (mode_defined(VIDEO_FIRST_BIOS+mode))
  75. continue;
  76. if (set_bios_mode(mode))
  77. continue;
  78. /* Try to verify that it's a text mode. */
  79. /* Attribute Controller: make graphics controller disabled */
  80. if (in_idx(0x3c0, 0x10) & 0x01)
  81. continue;
  82. /* Graphics Controller: verify Alpha addressing enabled */
  83. if (in_idx(0x3ce, 0x06) & 0x01)
  84. continue;
  85. /* CRTC cursor location low should be zero(?) */
  86. if (in_idx(crtc, 0x0f))
  87. continue;
  88. mi = GET_HEAP(struct mode_info, 1);
  89. mi->mode = VIDEO_FIRST_BIOS+mode;
  90. mi->depth = 0; /* text */
  91. mi->x = rdfs16(0x44a);
  92. mi->y = rdfs8(0x484)+1;
  93. nmodes++;
  94. }
  95. set_bios_mode(saved_mode);
  96. return nmodes;
  97. }
  98. __videocard video_bios =
  99. {
  100. .card_name = "BIOS",
  101. .probe = bios_probe,
  102. .set_mode = bios_set_mode,
  103. .unsafe = 1,
  104. .xmode_first = VIDEO_FIRST_BIOS,
  105. .xmode_n = 0x80,
  106. };