]> xenbits.xensource.com Git - seabios.git/commitdiff
Add minimal support for machines without hardware interrupts
authorKevin O'Connor <kevin@koconnor.net>
Mon, 10 Aug 2015 20:14:48 +0000 (16:14 -0400)
committerKevin O'Connor <kevin@koconnor.net>
Mon, 24 Aug 2015 15:02:13 +0000 (11:02 -0400)
Some Chromebooks (with Baytrail CPUs) apparently do not support
routing of legacy interrupts.  This patch adds minimal support for
running SeaBIOS in such an environment.  Even with this patch, it is
known that old operating systems and even some recent bootloaders will
not function without real hardware interrupts.

Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
src/Kconfig
src/clock.c
src/hw/pic.c
src/hw/pic.h
src/hw/timer.c
src/stacks.c
src/util.h

index 56a1b2f432c1f49739c0942a54381cab7308fead..b873cd392964a2c3d3ad9f56320d5120acb4a017 100644 (file)
@@ -209,7 +209,7 @@ menu "Hardware support"
         help
             Support boot from LSI MegaRAID SAS scsi storage.
     config FLOPPY
-        depends on DRIVES
+        depends on DRIVES && HARDWARE_IRQ
         bool "Floppy controller"
         default y
         help
@@ -301,6 +301,7 @@ menu "Hardware support"
             Support parallel ports. This also enables int 17 parallel port calls.
     config RTC_TIMER
         bool "Real Time Clock (RTC) scheduling"
+        depends on HARDWARE_IRQ
         default y
         help
             Support MC146818 Real Time Clock chip timer
@@ -309,6 +310,16 @@ menu "Hardware support"
             Disabling this support does not disable access to the RTC
             cmos registers.
 
+    config HARDWARE_IRQ
+        bool "Hardware interrupts"
+        default y
+        help
+            Program and support hardware interrupts using the i8259
+            programmable interrupt controller (PIC).  This option must
+            be enabled in order to support most boot loaders.  Only
+            disable this option if running on peculiar hardware known
+            not to support irq routing.
+
     config USE_SMM
         depends on QEMU
         bool "System Management Mode (SMM)"
index 2bb5209a92396461269e5f661c98faaf7bac3326..c73545b0b9f8cbc2abc088a5769b65596dce2f2d 100644 (file)
@@ -279,13 +279,10 @@ handle_1a(struct bregs *regs)
     }
 }
 
-// INT 08h System Timer ISR Entry Point
-void VISIBLE16
-handle_08(void)
+// Update main tick counter
+static void
+clock_update(void)
 {
-    debug_isr(DEBUG_ISR_08);
-
-    // Update counter
     u32 counter = GET_BDA(timer_counter);
     counter++;
     // compare to one days worth of timer ticks at 18.2 hz
@@ -300,6 +297,14 @@ handle_08(void)
     floppy_tick();
     usb_check_event();
     ps2_check_event();
+}
+
+// INT 08h System Timer ISR Entry Point
+void VISIBLE16
+handle_08(void)
+{
+    debug_isr(DEBUG_ISR_08);
+    clock_update();
 
     // chain to user timer tick INT #0x1c
     struct bregs br;
@@ -310,6 +315,20 @@ handle_08(void)
     pic_eoi1();
 }
 
