checkpoint
This commit is contained in:
parent
be0a7eacda
commit
ae6e8aa730
5 changed files with 228 additions and 7 deletions
2
Makefile
2
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
|
||||
|
|
4
defs.h
4
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);
|
||||
|
|
117
ide.c
Normal file
117
ide.c
Normal 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
20
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();
|
||||
|
||||
|
|
92
picirq.c
Normal file
92
picirq.c
Normal 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");
|
||||
}
|
Loading…
Reference in a new issue