timer interrupts

disk interrupts (assuming bochs has a bug)
This commit is contained in:
kaashoek 2006-07-05 20:00:14 +00:00
parent 8b4e2a08fe
commit b22d898297
9 changed files with 185 additions and 138 deletions

6
defs.h
View file

@ -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);

11
ide.c
View file

@ -31,6 +31,15 @@ ide_wait_ready(int check_error)
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)
{
@ -79,8 +88,6 @@ ide_read(uint32_t secno, void *dst, unsigned nsecs)
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;

6
main.c
View file

@ -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

61
mp.c
View file

@ -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:

View file

@ -4,17 +4,20 @@
#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);
@ -50,7 +53,7 @@ pic_init(void)
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
outb(IO_PIC2+1, 0x3); // ICW4
// OCW3: 0ef01prs
// ef: 0x = NOP, 10 = clear specific mask, 11 = set specific mask
@ -64,6 +67,7 @@ pic_init(void)
if (irq_mask_8259A != 0xFFFF)
irq_setmask_8259A(irq_mask_8259A);
}
void
@ -71,11 +75,12 @@ 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:");
cprintf("%d: enabled interrupts:", cpu());
for (i = 0; i < 16; i++)
if (~mask & (1<<i))
cprintf(" %d", i);

1
proc.h
View file

@ -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()
};

View file

@ -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);
}

1
trap.c
View file

@ -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

5
x86.h
View file

@ -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