+u32 last_timer_check VARLOW;
+
+// Simulate timer irq on machines without hardware irqs
+void
+clock_poll_irq(void)
+{
+    if (CONFIG_HARDWARE_IRQ)
+        return;
+    if (!timer_check(GET_LOW(last_timer_check)))
+        return;
+    SET_LOW(last_timer_check, timer_calc(ticks_to_ms(1)));
+    clock_update();
+}
+
 
 /****************************************************************
  * IRQ based timer
index 6ff696765ce7c1b2443abeeb8229fb51a8bcc6a9..d8b9764c702771eda1c33e2767e275cad9b81ab1 100644 (file)
 u16
 pic_irqmask_read(void)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return 0;
     return inb(PORT_PIC1_DATA) | (inb(PORT_PIC2_DATA) << 8);
 }
 
 void
 pic_irqmask_write(u16 mask)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return;
     outb(mask, PORT_PIC1_DATA);
     outb(mask >> 8, PORT_PIC2_DATA);
 }
@@ -26,6 +30,8 @@ pic_irqmask_write(u16 mask)
 void
 pic_irqmask_mask(u16 off, u16 on)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return;
     u8 pic1off = off, pic1on = on, pic2off = off>>8, pic2on = on>>8;
     outb((inb(PORT_PIC1_DATA) & ~pic1off) | pic1on, PORT_PIC1_DATA);
     outb((inb(PORT_PIC2_DATA) & ~pic2off) | pic2on, PORT_PIC2_DATA);
@@ -34,6 +40,8 @@ pic_irqmask_mask(u16 off, u16 on)
 void
 pic_reset(u8 irq0, u8 irq8)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return;
     // Send ICW1 (select OCW1 + will send ICW4)
     outb(0x11, PORT_PIC1_CMD);
     outb(0x11, PORT_PIC2_CMD);
@@ -60,6 +68,8 @@ pic_setup(void)
 void
 enable_hwirq(int hwirq, struct segoff_s func)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return;
     pic_irqmask_mask(1 << hwirq, 0);
     int vector;
     if (hwirq < 8)
@@ -72,6 +82,8 @@ enable_hwirq(int hwirq, struct segoff_s func)
 static u8
 pic_isr1_read(void)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return 0;
     // 0x0b == select OCW1 + read ISR
     outb(0x0b, PORT_PIC1_CMD);
     return inb(PORT_PIC1_CMD);
@@ -80,6 +92,8 @@ pic_isr1_read(void)
 static u8
 pic_isr2_read(void)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return 0;
     // 0x0b == select OCW1 + read ISR
     outb(0x0b, PORT_PIC2_CMD);
     return inb(PORT_PIC2_CMD);
index 6947b6e8199f6091c560760e4913281f4ea65304..f2d9f61304d9a46b6cf577a5c7d0602d7819ad87 100644 (file)
@@ -34,6 +34,8 @@
 static inline void
 pic_eoi1(void)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return;
     // Send eoi (select OCW2 + eoi)
     outb(0x20, PORT_PIC1_CMD);
 }
@@ -41,6 +43,8 @@ pic_eoi1(void)
 static inline void
 pic_eoi2(void)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return;
     // Send eoi (select OCW2 + eoi)
     outb(0x20, PORT_PIC2_CMD);
     pic_eoi1();
index 882b7728ff52d7c94b9c1d3f0fbc344c37dbd181..03d22b2f5834d660cc1b9167ba176b0813a5b522 100644 (file)
@@ -242,6 +242,8 @@ ticks_from_ms(u32 ms)
 void
 pit_setup(void)
 {
+    if (!CONFIG_HARDWARE_IRQ)
+        return;
     // timer0: binary count, 16bit count, mode 2
     outb(PM_SEL_TIMER0|PM_ACCESS_WORD|PM_MODE2|PM_CNT_BINARY, PORT_PIT_MODE);
     // maximum count of 0000H = 18.2Hz
index e67aeb6ae5385a7f2cd629ce59c25117b07dcec8..7759c577de23deaaa0c5da1c64ca7a2a1c7dbccf 100644 (file)
@@ -671,6 +671,8 @@ check_irqs(void)
         stack_hop_back(0, 0, _cfunc16_check_irqs);
         return;
     }
+    if (MODE16)
+        clock_poll_irq();
     asm volatile("sti ; nop ; rep ; nop ; cli ; cld" : : :"memory");
 }
 
@@ -706,7 +708,8 @@ wait_irq(void)
 void
 yield_toirq(void)
 {
-    if (!MODESEGMENT && (have_threads() || !CanInterrupt)) {
+    if (!CONFIG_HARDWARE_IRQ
+        || (!MODESEGMENT && (have_threads() || !CanInterrupt))) {
         // Threads still active or irqs not available - do a yield instead.
         yield();
         return;
index 8ea0ba0ab95213acf88be0021fbb0ee121437709..327abeb71ddf811497efd30bbd1e04b71d34921f 100644 (file)
@@ -53,6 +53,7 @@ int cdrom_boot(struct drive_s *drive_g);
 // clock.c
 void clock_setup(void);
 void handle_1583(struct bregs *regs);
+void clock_poll_irq(void);
 u32 irqtimer_calc_ticks(u32 count);
 u32 irqtimer_calc(u32 msecs);
 int irqtimer_check(u32 end);