video-bios.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. if (new_mode != boot_params.screen_info.orig_video_mode) {
  43. /* Mode setting failed, but we didn't end up where we
  44. started. That's bad. Try to revert to the original
  45. video mode. */
  46. ax = boot_params.screen_info.orig_video_mode;
  47. asm volatile(INT10
  48. : "+a" (ax)
  49. : : "ebx", "ecx", "edx", "esi", "edi");
  50. }
  51. return -1;
  52. }
  53. static int bios_probe(void)
  54. {
  55. u8 mode;
  56. u8 saved_mode = boot_params.screen_info.orig_video_mode;
  57. u16 crtc;
  58. struct mode_info *mi;
  59. int nmodes = 0;
  60. if (adapter != ADAPTER_EGA && adapter != ADAPTER_VGA)
  61. return 0;
  62. set_fs(0);
  63. crtc = vga_crtc();
  64. video_bios.modes = GET_HEAP(struct mode_info, 0);
  65. for (mode = 0x14; mode <= 0x7f; mode++) {
  66. if (heap_free() < sizeof(struct mode_info))
  67. break;
  68. if (mode_defined(VIDEO_FIRST_BIOS+mode))
  69. continue;
  70. if (set_bios_mode(mode))
  71. continue;
  72. /* Try to verify that it's a text mode. */
  73. /* Attribute Controller: make graphics controller disabled */
  74. if (in_idx(0x3c0, 0x10) & 0x01)
  75. continue;
  76. /* Graphics Controller: verify Alpha addressing enabled */
  77. if (in_idx(0x3ce, 0x06) & 0x01)
  78. continue;
  79. /* CRTC cursor location low should be zero(?) */
  80. if (in_idx(crtc, 0x0f))
  81. continue;
  82. mi = GET_HEAP(struct mode_info, 1);
  83. mi->mode = VIDEO_FIRST_BIOS+mode;
  84. mi->x = rdfs16(0x44a);
  85. mi->y = rdfs8(0x484)+1;
  86. nmodes++;
  87. }
  88. set_bios_mode(saved_mode);
  89. return nmodes;
  90. }
  91. __videocard video_bios =
  92. {
  93. .card_name = "BIOS (scanned)",
  94. .probe = bios_probe,
  95. .set_mode = bios_set_mode,
  96. .unsafe = 1,
  97. .xmode_first = VIDEO_FIRST_BIOS,
  98. .xmode_n = 0x80,
  99. };