summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorkaashoek <kaashoek>2006-07-05 20:00:14 +0000
committerkaashoek <kaashoek>2006-07-05 20:00:14 +0000
commitb22d898297a2496ba4cfd31d445769fbebc0a46d (patch)
tree99a08718f78c6836be1a245650e48c9f20333fb9
parent8b4e2a08febc8b957b44732dbc7da831479a0005 (diff)
downloadxv6-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.h6
-rw-r--r--ide.c127
-rw-r--r--main.c6
-rw-r--r--mp.c61
-rw-r--r--picirq.c131
-rw-r--r--proc.h1
-rw-r--r--string.c11
-rw-r--r--trap.c1
-rw-r--r--x86.h5
9 files changed, 198 insertions, 151 deletions
diff --git a/defs.h b/defs.h
index e627a4c..d1025a6 100644
--- a/defs.h
+++ b/defs.h
@@ -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);
diff --git a/ide.c b/ide.c
index 3152f93..0e63a86 100644
--- a/ide.c
+++ b/ide.c
@@ -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;
}
diff --git a/main.c b/main.c
index 4c2a2f9..296d00f 100644
--- a/main.c
+++ b/main.c
@@ -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
diff --git a/mp.c b/mp.c
index 57b887d..a0d51bf 100644
--- a/mp.c
+++ b/mp.c
@@ -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:
diff --git a/picirq.c b/picirq.c
index ba131a3..9c3ea0c 100644
--- a/picirq.c
+++ b/picirq.c
@@ -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");
}
diff --git a/proc.h b/proc.h
index e371f7d..0c748aa 100644
--- a/proc.h
+++ b/proc.h
@@ -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()
};
diff --git a/string.c b/string.c
index 54f4ba8..c88e7de 100644
--- a/string.c
+++ b/string.c
@@ -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);
+}
diff --git a/trap.c b/trap.c
index e36540d..0459583 100644
--- a/trap.c
+++ b/trap.c
@@ -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
diff --git a/x86.h b/x86.h
index 7bc677f..0063826 100644
--- a/x86.h
+++ b/x86.h
@@ -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