提交 b22d8982 创建 作者: kaashoek's avatar kaashoek

timer interrupts

disk interrupts (assuming bochs has a bug)
上级 8b4e2a08
...@@ -25,11 +25,13 @@ void * memcpy(void *dst, void *src, unsigned n); ...@@ -25,11 +25,13 @@ void * memcpy(void *dst, void *src, unsigned n);
void * memset(void *dst, int c, unsigned n); void * memset(void *dst, int c, unsigned n);
int memcmp(const void *v1, const void *v2, unsigned n); int memcmp(const void *v1, const void *v2, unsigned n);
void *memmove(void *dst, const void *src, unsigned n); void *memmove(void *dst, const void *src, unsigned n);
int strncmp(const char *p, const char *q, unsigned n);
// syscall.c // syscall.c
void syscall(void); void syscall(void);
// picirq.c // picirq.c
extern uint16_t irq_mask_8259A;
void irq_setmask_8259A(uint16_t mask); void irq_setmask_8259A(uint16_t mask);
void pic_init(void); void pic_init(void);
...@@ -66,3 +68,7 @@ struct fd * fd_alloc(); ...@@ -66,3 +68,7 @@ struct fd * fd_alloc();
void fd_close(struct fd *); void fd_close(struct fd *);
int fd_read(struct fd *fd, char *addr, int n); int fd_read(struct fd *fd, char *addr, int n);
int fd_write(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; ...@@ -21,97 +21,104 @@ static int diskno = 0;
static int static int
ide_wait_ready(int check_error) ide_wait_ready(int check_error)
{ {
int r; int r;
while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
/* do nothing */; /* do nothing */;
if (check_error && (r & (IDE_DF|IDE_ERR)) != 0) if (check_error && (r & (IDE_DF|IDE_ERR)) != 0)
return -1; return -1;
return 0; 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 int
ide_probe_disk1(void) ide_probe_disk1(void)
{ {
int r, x; int r, x;
// wait for Device 0 to be ready // wait for Device 0 to be ready
ide_wait_ready(0); ide_wait_ready(0);
// switch to Device 1 // switch to Device 1
outb(0x1F6, 0xE0 | (1<<4)); outb(0x1F6, 0xE0 | (1<<4));
// check for Device 1 to be ready for a while // check for Device 1 to be ready for a while
for (x = 0; x < 1000 && (r = inb(0x1F7)) == 0; x++) for (x = 0; x < 1000 && (r = inb(0x1F7)) == 0; x++)
/* do nothing */; /* do nothing */;
// switch back to Device 0 // switch back to Device 0
outb(0x1F6, 0xE0 | (0<<4)); outb(0x1F6, 0xE0 | (0<<4));
cprintf("Device 1 presence: %d\n", (x < 1000)); cprintf("Device 1 presence: %d\n", (x < 1000));
return (x < 1000); return (x < 1000);
} }
void void
ide_set_disk(int d) ide_set_disk(int d)
{ {
if (d != 0 && d != 1) if (d != 0 && d != 1)
panic("bad disk number"); panic("bad disk number");
diskno = d; diskno = d;
} }
int int
ide_read(uint32_t secno, void *dst, unsigned nsecs) ide_read(uint32_t secno, void *dst, unsigned nsecs)
{ {
int r; int r;
if(nsecs > 256) if(nsecs > 256)
panic("ide_read"); panic("ide_read");
ide_wait_ready(0); ide_wait_ready(0);
outb(0x3f6, 0); outb(0x3f6, 0);
outb(0x1F2, nsecs); outb(0x1F2, nsecs);
outb(0x1F3, secno & 0xFF); outb(0x1F3, secno & 0xFF);
outb(0x1F4, (secno >> 8) & 0xFF); outb(0x1F4, (secno >> 8) & 0xFF);
outb(0x1F5, (secno >> 16) & 0xFF); outb(0x1F5, (secno >> 16) & 0xFF);
outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F));
outb(0x1F7, 0x20); // CMD 0x20 means read sector outb(0x1F7, 0x20); // CMD 0x20 means read sector
sleep(0); for (; nsecs > 0; nsecs--, dst += 512) {
if ((r = ide_wait_ready(1)) < 0)
for (; nsecs > 0; nsecs--, dst += 512) { return r;
if ((r = ide_wait_ready(1)) < 0) insl(0x1F0, dst, 512/4);
return r; }
insl(0x1F0, dst, 512/4);
}
return 0; return 0;
} }
int int
ide_write(uint32_t secno, const void *src, unsigned nsecs) ide_write(uint32_t secno, const void *src, unsigned nsecs)
{ {
int r; int r;
if(nsecs > 256) if(nsecs > 256)
panic("ide_write"); panic("ide_write");
ide_wait_ready(0); ide_wait_ready(0);
outb(0x1F2, nsecs); outb(0x1F2, nsecs);
outb(0x1F3, secno & 0xFF); outb(0x1F3, secno & 0xFF);
outb(0x1F4, (secno >> 8) & 0xFF); outb(0x1F4, (secno >> 8) & 0xFF);
outb(0x1F5, (secno >> 16) & 0xFF); outb(0x1F5, (secno >> 16) & 0xFF);
outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F)); outb(0x1F6, 0xE0 | ((diskno&1)<<4) | ((secno>>24)&0x0F));
outb(0x1F7, 0x30); // CMD 0x30 means write sector outb(0x1F7, 0x30); // CMD 0x30 means write sector
for (; nsecs > 0; nsecs--, src += 512) { for (; nsecs > 0; nsecs--, src += 512) {
if ((r = ide_wait_ready(1)) < 0) if ((r = ide_wait_ready(1)) < 0)
return r; return r;
outsl(0x1F0, src, 512/4); outsl(0x1F0, src, 512/4);
} }
return 0; return 0;
} }
...@@ -36,7 +36,7 @@ main() ...@@ -36,7 +36,7 @@ main()
cprintf("\nxV6\n\n"); cprintf("\nxV6\n\n");
pic_init(); // initialize PIC---not clear why pic_init(); // initialize PIC
mp_init(); // multiprocessor mp_init(); // multiprocessor
kinit(); // physical memory allocator kinit(); // physical memory allocator
tvinit(); // trap vectors tvinit(); // trap vectors
...@@ -59,12 +59,14 @@ main() ...@@ -59,12 +59,14 @@ main()
p->ppid = 0; p->ppid = 0;
setupsegs(p); setupsegs(p);
write_eflags(read_eflags() | FL_IF);
// turn on interrupts on boot processor // turn on interrupts on boot processor
lapic_timerinit(); lapic_timerinit();
lapic_enableintr(); lapic_enableintr();
write_eflags(read_eflags() | FL_IF);
#if 0 #if 0
ide_init();
ide_read(0, buf, 1); ide_read(0, buf, 1);
cprintf("sec0.0 %x\n", buf[0] & 0xff); cprintf("sec0.0 %x\n", buf[0] & 0xff);
#endif #endif
......
...@@ -92,6 +92,28 @@ enum { /* LAPIC_TDCR */ ...@@ -92,6 +92,28 @@ enum { /* LAPIC_TDCR */
LAPIC_X1 = 0x0000000B, /* divide by 1 */ 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 #define APBOOTCODE 0x7000 // XXX hack
static struct MP* mp; // The MP floating point structure static struct MP* mp; // The MP floating point structure
...@@ -126,7 +148,7 @@ lapic_timerinit() ...@@ -126,7 +148,7 @@ lapic_timerinit()
void void
lapic_timerintr() lapic_timerintr()
{ {
// cprintf("%d: timer interrupt!\n", cpu()); cprintf("%d: timer interrupt!\n", cpu());
lapic_write (LAPIC_EOI, 0); lapic_write (LAPIC_EOI, 0);
} }
...@@ -137,23 +159,17 @@ lapic_init(int c) ...@@ -137,23 +159,17 @@ lapic_init(int c)
cprintf("lapic_init %d\n", 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); // in virtual wire mode, set up the LINT0 and LINT1 as follows:
r = (lapic_read(LAPIC_ID)>>24) & 0xFF; lapic_write(LAPIC_LINT0, APIC_IMASK | APIC_EXTINT);
lapic_write(LAPIC_LDR, (1<<r)<<24); lapic_write(LAPIC_LINT1, APIC_IMASK | APIC_NMI);
lapic_write(LAPIC_TPR, 0xFF);
lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS));
/* lapic_write(LAPIC_EOI, 0); // acknowledge any outstanding interrupts.
* 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);
lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF; lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF;
if(lvt >= 4) if(lvt >= 4)
...@@ -290,7 +306,7 @@ mp_detect(void) ...@@ -290,7 +306,7 @@ mp_detect(void)
if(sum || (pcmp->version != 1 && pcmp->version != 4)) if(sum || (pcmp->version != 1 && pcmp->version != 4))
return 3; 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; return 0;
} }
...@@ -308,8 +324,10 @@ mp_init() ...@@ -308,8 +324,10 @@ mp_init()
uint8_t *p, *e; uint8_t *p, *e;
struct MPCTB *mpctb; struct MPCTB *mpctb;
struct MPPE *proc; struct MPPE *proc;
struct MPBE *bus;
int c; int c;
extern int main(); extern int main();
int i;
ncpu = 0; ncpu = 0;
if ((r = mp_detect()) != 0) return; if ((r = mp_detect()) != 0) return;
...@@ -332,8 +350,6 @@ mp_init() ...@@ -332,8 +350,6 @@ mp_init()
case MPPROCESSOR: case MPPROCESSOR:
proc = (struct MPPE *) p; proc = (struct MPPE *) p;
cpus[ncpu].apicid = proc->apicid; 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); cprintf("a processor %x\n", cpus[ncpu].apicid);
if (proc->flags & MPBP) { if (proc->flags & MPBP) {
bcpu = &cpus[ncpu]; bcpu = &cpus[ncpu];
...@@ -342,6 +358,12 @@ mp_init() ...@@ -342,6 +358,12 @@ mp_init()
p += sizeof(struct MPPE); p += sizeof(struct MPPE);
continue; continue;
case MPBUS: 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); p += sizeof(struct MPBE);
continue; continue;
case MPIOAPIC: case MPIOAPIC:
...@@ -349,6 +371,7 @@ mp_init() ...@@ -349,6 +371,7 @@ mp_init()
p += sizeof(struct MPIOAPIC); p += sizeof(struct MPIOAPIC);
continue; continue;
case MPIOINTR: case MPIOINTR:
cprintf("an I/O intr\n");
p += sizeof(struct MPIE); p += sizeof(struct MPIE);
continue; continue;
default: default:
......
...@@ -4,80 +4,85 @@ ...@@ -4,80 +4,85 @@
#include "x86.h" #include "x86.h"
#include "defs.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. // Current IRQ mask.
// Initial IRQ mask has interrupt 2 enabled (for slave 8259A). // Initial IRQ mask has interrupt 2 enabled (for slave 8259A).
uint16_t irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE); uint16_t irq_mask_8259A = 0xFFFF & ~(1<<IRQ_SLAVE);
static int didinit;
/* Initialize the 8259A interrupt controllers. */ /* Initialize the 8259A interrupt controllers. */
void void
pic_init(void) pic_init(void)
{ {
didinit = 1; // mask all interrupts
outb(IO_PIC1+1, 0xFF);
// mask all interrupts outb(IO_PIC2+1, 0xFF);
outb(IO_PIC1+1, 0xFF);
outb(IO_PIC2+1, 0xFF); // Set up master (8259A-1)
// Set up master (8259A-1) // ICW1: 0001g0hi
// g: 0 = edge triggering, 1 = level triggering
// ICW1: 0001g0hi // h: 0 = cascaded PICs, 1 = master only
// g: 0 = edge triggering, 1 = level triggering // i: 0 = no ICW4, 1 = ICW4 required
// h: 0 = cascaded PICs, 1 = master only outb(IO_PIC1, 0x11);
// i: 0 = no ICW4, 1 = ICW4 required
outb(IO_PIC1, 0x11); // ICW2: Vector offset
outb(IO_PIC1+1, IRQ_OFFSET);
// 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).
// ICW3: bit mask of IR lines connected to slave PICs (master PIC), outb(IO_PIC1+1, 1<<IRQ_SLAVE);
// 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
// ICW4: 000nbmap // b: 1 = buffered mode
// n: 1 = special fully nested mode // m: 0 = slave PIC, 1 = master PIC
// b: 1 = buffered mode // (ignored when b is 0, as the master/slave role
// m: 0 = slave PIC, 1 = master PIC // can be hardwired).
// (ignored when b is 0, as the master/slave role // a: 1 = Automatic EOI mode
// can be hardwired). // p: 0 = MCS-80/85 mode, 1 = intel x86 mode
// a: 1 = Automatic EOI mode outb(IO_PIC1+1, 0x3);
// 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
// Set up slave (8259A-2) outb(IO_PIC2+1, IRQ_OFFSET + 8); // ICW2
outb(IO_PIC2, 0x11); // ICW1 outb(IO_PIC2+1, IRQ_SLAVE); // ICW3
outb(IO_PIC2+1, IRQ_OFFSET + 8); // ICW2 // NB Automatic EOI mode doesn't tend to work on the slave.
outb(IO_PIC2+1, IRQ_SLAVE); // ICW3 // Linux source code says it's "to be investigated".
// NB Automatic EOI mode doesn't tend to work on the slave. outb(IO_PIC2+1, 0x3); // ICW4
// 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
// OCW3: 0ef01prs // p: 0 = no polling, 1 = polling mode
// ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask // rs: 0x = NOP, 10 = read IRR, 11 = read ISR
// p: 0 = no polling, 1 = polling mode outb(IO_PIC1, 0x68); /* clear specific mask */
// rs: 0x = NOP, 10 = read IRR, 11 = read ISR outb(IO_PIC1, 0x0a); /* read IRR by default */
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 */
outb(IO_PIC2, 0x68); /* OCW3 */
outb(IO_PIC2, 0x0a); /* OCW3 */ if (irq_mask_8259A != 0xFFFF)
irq_setmask_8259A(irq_mask_8259A);
if (irq_mask_8259A != 0xFFFF)
irq_setmask_8259A(irq_mask_8259A);
} }
void void
irq_setmask_8259A(uint16_t mask) irq_setmask_8259A(uint16_t mask)
{ {
int i; int i;
irq_mask_8259A = mask; irq_mask_8259A = mask;
if (!didinit)
return; outb(IO_PIC1+1, (char)mask);
outb(IO_PIC1+1, (char)mask); outb(IO_PIC2+1, (char)(mask >> 8));
outb(IO_PIC2+1, (char)(mask >> 8));
cprintf("enabled interrupts:"); cprintf("%d: enabled interrupts:", cpu());
for (i = 0; i < 16; i++)
if (~mask & (1<<i)) for (i = 0; i < 16; i++)
cprintf(" %d", i); if (~mask & (1<<i))
cprintf("\n"); cprintf(" %d", i);
cprintf("\n");
} }
...@@ -42,7 +42,6 @@ extern struct proc *curproc[NCPU]; ...@@ -42,7 +42,6 @@ extern struct proc *curproc[NCPU];
struct cpu { struct cpu {
uint8_t apicid; // Local APIC ID 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() 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) ...@@ -58,3 +58,14 @@ memmove(void *dst, const void *src, unsigned n)
return dst; 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) ...@@ -61,7 +61,6 @@ trap(struct Trapframe *tf)
return; 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 // XXX probably ought to lgdt on trap return
......
...@@ -352,11 +352,6 @@ struct Trapframe { ...@@ -352,11 +352,6 @@ struct Trapframe {
#define MAX_IRQS 16 // Number of IRQs #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_OFFSET 32 // IRQ 0 corresponds to int IRQ_OFFSET
#define IRQ_ERROR 19 #define IRQ_ERROR 19
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论