checkpoint

This commit is contained in:
rtm 2006-06-16 20:29:25 +00:00
parent be0a7eacda
commit ae6e8aa730
5 changed files with 228 additions and 7 deletions

View file

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

4
defs.h
View file

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

117
ide.c Normal file
View file

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

20
main.c
View file

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

92
picirq.c Normal file
View file

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