From f70172129c94e4d53b56fc10a7d859679b581bd2 Mon Sep 17 00:00:00 2001
From: kaashoek <kaashoek>
Date: Thu, 7 Sep 2006 01:37:58 +0000
Subject: [PATCH] run without lapic and ioapic, if they are not present if no
 lapic available, use 8253pit for clock now xv6 runs both on qemu
 (uniprocessor) and bochs (uniprocessor and MP)

---
 8253pit.c   | 46 +++++++++++++++++++++++++++++++++++++
 Makefile    |  1 +
 console.c   |  1 +
 defs.h      |  6 +++++
 ide.c       |  1 +
 ioapic.c    | 66 ++++++++++++++++++++++++++++-------------------------
 lapic.c     | 33 +++++++++++++++++++--------
 main.c      |  7 ++++--
 mp.c        |  8 +++++--
 picirq.c    |  4 ++--
 runoff.list |  1 +
 traps.h     |  2 +-
 12 files changed, 128 insertions(+), 48 deletions(-)
 create mode 100644 8253pit.c

diff --git a/8253pit.c b/8253pit.c
new file mode 100644
index 0000000..0b82e29
--- /dev/null
+++ b/8253pit.c
@@ -0,0 +1,46 @@
+#include "types.h"
+#include "x86.h"
+#include "defs.h"
+#include "traps.h"
+
+// Register definitions for the Intel
+// 8253/8254/82C54 Programmable Interval Timer (PIT).
+
+#define	IO_TIMER1	0x040		/* 8253 Timer #1 */
+#define	IO_TIMER2	0x048		/* 8253 Timer #2 (EISA only) */
+
+//
+// Frequency of all three count-down timers; (TIMER_FREQ/freq) is the
+// appropriate count to generate a frequency of freq hz.
+
+#define	TIMER_FREQ	1193182
+#define TIMER_DIV(x)	((TIMER_FREQ+(x)/2)/(x))
+
+#define	TIMER_CNTR0	(IO_TIMER1 + 0)	/* timer 0 counter port */
+#define	TIMER_CNTR1	(IO_TIMER1 + 1)	/* timer 1 counter port */
+#define	TIMER_CNTR2	(IO_TIMER1 + 2)	/* timer 2 counter port */
+#define	TIMER_MODE	(IO_TIMER1 + 3)	/* timer mode port */
+#define		TIMER_SEL0	0x00	/* select counter 0 */
+#define		TIMER_SEL1	0x40	/* select counter 1 */
+#define		TIMER_SEL2	0x80	/* select counter 2 */
+#define		TIMER_INTTC	0x00	/* mode 0, intr on terminal cnt */
+#define		TIMER_ONESHOT	0x02	/* mode 1, one shot */
+#define		TIMER_RATEGEN	0x04	/* mode 2, rate generator */
+#define		TIMER_SQWAVE	0x06	/* mode 3, square wave */
+#define		TIMER_SWSTROBE	0x08	/* mode 4, s/w triggered strobe */
+#define		TIMER_HWSTROBE	0x0a	/* mode 5, h/w triggered strobe */
+#define		TIMER_LATCH	0x00	/* latch counter for reading */
+#define		TIMER_LSB	0x10	/* r/w counter LSB */
+#define		TIMER_MSB	0x20	/* r/w counter MSB */
+#define		TIMER_16BIT	0x30	/* r/w counter 16 bits, LSB first */
+#define		TIMER_BCD	0x01	/* count in BCD */
+
+void
+pit8253_timerinit(void)
+{
+  // initialize 8253 clock to interrupt 100 times/sec
+  outb(TIMER_MODE, TIMER_SEL0 | TIMER_RATEGEN | TIMER_16BIT);
+  outb(IO_TIMER1, TIMER_DIV(100) % 256);
+  outb(IO_TIMER1, TIMER_DIV(100) / 256);
+  irq_setmask_8259A(irq_mask_8259A & ~(1<<IRQ_TIMER));
+}
diff --git a/Makefile b/Makefile
index c430bed..85d772d 100644
--- a/Makefile
+++ b/Makefile
@@ -21,6 +21,7 @@ OBJS = \
 	vectors.o\
 	bio.o\
 	fs.o\
+	8253pit.o\
 
 # Cross-compiling (e.g., on Mac OS X)
 TOOLPREFIX = i386-jos-elf-
diff --git a/console.c b/console.c
index 418aa84..1952a3c 100644
--- a/console.c
+++ b/console.c
@@ -409,6 +409,7 @@ console_init()
   devsw[CONSOLE].d_write = console_write;
   devsw[CONSOLE].d_read = console_read;
 
+  irq_setmask_8259A(irq_mask_8259A & ~(1 << IRQ_KBD));
   ioapic_enable(IRQ_KBD, 0);
 
   use_console_lock = 1;
diff --git a/defs.h b/defs.h
index 85f0085..fb48700 100644
--- a/defs.h
+++ b/defs.h
@@ -49,9 +49,15 @@ int checkstring(uint);
 int putint(struct proc*, uint, int);
 
 // picirq.c
