diff options
author | rtm <rtm> | 2006-06-16 20:29:25 +0000 |
---|---|---|
committer | rtm <rtm> | 2006-06-16 20:29:25 +0000 |
commit | ae6e8aa730fa410118c0532938d4a9e62b08bbe8 (patch) | |
tree | 8341e238d7b725a2aeec1476bc0f46c46b5c90e8 | |
parent | be0a7eacdab4443199ed0ed4379a84edc7c98fd6 (diff) | |
download | xv6-labs-ae6e8aa730fa410118c0532938d4a9e62b08bbe8.tar.gz xv6-labs-ae6e8aa730fa410118c0532938d4a9e62b08bbe8.tar.bz2 xv6-labs-ae6e8aa730fa410118c0532938d4a9e62b08bbe8.zip |
checkpoint
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | defs.h | 4 | ||||
-rw-r--r-- | ide.c | 117 | ||||
-rw-r--r-- | main.c | 20 | ||||
-rw-r--r-- | picirq.c | 92 |
5 files changed, 228 insertions, 7 deletions
@@ -1,5 +1,5 @@ OBJS = main.o console.o string.o kalloc.o proc.o trapasm.o trap.o vectors.o \ - syscall.o + syscall.o ide.o picirq.o CC = i386-jos-elf-gcc LD = i386-jos-elf-ld @@ -24,3 +24,7 @@ void * memset(void *dst, int c, unsigned n); // syscall.c void syscall(void); + +// picirq.c +void irq_setmask_8259A(uint16_t mask); +void pic_init(void); @@ -0,0 +1,117 @@ +/* + * Minimal PIO-based (non-interrupt-driven) IDE driver code. + * For information about what all this IDE/ATA magic means, + * see the materials available on the class references page. + */ + +#include "types.h" +#include "param.h" +#include "mmu.h" +#include "proc.h" +#include "defs.h" +#include "x86.h" + +#define IDE_BSY 0x80 +#define IDE_DRDY 0x40 +#define IDE_DF 0x20 +#define IDE_ERR 0x01 + +static int diskno = 0; + +static int +ide_wait_ready(int check_error) +{ + int r; + + 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; +} + +int +ide_probe_disk1(void) +{ + int r, x; + + // wait for Device 0 to be ready + ide_wait_ready(0); + + // 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 */; + + // switch back to Device 0 + outb(0x1F6, 0xE0 | (0<<4)); + + 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; +} + +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); + } + + return 0; +} + +int +ide_write(uint32_t secno, const void *src, unsigned nsecs) +{ + int r; + + if(nsecs > 256) + panic("ide_write"); + + 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 + + for (; nsecs > 0; nsecs--, src += 512) { + if ((r = ide_wait_ready(1)) < 0) + return r; + outsl(0x1F0, src, 512/4); + } + + return 0; +} @@ -9,6 +9,8 @@ extern char edata[], end[]; +char buf[512]; + int main() { @@ -18,16 +20,11 @@ main() // clear BSS memset(edata, 0, end - edata); - // partially initizialize PIC - outb(0x20+1, 0xFF); // IO_PIC1 - outb(0xA0+1, 0xFF); // IO_PIC2 - outb(0x20, 0x11); - outb(0x20+1, 32); - cprintf("\nxV6\n\n"); kinit(); // physical memory allocator tinit(); // traps and interrupts + pic_init(); // create fake process zero p = &proc[0]; @@ -46,6 +43,16 @@ main() p->ppid = 0; setupsegs(p); + // turn on interrupts + write_eflags(read_eflags() | FL_IF); + irq_setmask_8259A(0); + +#if 1 + ide_read(0, buf, 1); + cprintf("sec0.0 %x\n", buf[0] & 0xff); +#endif + +#if 0 p = newproc(); i = 0; @@ -73,6 +80,7 @@ main() p->mem[i++] = T_SYSCALL; p->tf->tf_eip = 0; p->tf->tf_esp = p->sz; +#endif swtch(); diff --git a/picirq.c b/picirq.c new file mode 100644 index 0000000..5fc90c5 --- /dev/null +++ b/picirq.c @@ -0,0 +1,92 @@ +/* See COPYRIGHT for copyright information. */ + +#include "types.h" +#include "x86.h" +#include "defs.h" + +#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 + +// 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); +} + +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"); +} |