diff options
| -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 | 