+extern ushort irq_mask_8259A;
 void pic_init(void);
+void irq_setmask_8259A(ushort);
+
+// 8253pit.c
+void pit8253_timerinit(void);
 
 // mp.c
+extern int ismp;
 void mp_init(void);
 void mp_startthem(void);
 int mp_bcpu(void);
diff --git a/ide.c b/ide.c
index f0fd0f9..4e2e1a6 100644
--- a/ide.c
+++ b/ide.c
@@ -50,6 +50,7 @@ void
 ide_init(void)
 {
   initlock(&ide_lock, "ide");
+  irq_setmask_8259A(irq_mask_8259A & ~(1 << IRQ_IDE));
   ioapic_enable (IRQ_IDE, ncpu - 1);
   ide_wait_ready(0);
   disk_1_present = ide_probe_disk1();
diff --git a/ioapic.c b/ioapic.c
index 8d22582..8745a69 100644
--- a/ioapic.c
+++ b/ioapic.c
@@ -37,28 +37,30 @@ ioapic_init(void)
   uchar id;
   int i;
 
-  io = (struct ioapic*) IO_APIC_BASE;
-  l = ioapic_read(io, IOAPIC_VER);
-  nintr =  ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
-  id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
-  if(id != ioapic_id)
-    panic("ioapic_init: id isn't equal to ioapic_id\n");
-  for(i = 0; i < nintr; i++) {
-    // active-hi and edge-triggered for ISA interrupts
-    // Assume that pin 0 on the first I/O APIC is an ExtINT pin.
-    // Assume that pins 1-15 are ISA interrupts
-    l = ioapic_read(io, IOAPIC_REDTBL_LO(i));
-    l = l & ~IOART_INTMASK;  // allow INTs
-    l |= IOART_INTMSET;
-    l = l & ~IOART_INTPOL;   // active hi
-    l = l & ~IOART_TRGRMOD;  // edgee triggered
-    l = l & ~IOART_DELMOD;   // fixed
-    l = l & ~IOART_DESTMOD;  // physical mode
-    l = l | (IRQ_OFFSET + i); // vector
-    ioapic_write(io, IOAPIC_REDTBL_LO(i), l);
-    h = ioapic_read(io, IOAPIC_REDTBL_HI(i));
-    h &= ~IOART_DEST;
-    ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
+  if (ismp) {
+    io = (struct ioapic*) IO_APIC_BASE;
+    l = ioapic_read(io, IOAPIC_VER);
+    nintr =  ((l & IOART_VER_MAXREDIR) >> MAXREDIRSHIFT) + 1;
+    id = ioapic_read(io, IOAPIC_ID) >> APIC_ID_SHIFT;
+    if(id != ioapic_id)
+      cprintf("ioapic_init: id isn't equal to ioapic_id; not a MP\n");
+    for(i = 0; i < nintr; i++) {
+      // active-hi and edge-triggered for ISA interrupts
+      // Assume that pin 0 on the first I/O APIC is an ExtINT pin.
+      // Assume that pins 1-15 are ISA interrupts
+      l = ioapic_read(io, IOAPIC_REDTBL_LO(i));
+      l = l & ~IOART_INTMASK;  // allow INTs
+      l |= IOART_INTMSET;
+      l = l & ~IOART_INTPOL;   // active hi
+      l = l & ~IOART_TRGRMOD;  // edgee triggered
+      l = l & ~IOART_DELMOD;   // fixed
+      l = l & ~IOART_DESTMOD;  // physical mode
+      l = l | (IRQ_OFFSET + i); // vector
+      ioapic_write(io, IOAPIC_REDTBL_LO(i), l);
+      h = ioapic_read(io, IOAPIC_REDTBL_HI(i));
+      h &= ~IOART_DEST;
+      ioapic_write(io, IOAPIC_REDTBL_HI(i), h);
+    }
   }
 }
 
@@ -67,13 +69,15 @@ ioapic_enable (int irq, int cpunum)
 {
   uint l, h;
   struct ioapic *io;
-
-  io = (struct ioapic*) IO_APIC_BASE;
-  l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
-  l = l & ~IOART_INTMASK;  // allow INTs
-  ioapic_write(io, IOAPIC_REDTBL_LO(irq), l);
-  h = ioapic_read(io, IOAPIC_REDTBL_HI(irq));
-  h &= ~IOART_DEST;
-  h |= (cpunum << APIC_ID_SHIFT);
-  ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
+  
+  if (ismp) {
+    io = (struct ioapic*) IO_APIC_BASE;
+    l = ioapic_read(io, IOAPIC_REDTBL_LO(irq));
+    l = l & ~IOART_INTMASK;  // allow INTs
+    ioapic_write(io, IOAPIC_REDTBL_LO(irq), l);
+    h = ioapic_read(io, IOAPIC_REDTBL_HI(irq));
+    h &= ~IOART_DEST;
+    h |= (cpunum << APIC_ID_SHIFT);
+    ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
+  }
 }
diff --git a/lapic.c b/lapic.c
index 8dc6d82..7777929 100644
--- a/lapic.c
+++ b/lapic.c
@@ -105,17 +105,20 @@ lapic_write(int r, int data)
 void
 lapic_timerinit(void)
 {
-  lapic_write(LAPIC_TDCR, LAPIC_X1);
-  lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |
-                           (IRQ_OFFSET + IRQ_TIMER));
-  lapic_write(LAPIC_TCCR, 10000000);
-  lapic_write(LAPIC_TICR, 10000000);
+  if (lapicaddr) {
+    lapic_write(LAPIC_TDCR, LAPIC_X1);
+    lapic_write(LAPIC_TIMER, LAPIC_CLKIN | LAPIC_PERIODIC |
+		(IRQ_OFFSET + IRQ_TIMER));
+    lapic_write(LAPIC_TCCR, 10000000);
+    lapic_write(LAPIC_TICR, 10000000);
+  }
 }
 
 void
 lapic_timerintr(void)
 {
-  lapic_write(LAPIC_EOI, 0);
+  if (lapicaddr) 
+    lapic_write(LAPIC_EOI, 0);
 }
 
 void
