video-bios.c 2.8 KB

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