video-bios.c 2.8 KB

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