diff options
author | kaashoek <kaashoek> | 2006-07-05 20:00:14 +0000 |
---|---|---|
committer | kaashoek <kaashoek> | 2006-07-05 20:00:14 +0000 |
commit | b22d898297a2496ba4cfd31d445769fbebc0a46d (patch) | |
tree | 99a08718f78c6836be1a245650e48c9f20333fb9 | |
parent | 8b4e2a08febc8b957b44732dbc7da831479a0005 (diff) | |
download | xv6-labs-b22d898297a2496ba4cfd31d445769fbebc0a46d.tar.gz xv6-labs-b22d898297a2496ba4cfd31d445769fbebc0a46d.tar.bz2 xv6-labs-b22d898297a2496ba4cfd31d445769fbebc0a46d.zip |
timer interrupts
disk interrupts (assuming bochs has a bug)
-rw-r--r-- | defs.h | 6 | ||||
-rw-r--r-- | ide.c | 127 | ||||
-rw-r--r-- | main.c | 6 | ||||
-rw-r--r-- | mp.c | 61 | ||||
-rw-r--r-- | picirq.c | 131 | ||||
-rw-r--r-- | proc.h | 1 | ||||
-rw-r--r-- | string.c | 11 | ||||
-rw-r--r-- | trap.c | 1 | ||||
-rw-r--r-- | x86.h | 5 |
9 files changed, 198 insertions, 151 deletions
@@ -25,11 +25,13 @@ void * memcpy(void *dst, void *src, unsigned n); void * memset(void *dst, int c, unsigned n); int memcmp(const void *v1, const void *v2, unsigned n); void *memmove(void *dst, const void *src, unsigned n); +int strncmp(const char *p, const char *q, unsigned n); // syscall.c void syscall(void); // picirq.c +extern uint16_t irq_mask_8259A; void irq_setmask_8259A(uint16_t mask); void pic_init(void); @@ -66,3 +68,7 @@ struct fd * fd_alloc(); void fd_close(struct fd *); int fd_read(struct fd *fd, char *addr, int n); int fd_write(struct fd *fd, char *addr, int n); + +// ide.c +void ide_init(void); +int ide_read(uint32_t secno, void *dst, unsigned nsecs); @@ -21,97 +21,104 @@ static int diskno = 0; static int ide_wait_ready(int check_error) { - int r; + int r; - while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) - /* do nothing */; + while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) + /* do nothing */; - if (check_error && (r & (IDE_DF|IDE_ERR)) != 0) - return -1; - return 0; + if (check_error && (r & (IDE_DF|IDE_ERR)) != 0) + return -1; + return 0; } +void +ide_init(void) +{ + cprintf("ide_init: enable IRQ 14\n"); + irq_setmask_8259A(irq_mask_8259A & ~(1<<14)); + ide_wait_ready(0); +} + + int ide_probe_disk1(void) { - int r, x; + int r, x; - // wait for Device 0 to be ready - ide_wait_ready(0); + // wait for Device 0 to be ready + ide_wait_ready(0); - // switch to Device 1 - outb(0x1F6, 0xE0 | (1<<4)); + // switch to Device 1 + outb(0x1F6, 0xE0 | (1<<4)); - // check for Device 1 to be ready for a while - for (x = 0; x < 1000 && (r = inb(0x1F7)) == 0; x++) - /* do nothing */; + // check for Device 1 to be ready for a while + for (x = 0; x < 1000 && (r = inb(0x1F7)) == 0; x++) + /* do nothing */; - // switch back to Device 0 - outb(0x1F6, 0xE0 | (0<<4)); + // switch back to Device 0 + outb(0x1F6, 0xE0 | (0<<4)); - cprintf("Device 1 presence: %d\n", (x < 1000)); - return (x < 1000); + cprintf("Device 1 presence: %d\n", (x < 1000)); + return (x < 1000); } void ide_set_disk(int d) { - if (d != 0 && d != 1) - panic("bad disk number"); - diskno = d; + if (d != 0 && d != 1) + panic("bad disk number"); + diskno = d; } int ide_read(uint32_t secno, void *dst, unsigned nsecs) { - int r; - - if(nsecs > 256) - panic("ide_read"); - - ide_wait_ready(0); - - outb(0x3f6, 0); - outb(0x1F2, nsecs); - outb(0x1F3, secno & 0xFF); - outb(0x1F4, (secno >> 8) & 0xFF); - outb(0x1F5, (secno >> 16) & 0xFF); - outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); - outb(0x1F7, 0x20); // CMD 0x20 means read sector - - sleep(0); - - for (; nsecs > 0; nsecs--, dst += 512) { - if ((r = ide_wait_ready(1)) < 0) - return r; - insl(0x1F0, dst, 512/4); - } + int r; + + if(nsecs > 256) + panic("ide_read"); + + ide_wait_ready(0); + + outb(0x3f6, 0); + outb(0x1F2, nsecs); + outb(0x1F3, secno & 0xFF); + outb(0x1F4, (secno >> 8) & 0xFF); + outb(0x1F5, (secno >> 16) & 0xFF); + outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); + outb(0x1F7, 0x20); // CMD 0x20 means read sector + + for (; nsecs > 0; nsecs--, dst += 512) { + if ((r = ide_wait_ready(1)) < 0) + return r; + insl(0x1F0, dst, 512/4); + } - return 0; + return 0; } int ide_write(uint32_t secno, const void *src, unsigned nsecs) { - int r; + int r; - if(nsecs > 256) - panic("ide_write"); + if(nsecs > 256) + panic("ide_write"); - ide_wait_ready(0); + ide_wait_ready(0); - outb(0x1F2, nsecs); - outb(0x1F3, secno & 0xFF); - outb(0x1F4, (secno >> 8) & 0xFF); - outb(0x1F5, (secno >> 16) & 0xFF); - outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); - outb(0x1F7, 0x30); // CMD 0x30 means write sector + outb(0x1F2, nsecs); + outb(0x1F3, secno & 0xFF); + outb(0x1F4, (secno >> 8) & 0xFF); + outb(0x1F5, (secno >> 16) & 0xFF); + outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); + outb(0x1F7, 0x30); // CMD 0x30 means write sector - for (; nsecs > 0; nsecs--, src += 512) { - if ((r = ide_wait_ready(1)) < 0) - return r; - outsl(0x1F0, src, 512/4); - } + for (; nsecs > 0; nsecs--, src += 512) { + if ((r = ide_wait_ready(1)) < 0) + return r; + outsl(0x1F0, src, 512/4); + } - return 0; + return 0; } @@ -36,7 +36,7 @@ main() cprintf("\nxV6\n\n"); - pic_init(); // initialize PIC---not clear why + pic_init(); // initialize PIC mp_init(); // multiprocessor kinit(); // physical memory allocator tvinit(); // trap vectors @@ -59,12 +59,14 @@ main() p->ppid = 0; setupsegs(p); + write_eflags(read_eflags() | FL_IF); + // turn on interrupts on boot processor lapic_timerinit(); lapic_enableintr(); - write_eflags(read_eflags() | FL_IF); #if 0 + ide_init(); ide_read(0, buf, 1); cprintf("sec0.0 %x\n", buf[0] & 0xff); #endif @@ -92,6 +92,28 @@ enum { /* LAPIC_TDCR */ LAPIC_X1 = 0x0000000B, /* divide by 1 */ }; +static char* buses[] = { + "CBUSI ", + "CBUSII", + "EISA ", + "FUTURE", + "INTERN", + "ISA ", + "MBI ", + "MBII ", + "MCA ", + "MPI ", + "MPSA ", + "NUBUS ", + "PCI ", + "PCMCIA", + "TC ", + "VL ", + "VME ", + "XPRESS", + 0, +}; + #define APBOOTCODE 0x7000 // XXX hack static struct MP* mp; // The MP floating point structure @@ -126,7 +148,7 @@ lapic_timerinit() void lapic_timerintr() { - // cprintf("%d: timer interrupt!\n", cpu()); + cprintf("%d: timer interrupt!\n", cpu()); lapic_write (LAPIC_EOI, 0); } @@ -137,23 +159,17 @@ lapic_init(int c) cprintf("lapic_init %d\n", c); - irq_setmask_8259A(0xFFFF); + lapic_write(LAPIC_DFR, 0xFFFFFFFF); // set destination format register + r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // read APIC ID + lapic_write(LAPIC_LDR, (1<<r)<<24); // set logical destination register to r + lapic_write(LAPIC_TPR, 0xFF); // no interrupts for now + lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS)); // enable APIC - lapic_write(LAPIC_DFR, 0xFFFFFFFF); - r = (lapic_read(LAPIC_ID)>>24) & 0xFF; - lapic_write(LAPIC_LDR, (1<<r)<<24); - lapic_write(LAPIC_TPR, 0xFF); - lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS)); + // in virtual wire mode, set up the LINT0 and LINT1 as follows: + lapic_write(LAPIC_LINT0, APIC_IMASK | APIC_EXTINT); + lapic_write(LAPIC_LINT1, APIC_IMASK | APIC_NMI); - /* - * Set the local interrupts. It's likely these should just be - * masked off for SMP mode as some Pentium Pros have problems if - * LINT[01] are set to ExtINT. - * Acknowledge any outstanding interrupts. - */ - lapic_write(LAPIC_LINT0, cpus[c].lintr[0]); - lapic_write(LAPIC_LINT1, cpus[c].lintr[1]); - lapic_write(LAPIC_EOI, 0); + lapic_write(LAPIC_EOI, 0); // acknowledge any outstanding interrupts. lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF; if(lvt >= 4) @@ -290,7 +306,7 @@ mp_detect(void) if(sum || (pcmp->version != 1 && pcmp->version != 4)) return 3; - cprintf("Mp spec rev #: %x\n", mp->specrev); + cprintf("Mp spec rev #: %x imcrp 0x%x\n", mp->specrev, mp->imcrp); return 0; } @@ -308,8 +324,10 @@ mp_init() uint8_t *p, *e; struct MPCTB *mpctb; struct MPPE *proc; + struct MPBE *bus; int c; extern int main(); + int i; ncpu = 0; if ((r = mp_detect()) != 0) return; @@ -332,8 +350,6 @@ mp_init() case MPPROCESSOR: proc = (struct MPPE *) p; cpus[ncpu].apicid = proc->apicid; - cpus[ncpu].lintr[0] = APIC_IMASK; - cpus[ncpu].lintr[1] = APIC_IMASK; cprintf("a processor %x\n", cpus[ncpu].apicid); if (proc->flags & MPBP) { bcpu = &cpus[ncpu]; @@ -342,6 +358,12 @@ mp_init() p += sizeof(struct MPPE); continue; case MPBUS: + bus = (struct MPBE *) p; + for(i = 0; buses[i]; i++){ + if(strncmp(buses[i], bus->string, sizeof(bus->string)) == 0) + break; + } + cprintf("a bus %d\n", i); p += sizeof(struct MPBE); continue; case MPIOAPIC: @@ -349,6 +371,7 @@ mp_init() p += sizeof(struct MPIOAPIC); continue; case MPIOINTR: + cprintf("an I/O intr\n"); p += sizeof(struct MPIE); continue; default: @@ -4,80 +4,85 @@ #include "x86.h" #include "defs.h" +// I/O Addresses of the two 8259A programmable interrupt controllers +#define IO_PIC1 0x20 // Master (IRQs 0-7) +#define IO_PIC2 0xA0 // Slave (IRQs 8-15) + +#define IRQ_SLAVE 2 // IRQ at which slave connects to master + // Current IRQ mask. // Initial IRQ mask has interrupt 2 enabled (for slave 8259A). uint16_t irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE); -static int didinit; /* Initialize the 8259A interrupt controllers. */ void pic_init(void) { - didinit = 1; - - // mask all interrupts - outb(IO_PIC1+1, 0xFF); - outb(IO_PIC2+1, 0xFF); - - // Set up master (8259A-1) - - // ICW1: 0001g0hi - // g: 0 = edge triggering, 1 = level triggering - // h: 0 = cascaded PICs, 1 = master only - // i: 0 = no ICW4, 1 = ICW4 required - outb(IO_PIC1, 0x11); - - // ICW2: Vector offset - outb(IO_PIC1+1, IRQ_OFFSET); - - // ICW3: bit mask of IR lines connected to slave PICs (master PIC), - // 3-bit No of IR line at which slave connects to master(slave PIC). - outb(IO_PIC1+1, 1<<IRQ_SLAVE); - - // ICW4: 000nbmap - // n: 1 = special fully nested mode - // b: 1 = buffered mode - // m: 0 = slave PIC, 1 = master PIC - // (ignored when b is 0, as the master/slave role - // can be hardwired). - // a: 1 = Automatic EOI mode - // p: 0 = MCS-80/85 mode, 1 = intel x86 mode - outb(IO_PIC1+1, 0x3); - - // Set up slave (8259A-2) - outb(IO_PIC2, 0x11); // ICW1 - outb(IO_PIC2+1, IRQ_OFFSET + 8); // ICW2 - outb(IO_PIC2+1, IRQ_SLAVE); // ICW3 - // NB Automatic EOI mode doesn't tend to work on the slave. - // Linux source code says it's "to be investigated". - outb(IO_PIC2+1, 0x01); // ICW4 - - // OCW3: 0ef01prs - // ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask - // p: 0 = no polling, 1 = polling mode - // rs: 0x = NOP, 10 = read IRR, 11 = read ISR - outb(IO_PIC1, 0x68); /* clear specific mask */ - outb(IO_PIC1, 0x0a); /* read IRR by default */ - - outb(IO_PIC2, 0x68); /* OCW3 */ - outb(IO_PIC2, 0x0a); /* OCW3 */ - - if (irq_mask_8259A != 0xFFFF) - irq_setmask_8259A(irq_mask_8259A); + // mask all interrupts + outb(IO_PIC1+1, 0xFF); + outb(IO_PIC2+1, 0xFF); + + // Set up master (8259A-1) + + // ICW1: 0001g0hi + // g: 0 = edge triggering, 1 = level triggering + // h: 0 = cascaded PICs, 1 = master only + // i: 0 = no ICW4, 1 = ICW4 required + outb(IO_PIC1, 0x11); + + // ICW2: Vector offset + outb(IO_PIC1+1, IRQ_OFFSET); + + // ICW3: bit mask of IR lines connected to slave PICs (master PIC), + // 3-bit No of IR line at which slave connects to master(slave PIC). + outb(IO_PIC1+1, 1<<IRQ_SLAVE); + + // ICW4: 000nbmap + // n: 1 = special fully nested mode + // b: 1 = buffered mode + // m: 0 = slave PIC, 1 = master PIC + // (ignored when b is 0, as the master/slave role + // can be hardwired). + // a: 1 = Automatic EOI mode + // p: 0 = MCS-80/85 mode, 1 = intel x86 mode + outb(IO_PIC1+1, 0x3); + + // Set up slave (8259A-2) + outb(IO_PIC2, 0x11); // ICW1 + outb(IO_PIC2+1, IRQ_OFFSET + 8); // ICW2 + outb(IO_PIC2+1, IRQ_SLAVE); // ICW3 + // NB Automatic EOI mode doesn't tend to work on the slave. + // Linux source code says it's "to be investigated". + outb(IO_PIC2+1, 0x3); // ICW4 + + // OCW3: 0ef01prs + // ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask + // p: 0 = no polling, 1 = polling mode + // rs: 0x = NOP, 10 = read IRR, 11 = read ISR + outb(IO_PIC1, 0x68); /* clear specific mask */ + outb(IO_PIC1, 0x0a); /* read IRR by default */ + + outb(IO_PIC2, 0x68); /* OCW3 */ + outb(IO_PIC2, 0x0a); /* OCW3 */ + + if (irq_mask_8259A != 0xFFFF) + irq_setmask_8259A(irq_mask_8259A); + } void irq_setmask_8259A(uint16_t mask) { - int i; - irq_mask_8259A = mask; - if (!didinit) - return; - outb(IO_PIC1+1, (char)mask); - outb(IO_PIC2+1, (char)(mask >> 8)); - cprintf("enabled interrupts:"); - for (i = 0; i < 16; i++) - if (~mask & (1<<i)) - cprintf(" %d", i); - cprintf("\n"); + int i; + irq_mask_8259A = mask; + + outb(IO_PIC1+1, (char)mask); + outb(IO_PIC2+1, (char)(mask >> 8)); + + cprintf("%d: enabled interrupts:", cpu()); + + for (i = 0; i < 16; i++) + if (~mask & (1<<i)) + cprintf(" %d", i); + cprintf("\n"); } @@ -42,7 +42,6 @@ extern struct proc *curproc[NCPU]; struct cpu { uint8_t apicid; // Local APIC ID - int lintr[2]; // Local APIC char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main() }; @@ -58,3 +58,14 @@ memmove(void *dst, const void *src, unsigned n) return dst; } + +int +strncmp(const char *p, const char *q, unsigned n) +{ + while (n > 0 && *p && *p == *q) + n--, p++, q++; + if (n == 0) + return 0; + else + return (int) ((unsigned char) *p - (unsigned char) *q); +} @@ -61,7 +61,6 @@ trap(struct Trapframe *tf) return; } - cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip); // XXX probably ought to lgdt on trap return @@ -352,11 +352,6 @@ struct Trapframe { #define MAX_IRQS 16 // Number of IRQs -// I/O Addresses of the two 8259A programmable interrupt controllers -#define IO_PIC1 0x20 // Master (IRQs 0-7) -#define IO_PIC2 0xA0 // Slave (IRQs 8-15) - -#define IRQ_SLAVE 2 // IRQ at which slave connects to master #define IRQ_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET #define IRQ_ERROR 19 |