diff options
author | kaashoek <kaashoek> | 2006-09-07 01:37:58 +0000 |
---|---|---|
committer | kaashoek <kaashoek> | 2006-09-07 01:37:58 +0000 |
commit | f70172129c94e4d53b56fc10a7d859679b581bd2 (patch) | |
tree | f5c95ac0b9eea765d36ab0cb0c53573e2dfa0f9d | |
parent | f9bc4452b5437570f1709430e9364cc3e323cf3a (diff) | |
download | xv6-labs-f70172129c94e4d53b56fc10a7d859679b581bd2.tar.gz xv6-labs-f70172129c94e4d53b56fc10a7d859679b581bd2.tar.bz2 xv6-labs-f70172129c94e4d53b56fc10a7d859679b581bd2.zip |
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)
-rw-r--r-- | 8253pit.c | 46 | ||||
-rw-r--r-- | Makefile | 1 | ||||
-rw-r--r-- | console.c | 1 | ||||
-rw-r--r-- | defs.h | 6 | ||||
-rw-r--r-- | ide.c | 1 | ||||
-rw-r--r-- | ioapic.c | 66 | ||||
-rw-r--r-- | lapic.c | 33 | ||||
-rw-r--r-- | main.c | 7 | ||||
-rw-r--r-- | mp.c | 8 | ||||
-rw-r--r-- | picirq.c | 4 | ||||
-rw-r--r-- | runoff.list | 1 | ||||
-rw-r--r-- | traps.h | 2 |
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)); +} @@ -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- @@ -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; @@ -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); @@ -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(); @@ -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); + } } @@ -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; } @@ -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. @@ -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++; @@ -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 @@ -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 |