video-bios.c 2.7 KB

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