diff options
| -rw-r--r-- | defs.h | 6 | ||||
| -rw-r--r-- | ide.c | 127 | ||||
| -rw-r--r-- | main.c | 6 | ||||
| -rw-r--r-- | mp.c | 61 | ||||
| -rw-r--r-- | picirq.c | 131 | ||||
| -rw-r--r-- | proc.h | 1 | ||||
| -rw-r--r-- | string.c | 11 | ||||
| -rw-r--r-- | trap.c | 1 | ||||
| -rw-r--r-- | x86.h | 5 | 
9 files changed, 198 insertions, 151 deletions
@@ -25,11 +25,13 @@ void * memcpy(void *dst, void *src, unsigned n);  void * memset(void *dst, int c, unsigned n);  int memcmp(const void *v1, const void *v2, unsigned n);  void *memmove(void *dst, const void *src, unsigned n); +int strncmp(const char *p, const char *q, unsigned n);  // syscall.c  void syscall(void);  // picirq.c +extern uint16_t irq_mask_8259A;  void irq_setmask_8259A(uint16_t mask);  void pic_init(void); @@ -66,3 +68,7 @@ struct fd * fd_alloc();  void fd_close(struct fd *);  int fd_read(struct fd *fd, char *addr, int n);  int fd_write(struct fd *fd, char *addr, int n); + +// ide.c +void ide_init(void); +int ide_read(uint32_t secno, void *dst, unsigned nsecs); @@ -21,97 +21,104 @@ static int diskno = 0;  static int  ide_wait_ready(int check_error)  { -	int r; +  int r; -	while (((r = inb(0x1F7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) -		/* do nothing */; +  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; +  if (check_error && (r & (IDE_DF|IDE_ERR)) != 0) +    return -1; +  return 0;  } +void +ide_init(void) +{ +  cprintf("ide_init: enable IRQ 14\n"); +  irq_setmask_8259A(irq_mask_8259A & ~(1<<14)); +  ide_wait_ready(0); +} + +  int  ide_probe_disk1(void)  { -	int r, x; +  int r, x; -	// wait for Device 0 to be ready -	ide_wait_ready(0); +  // wait for Device 0 to be ready +  ide_wait_ready(0); -	// switch to Device 1 -	outb(0x1F6, 0xE0 | (1<<4)); +  // 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 */; +  // 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)); +  // switch back to Device 0 +  outb(0x1F6, 0xE0 | (0<<4)); -	cprintf("Device 1 presence: %d\n", (x < 1000)); -	return (x < 1000); +  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; +  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); -	} +  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 +    +  for (; nsecs > 0; nsecs--, dst += 512) { +    if ((r = ide_wait_ready(1)) < 0) +      return r; +    insl(0x1F0, dst, 512/4); +  } -	return 0; +  return 0;  }  int  ide_write(uint32_t secno, const void *src, unsigned nsecs)  { -	int r; +  int r; -        if(nsecs > 256) -          panic("ide_write"); +  if(nsecs > 256) +    panic("ide_write"); -	ide_wait_ready(0); +  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 +  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); -	} +  for (; nsecs > 0; nsecs--, src += 512) { +    if ((r = ide_wait_ready(1)) < 0) +      return r; +    outsl(0x1F0, src, 512/4); +  } -	return 0; +  return 0;  } @@ -36,7 +36,7 @@ main()    cprintf("\nxV6\n\n"); -  pic_init(); // initialize PIC---not clear why +  pic_init(); // initialize PIC    mp_init(); // multiprocessor    kinit(); // physical memory allocator    tvinit(); // trap vectors @@ -59,12 +59,14 @@ main()    p->ppid = 0;    setupsegs(p); +  write_eflags(read_eflags() | FL_IF); +    // turn on interrupts on boot processor    lapic_timerinit();    lapic_enableintr(); -  write_eflags(read_eflags() | FL_IF);  #if 0 +  ide_init();    ide_read(0, buf, 1);    cprintf("sec0.0 %x\n", buf[0] & 0xff);  #endif @@ -92,6 +92,28 @@ enum {					/* LAPIC_TDCR */    LAPIC_X1 = 0x0000000B,	/* divide by 1 */  }; +static char* buses[] = { +	"CBUSI ", +	"CBUSII", +	"EISA  ", +	"FUTURE", +	"INTERN", +	"ISA   ", +	"MBI   ", +	"MBII  ", +	"MCA   ", +	"MPI   ", +	"MPSA  ", +	"NUBUS ", +	"PCI   ", +	"PCMCIA", +	"TC    ", +	"VL    ", +	"VME   ", +	"XPRESS", +	0, +}; +  #define APBOOTCODE 0x7000 // XXX hack  static struct MP* mp;  // The MP floating point structure @@ -126,7 +148,7 @@ lapic_timerinit()  void  lapic_timerintr()  { -  // cprintf("%d: timer interrupt!\n", cpu()); +  cprintf("%d: timer interrupt!\n", cpu());    lapic_write (LAPIC_EOI, 0);  } @@ -137,23 +159,17 @@ lapic_init(int c)    cprintf("lapic_init %d\n", c); -  irq_setmask_8259A(0xFFFF); +  lapic_write(LAPIC_DFR, 0xFFFFFFFF); // set destination format register +  r = (lapic_read(LAPIC_ID)>>24) & 0xFF; // read APIC ID +  lapic_write(LAPIC_LDR, (1<<r)<<24);  // set logical destination register to r +  lapic_write(LAPIC_TPR, 0xFF);  // no interrupts for now +  lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS));  // enable APIC -  lapic_write(LAPIC_DFR, 0xFFFFFFFF); -  r = (lapic_read(LAPIC_ID)>>24) & 0xFF; -  lapic_write(LAPIC_LDR, (1<<r)<<24); -  lapic_write(LAPIC_TPR, 0xFF); -  lapic_write(LAPIC_SVR, LAPIC_ENABLE|(IRQ_OFFSET+IRQ_SPURIOUS)); +  // in virtual wire mode, set up the LINT0 and LINT1 as follows: +  lapic_write(LAPIC_LINT0, APIC_IMASK | APIC_EXTINT); +  lapic_write(LAPIC_LINT1, APIC_IMASK | APIC_NMI); -  /* -   * Set the local interrupts. It's likely these should just be -   * masked off for SMP mode as some Pentium Pros have problems if -   * LINT[01] are set to ExtINT. -   * Acknowledge any outstanding interrupts. -   */ -  lapic_write(LAPIC_LINT0, cpus[c].lintr[0]); -  lapic_write(LAPIC_LINT1, cpus[c].lintr[1]); -  lapic_write(LAPIC_EOI, 0); +  lapic_write(LAPIC_EOI, 0); // acknowledge any outstanding interrupts.    lvt = (lapic_read(LAPIC_VER)>>16) & 0xFF;    if(lvt >= 4) @@ -290,7 +306,7 @@ mp_detect(void)    if(sum || (pcmp->version != 1 && pcmp->version != 4))      return 3; -  cprintf("Mp spec rev #: %x\n", mp->specrev); +  cprintf("Mp spec rev #: %x imcrp 0x%x\n", mp->specrev, mp->imcrp);    return 0;  } @@ -308,8 +324,10 @@ mp_init()    uint8_t *p, *e;    struct MPCTB *mpctb;    struct MPPE *proc; +  struct MPBE *bus;    int c;    extern int main(); +  int i;    ncpu = 0;    if ((r = mp_detect()) != 0) return; @@ -332,8 +350,6 @@ mp_init()      case MPPROCESSOR:        proc = (struct MPPE *) p;        cpus[ncpu].apicid = proc->apicid; -      cpus[ncpu].lintr[0] = APIC_IMASK; -      cpus[ncpu].lintr[1] = APIC_IMASK;        cprintf("a processor %x\n", cpus[ncpu].apicid);        if (proc->flags & MPBP) {  	bcpu = &cpus[ncpu]; @@ -342,6 +358,12 @@ mp_init()        p += sizeof(struct MPPE);        continue;      case MPBUS: +      bus = (struct MPBE *) p; +      for(i = 0; buses[i]; i++){ +	if(strncmp(buses[i], bus->string, sizeof(bus->string)) == 0) +	  break; +      } +      cprintf("a bus %d\n", i);        p += sizeof(struct MPBE);        continue;      case MPIOAPIC: @@ -349,6 +371,7 @@ mp_init()        p += sizeof(struct MPIOAPIC);        continue;      case MPIOINTR: +      cprintf("an I/O intr\n");        p += sizeof(struct MPIE);        continue;      default: @@ -4,80 +4,85 @@  #include "x86.h"  #include "defs.h" +// 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 +  // 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); +  // 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, 0x3);			// 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"); +  int i; +  irq_mask_8259A = mask; + +  outb(IO_PIC1+1, (char)mask); +  outb(IO_PIC2+1, (char)(mask >> 8)); + +  cprintf("%d: enabled interrupts:", cpu()); + +  for (i = 0; i < 16; i++) +    if (~mask & (1<<i)) +      cprintf(" %d", i); +  cprintf("\n");  } @@ -42,7 +42,6 @@ extern struct proc *curproc[NCPU];  struct cpu {    uint8_t apicid;       // Local APIC ID -  int lintr[2];		// Local APIC    char mpstack[MPSTACK]; // per-cpu start-up stack, only used to get into main()  }; @@ -58,3 +58,14 @@ memmove(void *dst, const void *src, unsigned n)    return dst;  } + +int +strncmp(const char *p, const char *q, unsigned n) +{ +	while (n > 0 && *p && *p == *q) +		n--, p++, q++; +	if (n == 0) +		return 0; +	else +		return (int) ((unsigned char) *p - (unsigned char) *q); +} @@ -61,7 +61,6 @@ trap(struct Trapframe *tf)      return;    } -  cprintf("trap %d eip %x:%x\n", tf->tf_trapno, tf->tf_cs, tf->tf_eip);    // XXX probably ought to lgdt on trap return @@ -352,11 +352,6 @@ struct Trapframe {  #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  #define IRQ_ERROR       19  | 
