Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

bios.c 3.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /* Etherboot routines for PCBIOS firmware.
  2. *
  3. * Body of routines taken from old pcbios.S
  4. */
  5. #ifdef PCBIOS
  6. #include "etherboot.h"
  7. #include "realmode.h"
  8. #include "segoff.h"
  9. #define CF ( 1 << 0 )
  10. /**************************************************************************
  11. CURRTICKS - Get Time
  12. Use direct memory access to BIOS variables, longword 0040:006C (ticks
  13. today) and byte 0040:0070 (midnight crossover flag) instead of calling
  14. timeofday BIOS interrupt.
  15. **************************************************************************/
  16. #if defined(CONFIG_TSC_CURRTICKS)
  17. #undef CONFIG_BIOS_CURRTICKS
  18. #else
  19. #define CONFIG_BIOS_CURRTICKS 1
  20. #endif
  21. #if defined(CONFIG_BIOS_CURRTICKS)
  22. unsigned long currticks (void)
  23. {
  24. static uint32_t days = 0;
  25. uint32_t *ticks = VIRTUAL(0x0040,0x006c);
  26. uint8_t *midnight = VIRTUAL(0x0040,0x0070);
  27. /* Re-enable interrupts so that the timer interrupt can occur
  28. */
  29. RM_FRAGMENT(rm_currticks,
  30. "sti\n\t"
  31. "nop\n\t"
  32. "nop\n\t"
  33. "cli\n\t"
  34. );
  35. real_call ( rm_currticks, NULL, NULL );
  36. if ( *midnight ) {
  37. *midnight = 0;
  38. days += 0x1800b0;
  39. }
  40. return ( days + *ticks );
  41. }
  42. #endif /* CONFIG_BIOS_CURRTICKS */
  43. /**************************************************************************
  44. INT15 - Call Interrupt 0x15
  45. **************************************************************************/
  46. int int15 ( int ax )
  47. {
  48. struct {
  49. reg16_t ax;
  50. } PACKED in_stack;
  51. struct {
  52. reg16_t flags;
  53. } PACKED out_stack;
  54. reg16_t ret_ax;
  55. RM_FRAGMENT(rm_int15,
  56. "sti\n\t"
  57. "popw %ax\n\t"
  58. "stc\n\t"
  59. "int $0x15\n\t"
  60. "pushf\n\t"
  61. "cli\n\t"
  62. );
  63. in_stack.ax.word = ax;
  64. ret_ax.word = real_call ( rm_int15, &in_stack, &out_stack );
  65. /* Carry flag clear indicates function not supported */
  66. if ( ! ( out_stack.flags.word & CF ) ) return 0;
  67. return ret_ax.h;
  68. }
  69. #ifdef POWERSAVE
  70. /**************************************************************************
  71. CPU_NAP - Save power by halting the CPU until the next interrupt
  72. **************************************************************************/
  73. void cpu_nap ( void )
  74. {
  75. RM_FRAGMENT(rm_cpu_nap,
  76. "sti\n\t"
  77. "hlt\n\t"
  78. "cli\n\t"
  79. );
  80. real_call ( rm_cpu_nap, NULL, NULL );
  81. }
  82. #endif /* POWERSAVE */
  83. #if (TRY_FLOPPY_FIRST > 0)
  84. /**************************************************************************
  85. DISK_INIT - Initialize the disk system
  86. **************************************************************************/
  87. void disk_init ( void )
  88. {
  89. RM_FRAGMENT(rm_disk_init,
  90. "sti\n\t"
  91. "xorw %ax,%ax\n\t"
  92. "movb $0x80,%dl\n\t"
  93. "int $0x13\n\t"
  94. "cli\n\t"
  95. );
  96. real_call ( rm_disk_init, NULL, NULL );
  97. }
  98. /**************************************************************************
  99. DISK_READ - Read a sector from disk
  100. **************************************************************************/
  101. unsigned int pcbios_disk_read ( int drive, int cylinder, int head, int sector,
  102. char *buf ) {
  103. struct {
  104. reg16_t ax;
  105. reg16_t cx;
  106. reg16_t dx;
  107. segoff_t buffer;
  108. } PACKED in_stack;
  109. struct {
  110. reg16_t flags;
  111. } PACKED out_stack;
  112. reg16_t ret_ax;
  113. RM_FRAGMENT(rm_pcbios_disk_read,
  114. "sti\n\t"
  115. "popw %ax\n\t"
  116. "popw %cx\n\t"
  117. "popw %dx\n\t"
  118. "popw %bx\n\t"
  119. "popw %es\n\t"
  120. "int $0x13\n\t"
  121. "pushfw\n\t"
  122. "cli\n\t"
  123. );
  124. in_stack.ax.h = 2; /* INT 13,2 - Read disk sector */
  125. in_stack.ax.l = 1; /* Read one sector */
  126. in_stack.cx.h = cylinder & 0xff;
  127. in_stack.cx.l = ( ( cylinder >> 8 ) & 0x3 ) | sector;
  128. in_stack.dx.h = head;
  129. in_stack.dx.l = drive;
  130. in_stack.buffer.segment = SEGMENT ( buf );
  131. in_stack.buffer.offset = OFFSET ( buf );
  132. ret_ax.word = real_call ( rm_pcbios_disk_read, &in_stack, &out_stack );
  133. return ( out_stack.flags.word & CF ) ? ret_ax.word : 0;
  134. }
  135. #endif /* TRY_FLOPPY_FIRST */
  136. #endif /* PCBIOS */