summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--defs.h4
-rw-r--r--ide.c117
-rw-r--r--main.c20
-rw-r--r--picirq.c92
5 files changed, 228 insertions, 7 deletions
diff --git a/Makefile b/Makefile
index fa93f85..81241f4 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/defs.h b/defs.h
index eea3d0c..199ea87 100644
--- a/defs.h
+++ b/defs.h
@@ -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);
diff --git a/ide.c b/ide.c
new file mode 100644
index 0000000..3152f93
--- /dev/null
+++ b/ide.c
@@ -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;
+}
diff --git a/main.c b/main.c
index 43c8c02..2f3b00e 100644
--- a/main.c
+++ b/main.c
@@ -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");
+}