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 \
|
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
|
CC = i386-jos-elf-gcc
|
||||||
LD = i386-jos-elf-ld
|
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
|
// syscall.c
|
||||||
void syscall(void);
|
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[];
|
extern char edata[], end[];
|
||||||
|
|
||||||
|
char buf[512];
|
||||||
|
|
||||||
int
|
int
|
||||||
main()
|
main()
|
||||||
{
|
{
|
||||||
|
@ -18,16 +20,11 @@ main()
|
||||||
// clear BSS
|
// clear BSS
|
||||||
memset(edata, 0, end - edata);
|
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");
|
cprintf("\nxV6\n\n");
|
||||||
|
|
||||||
kinit(); // physical memory allocator
|
kinit(); // physical memory allocator
|
||||||
tinit(); // traps and interrupts
|
tinit(); // traps and interrupts
|
||||||
|
pic_init();
|
||||||
|
|
||||||
// create fake process zero
|
// create fake process zero
|
||||||
p = &proc[0];
|
p = &proc[0];
|
||||||
|
@ -46,6 +43,16 @@ main()
|
||||||
p->ppid = 0;
|
p->ppid = 0;
|
||||||
setupsegs(p);
|
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();
|
p = newproc();
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -73,6 +80,7 @@ main()
|
||||||
p->mem[i++] = T_SYSCALL;
|
p->mem[i++] = T_SYSCALL;
|
||||||
p->tf->tf_eip = 0;
|
p->tf->tf_eip = 0;
|
||||||
p->tf->tf_esp = p->sz;
|
p->tf->tf_esp = p->sz;
|
||||||
|
#endif
|
||||||
|
|
||||||
swtch();
|
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