]> hydra-www.ietfng.org Git - xv6-public/commitdiff
New IDE header, adjusted IDE driver code, nits.
authorPeter H. Froehlich <peter.hans.froehlich@gmail.com>
Sun, 27 Sep 2015 19:40:21 +0000 (15:40 -0400)
committerPeter H. Froehlich <peter.hans.froehlich@gmail.com>
Sun, 27 Sep 2015 19:40:21 +0000 (15:40 -0400)
bootmain.c
ide.c
ide.h [new file with mode: 0644]

index 97d525872772955ae85d4f0de78df1aea14ddfaf..2010d6fc69ca335d60bdf7351292601c462e2dfc 100644 (file)
@@ -1,5 +1,5 @@
 // Boot loader.
-// 
+//
 // Part of the boot block, along with bootasm.S, which calls bootmain().
 // bootasm.S has put the processor into protected 32-bit mode.
 // bootmain() loads an ELF kernel image from the disk starting at
@@ -9,8 +9,7 @@
 #include "elf.h"
 #include "x86.h"
 #include "memlayout.h"
-
-#define SECTSIZE  512
+#include "ide.h"
 
 void readseg(uchar*, uint, uint);
 
@@ -51,7 +50,7 @@ void
 waitdisk(void)
 {
   // Wait for disk ready.
-  while((inb(0x1F7) & 0xC0) != 0x40)
+  while((inb(IDE_DATA_PRIMARY+IDE_REG_STATUS) & 0xC0) != 0x40)
     ;
 }
 
@@ -61,16 +60,16 @@ readsect(void *dst, uint offset)
 {
   // Issue command.
   waitdisk();
-  outb(0x1F2, 1);   // count = 1
-  outb(0x1F3, offset);
-  outb(0x1F4, offset >> 8);
-  outb(0x1F5, offset >> 16);
-  outb(0x1F6, (offset >> 24) | 0xE0);
-  outb(0x1F7, 0x20);  // cmd 0x20 - read sectors
+  outb(IDE_DATA_PRIMARY+IDE_REG_SECTORS, 1);   // count = 1
+  outb(IDE_DATA_PRIMARY+IDE_REG_LBA0, offset);
+  outb(IDE_DATA_PRIMARY+IDE_REG_LBA1, offset >> 8);
+  outb(IDE_DATA_PRIMARY+IDE_REG_LBA2, offset >> 16);
+  outb(IDE_DATA_PRIMARY+IDE_REG_DISK, (offset >> 24) | 0xE0);
+  outb(IDE_DATA_PRIMARY+IDE_REG_COMMAND, IDE_CMD_READ);  // cmd 0x20 - read sectors
 
   // Read data.
   waitdisk();
-  insl(0x1F0, dst, SECTSIZE/4);
+  insl(IDE_DATA_PRIMARY+IDE_REG_DATA, dst, SECTOR_SIZE/4);
 }
 
 // Read 'count' bytes at 'offset' from kernel into physical address 'pa'.
@@ -83,14 +82,14 @@ readseg(uchar* pa, uint count, uint offset)
   epa = pa + count;
 
   // Round down to sector boundary.
-  pa -= offset % SECTSIZE;
+  pa -= offset % SECTOR_SIZE;
 
   // Translate from bytes to sectors; kernel starts at sector 1.
-  offset = (offset / SECTSIZE) + 1;
+  offset = (offset / SECTOR_SIZE) + 1;
 
   // If this is too slow, we could read lots of sectors at a time.
   // We'd write more to memory than asked, but it doesn't matter --
   // we load in increasing order.
-  for(; pa < epa; pa += SECTSIZE, offset++)
+  for(; pa < epa; pa += SECTOR_SIZE, offset++)
     readsect(pa, offset);
 }
diff --git a/ide.c b/ide.c
index ed5a572ec6e395ea0272d5d2a3a4125e544f28c2..1b0e63ea6e88c1c597f1db79b6ef08ac268be34d 100644 (file)
--- a/ide.c
+++ b/ide.c
 #include "spinlock.h"
 #include "fs.h"
 #include "buf.h"
-
-#define SECTOR_SIZE   512
-#define IDE_BSY       0x80
-#define IDE_DRDY      0x40
-#define IDE_DF        0x20
-#define IDE_ERR       0x01
-
-#define IDE_CMD_READ  0x20
-#define IDE_CMD_WRITE 0x30
+#include "ide.h"
 
 // idequeue points to the buf now being read/written to the disk.
 // idequeue->qnext points to the next buf to be processed.