@@ -123,6 +126,9 @@ lapic_init(int c)
 {
   uint r, lvt;
 
+  if (lapicaddr == 0) 
+    return;
+
   lapic_write(LAPIC_DFR, 0xFFFFFFFF);    // Set dst format register
   r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // Read APIC ID
   lapic_write(LAPIC_LDR, (1<<r)<<24);    // Set logical dst register to r
@@ -155,25 +161,32 @@ lapic_init(int c)
 void
 lapic_enableintr(void)
 {
-  lapic_write(LAPIC_TPR, 0);
+  if (lapicaddr)
+    lapic_write(LAPIC_TPR, 0);
 }
 
 void
 lapic_disableintr(void)
 {
-  lapic_write(LAPIC_TPR, 0xFF);
+  if (lapicaddr)
+    lapic_write(LAPIC_TPR, 0xFF);
 }
 
 void
 lapic_eoi(void)
 {
-  lapic_write(LAPIC_EOI, 0);
+  if (lapicaddr)
+    lapic_write(LAPIC_EOI, 0);
 }
 
 int
 cpu(void)
 {
-  int x = (lapic_read(LAPIC_ID)>>24) & 0xFF;
+  int x;
+  if (lapicaddr) 
+    x = (lapic_read(LAPIC_ID)>>24) & 0xFF;
+  else 
+    x = 0;
   return x;
 }
 
diff --git a/main.c b/main.c
index dba8bdd..876c20a 100644
--- a/main.c
+++ b/main.c
@@ -71,8 +71,11 @@ main0(void)
   // start other CPUs
   mp_startthem();
 
-  // turn on timer and enable interrupts on the local APIC
-  lapic_timerinit();
+  // turn on timer
+  if (ismp) lapic_timerinit();
+  else pit8253_timerinit();
+
+  // enable interrupts on the local APIC
   lapic_enableintr();
 
   // Enable interrupts on this processor.
diff --git a/mp.c b/mp.c
index f2bb142..7a0a676 100644
--- a/mp.c
+++ b/mp.c
@@ -30,6 +30,7 @@ static char *buses[] = {
 };
 
 struct cpu cpus[NCPU];
+int ismp;
 int ncpu;
 uchar ioapic_id;
 
@@ -124,8 +125,11 @@ mp_init(void)
   uchar byte;
 
   ncpu = 0;
-  if((r = mp_detect()) != 0)
+  if((r = mp_detect()) != 0) {
     return;
+  }
+
+  ismp = 1;
 
   // Run through the table saving information needed for starting
   // application processors and initialising any I/O APICs. The table
@@ -165,7 +169,7 @@ mp_init(void)
       p += sizeof(struct mpie);
       continue;
     default:
-      cprintf("mpinit: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
+      cprintf("mp_init: unknown PCMP type 0x%x (e-p 0x%x)\n", *p, e-p);
       while(p < e){
         cprintf("%uX ", *p);
         p++;
diff --git a/picirq.c b/picirq.c
index 184e693..eaac053 100644
--- a/picirq.c
+++ b/picirq.c
@@ -11,9 +11,9 @@
 
 // Current IRQ mask.
 // Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
-static ushort irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
+ushort irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
 
-static void
+void
 irq_setmask_8259A(ushort mask)
 {
   irq_mask_8259A = mask;
diff --git a/runoff.list b/runoff.list
index 93fcae6..111095b 100644
--- a/runoff.list
+++ b/runoff.list
@@ -60,3 +60,4 @@ lapic.c
 ioapic.c
 picirq.c
 console.c
+8253pit.c
\ No newline at end of file
diff --git a/traps.h b/traps.h
index b1bafa0..732d8e0 100644
--- a/traps.h
+++ b/traps.h
@@ -27,8 +27,8 @@
 
 #define IRQ_OFFSET      32      // IRQ 0 corresponds to int IRQ_OFFSET
 
+#define IRQ_TIMER        0
 #define IRQ_KBD          1
 #define IRQ_IDE         14
-#define IRQ_TIMER       18
 #define IRQ_ERROR       19
 #define IRQ_SPURIOUS    31
-- 
GitLab