[SeaBIOS] [PATCH 1/3] Add minimal support for machines without hardware interrupts

Kevin O'Connor kevin at koconnor.net
Mon Aug 17 17:21:55 CET 2015


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 at koconnor.net>
---
 src/Kconfig    | 13 ++++++++++++-
 src/clock.c    | 31 +++++++++++++++++++++++++------
 src/hw/pic.c   | 14 ++++++++++++++
 src/hw/pic.h   |  4 ++++
 src/hw/timer.c |  2 ++
 src/stacks.c   |  5 ++++-
 src/util.h     |  1 +
 7 files changed, 62 insertions(+), 8 deletions(-)

diff --git a/src/Kconfig b/src/Kconfig
index 56a1b2f..b873cd3 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -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)"
diff --git a/src/clock.c b/src/clock.c
index 2bb5209..c73545b 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -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
diff --git a/src/hw/pic.c b/src/hw/pic.c
index 6ff6967..d8b9764 100644
--- a/src/hw/pic.c
+++ b/src/hw/pic.c
@@ -13,12 +13,16 @@
 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);
diff --git a/src/hw/pic.h b/src/hw/pic.h
index 6947b6e..f2d9f61 100644
--- a/src/hw/pic.h
+++ b/src/hw/pic.h
@@ -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();
diff --git a/src/hw/timer.c b/src/hw/timer.c
index 882b772..03d22b2 100644
--- a/src/hw/timer.c
+++ b/src/hw/timer.c
@@ -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
diff --git a/src/stacks.c b/src/stacks.c
index e67aeb6..7759c57 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -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;
diff --git a/src/util.h b/src/util.h
index 8ea0ba0..327abeb 100644
--- a/src/util.h
+++ b/src/util.h
@@ -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);
-- 
1.9.3




More information about the SeaBIOS mailing list