@@ -37,7 +29,7 @@ idewait(int checkerr)
 {
   int r;
 
-  while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) 
+  while(((r = inb(IDE_DATA_PRIMARY+IDE_REG_STATUS)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY)
     ;
   if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0)
     return -1;
@@ -48,23 +40,23 @@ void
 ideinit(void)
 {
   int i;
-  
+
   initlock(&idelock, "ide");
   picenable(IRQ_IDE);
   ioapicenable(IRQ_IDE, ncpu - 1);
   idewait(0);
-  
+
   // Check if disk 1 is present
-  outb(0x1f6, 0xe0 | (1<<4));
+  outb(IDE_DATA_PRIMARY+IDE_REG_DISK, 0xe0 | (1<<4));
   for(i=0; i<1000; i++){
-    if(inb(0x1f7) != 0){
+    if(inb(IDE_DATA_PRIMARY+IDE_REG_STATUS) != 0){
       havedisk1 = 1;
       break;
     }
   }
-  
+
   // Switch back to disk 0.
-  outb(0x1f6, 0xe0 | (0<<4));
+  outb(IDE_DATA_PRIMARY+IDE_REG_DISK, 0xe0 | (0<<4));
 }
 
 // Start the request for b.  Caller must hold idelock.
@@ -79,19 +71,19 @@ idestart(struct buf *b)
   int sector = b->blockno * sector_per_block;
 
   if (sector_per_block > 7) panic("idestart");
-  
+
   idewait(0);
-  outb(0x3f6, 0);  // generate interrupt
-  outb(0x1f2, sector_per_block);  // number of sectors
-  outb(0x1f3, sector & 0xff);
-  outb(0x1f4, (sector >> 8) & 0xff);
-  outb(0x1f5, (sector >> 16) & 0xff);
-  outb(0x1f6, 0xe0 | ((b->dev&1)<<4) | ((sector>>24)&0x0f));
+  outb(IDE_CTRL_PRIMARY+IDE_REG_CTRL, 0);  // generate interrupt
+  outb(IDE_DATA_PRIMARY+IDE_REG_SECTORS, sector_per_block);  // number of sectors
+  outb(IDE_DATA_PRIMARY+IDE_REG_LBA0, sector & 0xff);
+  outb(IDE_DATA_PRIMARY+IDE_REG_LBA1, (sector >> 8) & 0xff);
+  outb(IDE_DATA_PRIMARY+IDE_REG_LBA2, (sector >> 16) & 0xff);
+  outb(IDE_DATA_PRIMARY+IDE_REG_DISK, 0xe0 | ((b->dev&1)<<4) | ((sector>>24)&0x0f));
   if(b->flags & B_DIRTY){
-    outb(0x1f7, IDE_CMD_WRITE);
-    outsl(0x1f0, b->data, BSIZE/4);
+    outb(IDE_DATA_PRIMARY+IDE_REG_COMMAND, IDE_CMD_WRITE);
+    outsl(IDE_DATA_PRIMARY+IDE_REG_DATA, b->data, BSIZE/4);
   } else {
-    outb(0x1f7, IDE_CMD_READ);
+    outb(IDE_DATA_PRIMARY+IDE_REG_COMMAND, IDE_CMD_READ);
   }
 }
 
@@ -112,13 +104,13 @@ ideintr(void)
 
   // Read data if needed.
   if(!(b->flags & B_DIRTY) && idewait(1) >= 0)
-    insl(0x1f0, b->data, BSIZE/4);
-  
+    insl(IDE_DATA_PRIMARY+IDE_REG_DATA, b->data, BSIZE/4);
+
   // Wake process waiting for this buf.
   b->flags |= B_VALID;
   b->flags &= ~B_DIRTY;
   wakeup(b);
-  
+
   // Start disk on next buf in queue.
   if(idequeue != 0)
     idestart(idequeue);
@@ -127,7 +119,7 @@ ideintr(void)
 }
 
 //PAGEBREAK!
-// Sync buf with disk. 
+// Sync buf with disk.
 // If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID.
 // Else if B_VALID is not set, read buf from disk, set B_VALID.
 void
@@ -149,11 +141,11 @@ iderw(struct buf *b)
   for(pp=&idequeue; *pp; pp=&(*pp)->qnext)  //DOC:insert-queue
     ;
   *pp = b;
-  
+
   // Start disk if necessary.
   if(idequeue == b)
     idestart(b);
-  
+
   // Wait for request to finish.
   while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){
     sleep(b, &idelock);
diff --git a/ide.h b/ide.h
new file mode 100644 (file)
index 0000000..c2bce5f
--- /dev/null
+++ b/ide.h
@@ -0,0 +1,45 @@
+// This file contains definitions for IDE/ATA disk controllers.
+
+// IDE sectors are 512 bytes long.
+#define SECTOR_SIZE 512
+
+// Base addresses in I/O space for the first two IDE channels,
+// each of which supports up to two drives.
+#define IDE_DATA_PRIMARY   0x1f0
+#define IDE_CTRL_PRIMARY   0x3f4
+#define IDE_DATA_SECONDARY 0x170
+#define IDE_CTRL_SECONDARY 0x374
+
+// DATA registers for each IDE channel; add offsets to relevant
+// DATA base address.
+#define IDE_REG_DATA    0x00 // read/write data from/to disk
+#define IDE_REG_ERROR   0x01
+#define IDE_REG_SECTORS 0x02
+#define IDE_REG_LBA0    0x03
+#define IDE_REG_LBA1    0x04
+#define IDE_REG_LBA2    0x05
+#define IDE_REG_DISK    0x06
+#define IDE_REG_COMMAND 0x07 // write commands
+#define IDE_REG_STATUS  0x07 // read status
+
+// Masks for IDE_REG_DISK.
+#define IDE_DISK_CHS 0xA0 // bits 7 and 5 always set, bit 6 LBA clear
+#define IDE_DISK_LBA 0xE0 // bits 7 and 5 always set, bit 6 LBA set
+
+// Flags read from IDE_REG_STATUS.
+#define IDE_BSY  0x80 // drive busy (with a command?)
+#define IDE_DRDY 0x40 // drive ready (for comment? spun up?)
+#define IDE_DF   0x20 // drive (write?) failure
+#define IDE_DRQ  0x08 // PIO data ready
+#define IDE_ERR  0x01 // error, details in IDE_REG_ERROR
+
+// Commands written to IDE_REG_COMMAND. These are
+// the PIO read/write commands for LBA-28.
+#define IDE_CMD_READ  0x20
+#define IDE_CMD_WRITE 0x30
+#define IDE_CMD_IDENT 0xEC
+
+// CTRL registers for each IDE channel; add offsets
+// to relevant CTRL base address.
+#define IDE_REG_CTRL      0x02 // write device control
+#define IDE_REG_ALTSTATUS 0x02 // read status (without IRQ stuff)