summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--bio.c2
-rw-r--r--defs.h6
-rw-r--r--ide.c8
-rw-r--r--ioapic.c82
-rw-r--r--ioapic.h90
-rw-r--r--lapic.c6
-rw-r--r--main.c1
-rw-r--r--mp.c31
-rw-r--r--picirq.c1
-rw-r--r--syscall.c1
11 files changed, 217 insertions, 12 deletions
diff --git a/Makefile b/Makefile
index d405284..c0153ad 100644
--- a/Makefile
+++ b/Makefile
@@ -4,6 +4,7 @@ OBJS = \
ide.o\
kalloc.o\
lapic.o\
+ ioapic.o\
main.o\
mp.o\
picirq.o\
diff --git a/bio.c b/bio.c
index c1a4bd6..602c915 100644
--- a/bio.c
+++ b/bio.c
@@ -43,7 +43,7 @@ bread(uint dev, uint sector)
acquire(&ide_lock);
c = ide_start_read(dev & 0xff, sector, b->data, 1);
- // sleep (c, &ide_lock);
+ sleep (c, &ide_lock);
ide_finish_read(c);
release(&ide_lock);
diff --git a/defs.h b/defs.h
index c6c333b..1c28cc0 100644
--- a/defs.h
+++ b/defs.h
@@ -57,8 +57,14 @@ void lapic_timerinit(void);
void lapic_timerintr(void);
void lapic_enableintr(void);
void lapic_disableintr(void);
+void lapic_eoi(void);
int cpu(void);
+// ioapic
+extern uchar ioapic_id;
+void ioapic_init(void);
+void ioapic_enable (int irq, int cpu);
+
// spinlock.c
struct spinlock;
void acquire(struct spinlock*);
diff --git a/ide.c b/ide.c
index 27a76fb..e2235a1 100644
--- a/ide.c
+++ b/ide.c
@@ -45,9 +45,12 @@ ide_wait_ready(int check_error)
void
ide_init(void)
{
- cprintf("ide_init: enable IRQ 14\n");
- irq_setmask_8259A(irq_mask_8259A & ~(1<<14));
+ if (ncpu < 2) {
+ panic ("ide_init: disk interrupt is going to the second cpu\n");
+ }
+ ioapic_enable (14, 1); // 14 is IRQ # for IDE
ide_wait_ready(0);
+ cprintf ("ide_init:done\n");
}
void
@@ -57,6 +60,7 @@ ide_intr(void)
cprintf("%d: ide_intr\n", cpu());
wakeup(&request[tail]);
release(&ide_lock);
+ lapic_eoi();
}
int
diff --git a/ioapic.c b/ioapic.c
new file mode 100644
index 0000000..776f895
--- /dev/null
+++ b/ioapic.c
@@ -0,0 +1,82 @@
+#include "types.h"
+#include "mp.h"
+#include "defs.h"
+#include "x86.h"
+#include "traps.h"
+#include "ioapic.h"
+
+struct ioapic {
+ uint ioregsel; uint p01; uint p02; uint p03;
+ uint iowin; uint p11; uint p12; uint p13;
+};
+
+
+#define IOAPIC_REDTBL_LO(i) (IOAPIC_REDTBL + (i) * 2)
+#define IOAPIC_REDTBL_HI(i) (IOAPIC_REDTBL_LO(i) + 1)
+
+static uint
+ioapic_read(struct ioapic *io, int reg)
+{
+ io->ioregsel = reg;
+ return (io->iowin);
+}
+
+static void
+ioapic_write(struct ioapic *io, int reg, uint val)
+{
+ io->ioregsel = reg;
+ io->iowin = val;
+}
+
+void
+ioapic_init(void)
+{
+ struct ioapic *io;
+ uint l, h;
+ int nintr;
+ 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");
+ cprintf ("ioapic VER: 0x%x id %d nintr %d\n", l, id, nintr);
+ 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 and that all
+ 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);
+ // cprintf("intr %d: lo 0x%x hi 0x%x\n", i, l, h);
+ }
+}
+
+void
+ioapic_enable (int irq, int cpu)
+{
+ 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 |= (cpu << APIC_ID_SHIFT); // for fun, disk interrupts to cpu 1
+ ioapic_write(io, IOAPIC_REDTBL_HI(irq), h);
+ cprintf("intr %d: lo 0x%x hi 0x%x\n", irq, l, h);
+}
diff --git a/ioapic.h b/ioapic.h
new file mode 100644
index 0000000..cd2fd5c
--- /dev/null
+++ b/ioapic.h
@@ -0,0 +1,90 @@
+#define IO_APIC_BASE 0xFEC00000 /* default physical locations of an IO APIC */
+#define IOAPIC_WINDOW 0x10 /* window register offset */
+
+/* constants relating to APIC ID registers */
+#define APIC_ID_MASK 0xff000000
+#define APIC_ID_SHIFT 24
+#define APIC_ID_CLUSTER 0xf0
+#define APIC_ID_CLUSTER_ID 0x0f
+#define APIC_MAX_CLUSTER 0xe
+#define APIC_MAX_INTRACLUSTER_ID 3
+#define APIC_ID_CLUSTER_SHIFT 4
+
+/* fields in VER */
+#define APIC_VER_VERSION 0x000000ff
+#define APIC_VER_MAXLVT 0x00ff0000
+#define MAXLVTSHIFT 16
+
+/* Indexes into IO APIC */
+#define IOAPIC_ID 0x00
+#define IOAPIC_VER 0x01
+#define IOAPIC_ARB 0x02
+#define IOAPIC_REDTBL 0x10
+#define IOAPIC_REDTBL0 IOAPIC_REDTBL
+#define IOAPIC_REDTBL1 (IOAPIC_REDTBL+0x02)
+#define IOAPIC_REDTBL2 (IOAPIC_REDTBL+0x04)
+#define IOAPIC_REDTBL3 (IOAPIC_REDTBL+0x06)
+#define IOAPIC_REDTBL4 (IOAPIC_REDTBL+0x08)
+#define IOAPIC_REDTBL5 (IOAPIC_REDTBL+0x0a)
+#define IOAPIC_REDTBL6 (IOAPIC_REDTBL+0x0c)
+#define IOAPIC_REDTBL7 (IOAPIC_REDTBL+0x0e)
+#define IOAPIC_REDTBL8 (IOAPIC_REDTBL+0x10)
+#define IOAPIC_REDTBL9 (IOAPIC_REDTBL+0x12)
+#define IOAPIC_REDTBL10 (IOAPIC_REDTBL+0x14)
+#define IOAPIC_REDTBL11 (IOAPIC_REDTBL+0x16)
+#define IOAPIC_REDTBL12 (IOAPIC_REDTBL+0x18)
+#define IOAPIC_REDTBL13 (IOAPIC_REDTBL+0x1a)
+#define IOAPIC_REDTBL14 (IOAPIC_REDTBL+0x1c)
+#define IOAPIC_REDTBL15 (IOAPIC_REDTBL+0x1e)
+#define IOAPIC_REDTBL16 (IOAPIC_REDTBL+0x20)
+#define IOAPIC_REDTBL17 (IOAPIC_REDTBL+0x22)
+#define IOAPIC_REDTBL18 (IOAPIC_REDTBL+0x24)
+#define IOAPIC_REDTBL19 (IOAPIC_REDTBL+0x26)
+#define IOAPIC_REDTBL20 (IOAPIC_REDTBL+0x28)
+#define IOAPIC_REDTBL21 (IOAPIC_REDTBL+0x2a)
+#define IOAPIC_REDTBL22 (IOAPIC_REDTBL+0x2c)
+#define IOAPIC_REDTBL23 (IOAPIC_REDTBL+0x2e)
+
+/*
+ * fields in the IO APIC's redirection table entries
+ */
+#define IOART_DEST APIC_ID_MASK /* broadcast addr: all APICs */
+
+#define IOART_RESV 0x00fe0000 /* reserved */
+
+#define IOART_INTMASK 0x00010000 /* R/W: INTerrupt mask */
+#define IOART_INTMCLR 0x00000000 /* clear, allow INTs */
+#define IOART_INTMSET 0x00010000 /* set, inhibit INTs */
+
+#define IOART_TRGRMOD 0x00008000 /* R/W: trigger mode */
+#define IOART_TRGREDG 0x00000000 /* edge */
+#define IOART_TRGRLVL 0x00008000 /* level */
+
+#define IOART_REM_IRR 0x00004000 /* RO: remote IRR */
+
+#define IOART_INTPOL 0x00002000 /* R/W: INT input pin polarity */
+#define IOART_INTAHI 0x00000000 /* active high */
+#define IOART_INTALO 0x00002000 /* active low */
+
+#define IOART_DELIVS 0x00001000 /* RO: delivery status */
+
+#define IOART_DESTMOD 0x00000800 /* R/W: destination mode */
+#define IOART_DESTPHY 0x00000000 /* physical */
+#define IOART_DESTLOG 0x00000800 /* logical */
+
+#define IOART_DELMOD 0x00000700 /* R/W: delivery mode */
+#define IOART_DELFIXED 0x00000000 /* fixed */
+#define IOART_DELLOPRI 0x00000100 /* lowest priority */
+#define IOART_DELSMI 0x00000200 /* System Management INT */
+#define IOART_DELRSV1 0x00000300 /* reserved */
+#define IOART_DELNMI 0x00000400 /* NMI signal */
+#define IOART_DELINIT 0x00000500 /* INIT signal */
+#define IOART_DELRSV2 0x00000600 /* reserved */
+#define IOART_DELEXINT 0x00000700 /* External INTerrupt */
+
+#define IOART_INTVEC 0x000000ff /* R/W: INTerrupt vector field */
+
+/* fields in VER */
+#define IOART_VER_VERSION 0x000000ff
+#define IOART_VER_MAXREDIR 0x00ff0000
+#define MAXREDIRSHIFT 16
diff --git a/lapic.c b/lapic.c
index 3aeda2f..f299b86 100644
--- a/lapic.c
+++ b/lapic.c
@@ -173,6 +173,12 @@ lapic_disableintr(void)
lapic_write(LAPIC_TPR, 0xFF);
}
+void
+lapic_eoi(void)
+{
+ lapic_write (LAPIC_EOI, 0);
+}
+
int
cpu(void)
{
diff --git a/main.c b/main.c
index 3db7eab..021fb51 100644
--- a/main.c
+++ b/main.c
@@ -45,6 +45,7 @@ main0(void)
cprintf("\nxV6\n\n");
pic_init(); // initialize PIC
+ ioapic_init();
kinit(); // physical memory allocator
tvinit(); // trap vectors
idtinit(); // CPU's idt
diff --git a/mp.c b/mp.c
index 4cb5db8..ece46a4 100644
--- a/mp.c
+++ b/mp.c
@@ -29,12 +29,12 @@ static char* buses[] = {
0,
};
-#define APBOOTCODE 0x7000 // XXX hack
-
-static struct mp* mp; // The MP floating point structure
struct cpu cpus[NCPU];
int ncpu;
+uchar ioapic_id;
+
static struct cpu *bcpu;
+static struct mp* mp; // The MP floating point structure
static struct mp*
mp_scan(uchar *addr, int len)
@@ -112,7 +112,6 @@ mp_detect(void)
if(sum || (pcmp->version != 1 && pcmp->version != 4))
return 3;
- cprintf("Mp spec rev #: %x imcrp 0x%x\n", mp->specrev, mp->imcrp);
return 0;
}
@@ -124,12 +123,15 @@ mp_init(void)
struct mpctb *mpctb;
struct mppe *proc;
struct mpbe *bus;
+ struct mpioapic *ioapic;
+ struct mpie *intr;
int i;
+ uchar byte;
ncpu = 0;
if ((r = mp_detect()) != 0) return;
- cprintf ("This computer is a multiprocessor!\n");
+ cprintf("Mp spec rev #: %x imcrp 0x%x\n", mp->specrev, mp->imcrp);
/*
* Run through the table saving information needed for starting
@@ -164,11 +166,14 @@ mp_init(void)
p += sizeof(struct mpbe);
continue;
case MPIOAPIC:
- cprintf("an I/O APIC\n");
+ ioapic = (struct mpioapic *) p;
+ cprintf("an I/O APIC: id %d %x\n", ioapic->apicno, ioapic->flags);
+ ioapic_id = ioapic->apicno;
p += sizeof(struct mpioapic);
continue;
case MPIOINTR:
- cprintf("an I/O intr\n");
+ intr = (struct mpie *) p;
+ // cprintf("an I/O intr: type %d flags 0x%x bus %d souce bus irq %d dest ioapic id %d dest ioapic intin %d\n", intr->intr, intr->flags, intr->busno, intr->irq, intr->apicno, intr->intin);
p += sizeof(struct mpie);
continue;
default:
@@ -180,10 +185,18 @@ mp_init(void)
break;
}
}
-
+
+ if (mp->imcrp) { // it appears that bochs doesn't support IMCR, and code won't run
+ outb(0x22, 0x70); /* select IMCR */
+ byte = inb(0x23); /* current contents */
+ byte |= 0x01; /* mask external INTR */
+ outb(0x23, byte); /* disconnect 8259s/NMI */
+ }
+
cprintf("ncpu: %d boot %d\n", ncpu, bcpu-cpus);
}
+
int
mp_bcpu(void)
{
@@ -192,6 +205,8 @@ mp_bcpu(void)
extern void mpmain(void);
+#define APBOOTCODE 0x7000 // XXX hack
+
void
mp_startthem(void)
{
diff --git a/picirq.c b/picirq.c
index 9818090..e774e6d 100644
--- a/picirq.c
+++ b/picirq.c
@@ -67,7 +67,6 @@ pic_init(void)
if (irq_mask_8259A != 0xFFFF)
irq_setmask_8259A(irq_mask_8259A);
-
}
void
diff --git a/syscall.c b/syscall.c
index 43be534..77a16cd 100644
--- a/syscall.c
+++ b/syscall.c
@@ -415,6 +415,7 @@ sys_block(void)
struct inode *ip;
for (i = 0; i < 2; i++) {
+ cprintf ("issue read\n");
b = bread(1, i);
cprintf("disk 1 sector %d: ", i);