Xv6 with picoc & Linkage editor
v1.0
The project delineate mutual cohesion between c library, linkage editor ( linker), interpreter and operating system by porting the same on xv6 kernel
|
00001 // Simple PIO-based (non-DMA) IDE driver code. 00002 00003 #include "types.h" 00004 #include "defs.h" 00005 #include "param.h" 00006 #include "memlayout.h" 00007 #include "mmu.h" 00008 #include "proc.h" 00009 #include "x86.h" 00010 #include "traps.h" 00011 #include "spinlock.h" 00012 #include "buf.h" 00013 00014 #define IDE_BSY 0x80 00015 #define IDE_DRDY 0x40 00016 #define IDE_DF 0x20 00017 #define IDE_ERR 0x01 00018 00019 #define IDE_CMD_READ 0x20 00020 #define IDE_CMD_WRITE 0x30 00021 00022 // idequeue points to the buf now being read/written to the disk. 00023 // idequeue->qnext points to the next buf to be processed. 00024 // You must hold idelock while manipulating queue. 00025 00026 static struct spinlock idelock; 00027 static struct buf *idequeue; 00028 00029 static int havedisk1; 00030 static void idestart(struct buf*); 00031 00032 // Wait for IDE disk to become ready. 00033 static int 00034 idewait(int checkerr) 00035 { 00036 int r; 00037 00038 while(((r = inb(0x1f7)) & (IDE_BSY|IDE_DRDY)) != IDE_DRDY) 00039 ; 00040 if(checkerr && (r & (IDE_DF|IDE_ERR)) != 0) 00041 return -1; 00042 return 0; 00043 } 00044 00045 void 00046 ideinit(void) 00047 { 00048 int i; 00049 00050 initlock(&idelock, "ide"); 00051 picenable(IRQ_IDE); 00052 ioapicenable(IRQ_IDE, ncpu - 1); 00053 idewait(0); 00054 00055 // Check if disk 1 is present 00056 outb(0x1f6, 0xe0 | (1<<4)); 00057 for(i=0; i<1000; i++){ 00058 if(inb(0x1f7) != 0){ 00059 havedisk1 = 1; 00060 break; 00061 } 00062 } 00063 00064 // Switch back to disk 0. 00065 outb(0x1f6, 0xe0 | (0<<4)); 00066 } 00067 00068 // Start the request for b. Caller must hold idelock. 00069 static void 00070 idestart(struct buf *b) 00071 { 00072 if(b == 0) 00073 panic("idestart"); 00074 00075 idewait(0); 00076 outb(0x3f6, 0); // generate interrupt 00077 outb(0x1f2, 1); // number of sectors 00078 outb(0x1f3, b->sector & 0xff); 00079 outb(0x1f4, (b->sector >> 8) & 0xff); 00080 outb(0x1f5, (b->sector >> 16) & 0xff); 00081 outb(0x1f6, 0xe0 | ((b->dev&1)<<4) | ((b->sector>>24)&0x0f)); 00082 if(b->flags & B_DIRTY){ 00083 outb(0x1f7, IDE_CMD_WRITE); 00084 outsl(0x1f0, b->data, 512/4); 00085 } else { 00086 outb(0x1f7, IDE_CMD_READ); 00087 } 00088 } 00089 00090 // Interrupt handler. 00091 void 00092 ideintr(void) 00093 { 00094 struct buf *b; 00095 00096 // First queued buffer is the active request. 00097 acquire(&idelock); 00098 if((b = idequeue) == 0){ 00099 release(&idelock); 00100 // cprintf("spurious IDE interrupt\n"); 00101 return; 00102 } 00103 idequeue = b->qnext; 00104 00105 // Read data if needed. 00106 if(!(b->flags & B_DIRTY) && idewait(1) >= 0) 00107 insl(0x1f0, b->data, 512/4); 00108 00109 // Wake process waiting for this buf. 00110 b->flags |= B_VALID; 00111 b->flags &= ~B_DIRTY; 00112 wakeup(b); 00113 00114 // Start disk on next buf in queue. 00115 if(idequeue != 0) 00116 idestart(idequeue); 00117 00118 release(&idelock); 00119 } 00120 00121 //PAGEBREAK! 00122 // Sync buf with disk. 00123 // If B_DIRTY is set, write buf to disk, clear B_DIRTY, set B_VALID. 00124 // Else if B_VALID is not set, read buf from disk, set B_VALID. 00125 void 00126 iderw(struct buf *b) 00127 { 00128 struct buf **pp; 00129 00130 if(!(b->flags & B_BUSY)) 00131 panic("iderw: buf not busy"); 00132 if((b->flags & (B_VALID|B_DIRTY)) == B_VALID) 00133 panic("iderw: nothing to do"); 00134 if(b->dev != 0 && !havedisk1) 00135 panic("iderw: ide disk 1 not present"); 00136 00137 acquire(&idelock); //DOC: acquire-lock 00138 00139 // Append b to idequeue. 00140 b->qnext = 0; 00141 for(pp=&idequeue; *pp; pp=&(*pp)->qnext) //DOC: insert-queue 00142 ; 00143 *pp = b; 00144 00145 // Start disk if necessary. 00146 if(idequeue == b) 00147 idestart(b); 00148 00149 // Wait for request to finish. 00150 while((b->flags & (B_VALID|B_DIRTY)) != B_VALID){ 00151 sleep(b, &idelock); 00152 } 00153 00154 release(&idelock); 00155 }