timer interrupts
disk interrupts (assuming bochs has a bug)
This commit is contained in:
parent
8b4e2a08fe
commit
b22d898297
9 changed files with 185 additions and 138 deletions
6
defs.h
6
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);
|
||||
|
|
121
ide.c
121
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;
|
||||
int r;
|
||||
|
||||
if(nsecs > 256)
|
||||
panic("ide_read");
|
||||
if(nsecs > 256)
|
||||
panic("ide_read");
|
||||
|
||||
ide_wait_ready(0);
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
6
main.c
6
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
|
||||
|
|
61
mp.c
61
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:
|
||||
|
|
111
picirq.c
111
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);
|
||||
|
||||
// mask all interrupts
|
||||
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
|
||||
// h: 0 = cascaded PICs, 1 = master only
|
||||
// i: 0 = no ICW4, 1 = ICW4 required
|
||||
outb(IO_PIC1, 0x11);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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
|
||||
|
||||
// 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 */
|
||||
|
||||
// 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 */
|
||||
|
||||
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
|
||||
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");
|
||||
}
|
||||
|
|
1
proc.h
1
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()
|
||||
};
|
||||
|
||||
|
|
11
string.c
11
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);
|
||||
}
|
||||
|
|
1
trap.c
1
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
|
||||
|
||||
|
|
5
x86.h
5
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
|
||||
|
|
Loading…
Reference in a new issue