summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--8253pit.c46
-rw-r--r--Makefile1
-rw-r--r--console.c1
-rw-r--r--defs.h6
-rw-r--r--ide.c1
-rw-r--r--ioapic.c66
-rw-r--r--lapic.c33
-rw-r--r--main.c7
-rw-r--r--mp.c8
-rw-r--r--picirq.c4
-rw-r--r--runoff.list1
-rw-r--r--traps.h2
12 files changed, 128 insertions, 48 deletions
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