00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 #include <isa/fdc.h>
00031 #include <isa/8259.h>
00032 #include <sys/video.h>
00033 #include <sys/gdt.h>
00034 #include <sys/idt.h>
00035 #include <ubixos/types.h>
00036 #include <ubixos/spinlock.h>
00037 #include <sys/io.h>
00038 #include <sys/dma.h>
00039 #include <sys/device.h>
00040 #include <lib/kprintf.h>
00041 #include <lib/kmalloc.h>
00042 #include <devfs/devfs.h>
00043 
00044 static spinLock_t fdcSpinLock = SPIN_LOCK_INITIALIZER;
00045 
00046 static volatile bool done = FALSE;
00047 static drvGeom geometry = { dg144Heads,dg144Tracks,dg144Spt };
00048 static bool diskChange = FALSE;
00049 static bool motor = FALSE;
00050 static volatile Int8 fdcTrack = 0xff;
00051 static Int8 sr0 = 0;
00052 static volatile int timeOut = 0;
00053 static Int8 statSize = 0;
00054 static Int8 status[7] = { 0 };
00055 
00056 unsigned long tbaddr = 0x80000L;
00057 
00058 int fdcInit2(struct device_node *dev) {
00059   dev->devInfo->size = (1024 * 1450);
00060   return(0x0);
00061   }
00062 
00063 int fdc_init() {
00064   struct device_interface *devInfo = (struct device_interface *)kmalloc(sizeof(struct device_interface));
00065   setVector(floppyIsr, mVec+6, (dInt+dPresent));
00066   irqEnable(6);
00067   reset();
00068   devInfo->major = 0x0;
00069   devInfo->init  = (void *)&fdcInit2;
00070   devInfo->read  = fdcRead;
00071   devInfo->write = fdcWrite;
00072   devInfo->reset = (void *)reset;
00073   
00074   device_add(0,'c',devInfo);
00075   devfs_makeNode("fd0",'b',0x0,0x0);
00076   return(0x0);
00077   }
00078 
00079 asm(
00080   ".globl floppyIsr      \n"
00081   "floppyIsr:            \n"
00082   "  pusha               \n"
00083   "  push %ss            \n"
00084   "  push %ds            \n"
00085   "  push %es            \n"
00086   "  push %fs            \n"
00087   "  push %gs            \n"
00088   "  call floppyIsrhndlr \n"
00089   "  pop %gs             \n"
00090   "  pop %fs             \n" 
00091   "  pop %es             \n"
00092   "  pop %ds             \n"
00093   "  pop %ss             \n"
00094   "  popa                \n"
00095   "  iret                \n"
00096   );
00097 
00098 void floppyIsrhndlr() {
00099   done = TRUE;
00100   outportByte(0x20,0x20);
00101   }
00102 
00103 void sendByte(int Int8) {
00104   volatile int msr;
00105   int tmo;
00106   for (tmo=0;tmo<128;tmo++) {
00107     msr = inportByte(fdcMsr);
00108     if ((msr & 0xc0) == 0x80) {
00109       outportByte(fdcData,Int8);
00110       return;
00111       }
00112     inportByte(0x80);
00113     }
00114   }
00115 
00116 int getByte() {
00117   volatile int msr;
00118   int tmo;
00119   for (tmo=0;tmo<128;tmo++) {
00120     msr = inportByte(fdcMsr);
00121     if ((msr & 0xd0) == 0xd0) {
00122       return inportByte(fdcData);
00123       }
00124     inportByte(0x80);
00125     }
00126   return(-1);
00127   }
00128 
00129 bool fdcRw(int block,Int8 *blockBuffer,bool read,unsigned long numSectors) {
00130   int head = 0x0,track = 0x0,sector = 0x0,tries= 0x0, copyCount = 0x0;
00131   unsigned char *p_tbaddr = (char *)0x80000;
00132   unsigned char *p_blockbuff = blockBuffer;
00133   
00134   block2Hts(block,&head,&track,§or);
00135   motorOn();
00136   if (!read && blockBuffer) {
00137     
00138     for (copyCount=0; copyCount<(numSectors*512); copyCount++) {
00139       *p_tbaddr = *p_blockbuff;
00140       p_blockbuff++;
00141       p_tbaddr++;
00142       }
00143     }
00144   for (tries = 0;tries < 3;tries++) {
00145     if (inportByte(fdcDir) & 0x80) {
00146       diskChange = TRUE;
00147       seek(1);  
00148       recalibrate();
00149       motorOff();
00150       kprint("FDC: Disk change detected. Trying again.\n");
00151       return fdcRw(block, blockBuffer, read, numSectors);
00152       }
00153     if (!seek(track)) {
00154       motorOff();
00155       kprintf("FDC: Error seeking to track [%i]\n",block);
00156       return FALSE;
00157       }
00158     outportByte(fdcCcr,0);
00159     if (read) {
00160       dmaXfer(2,tbaddr,numSectors*512,FALSE);
00161       sendByte(cmdRead);
00162       }
00163     else {
00164       dmaXfer(2,tbaddr,numSectors*512,TRUE);
00165       sendByte(cmdWrite);
00166       }
00167     sendByte(head << 2);
00168     sendByte(track);
00169     sendByte(head);
00170     sendByte(sector);
00171     sendByte(2);               
00172     sendByte(geometry.spt);
00173     if (geometry.spt == dg144Spt) {
00174       sendByte(dg144Gap3rw);  
00175       }
00176     else {
00177       sendByte(dg168Gap3rw);  
00178       }
00179     sendByte(0xff);            
00180     if (!waitFdc(TRUE)) {
00181       kprint("Timed out, trying operation again after reset()\n");
00182       reset();
00183       return fdcRw(block, blockBuffer, read, numSectors);
00184       }
00185     if ((status[0] & 0xc0) == 0) break;   
00186     recalibrate();  
00187     }
00188   motorOff();
00189   if (read && blockBuffer) {
00190     p_blockbuff = blockBuffer;
00191     p_tbaddr = (char *) 0x80000;
00192     for (copyCount=0x0; copyCount<(numSectors*512); copyCount++) {
00193       *p_blockbuff = *p_tbaddr;
00194       p_blockbuff++;
00195       p_tbaddr++;
00196       }
00197     }
00198   return (tries != 3);
00199   }
00200 
00201 void block2Hts(int block,int *head,int *track,int *sector) {
00202   *head = (block % (geometry.spt * geometry.heads)) / (geometry.spt);
00203   *track = block / (geometry.spt * geometry.heads);
00204   *sector = block % geometry.spt + 1;
00205   }
00206 
00207 void motorOn(void) {
00208   if (motor == FALSE) {
00209     outportByte(fdcDor,0x1c);
00210     motor = TRUE;
00211     }
00212   }
00213 
00214 void motorOff(void) {
00215   if (motor == TRUE) {
00216     
00217     
00218     motor = FALSE;
00219     }
00220   }
00221 
00222 bool seek(int track) {
00223   if (fdcTrack == track) {
00224     return(TRUE);
00225     }
00226   sendByte(cmdSeek);
00227   sendByte(0);
00228   sendByte(track);
00229   if (!waitFdc(TRUE)) {
00230     kprintf("wait fdc failed\n");
00231     return(FALSE);
00232     }
00233   if ((sr0 != 0x20) || (fdcTrack != track)) {
00234     return(FALSE);
00235     }
00236   else {
00237     return(TRUE);
00238     }
00239   }
00240 
00241 bool readBlock(int block,Int8 *blockBuffer, unsigned long numSectors) {
00242   int result = 0x0,loop = 0x0;
00243   if (numSectors > 1) {
00244     for (loop=0; loop<numSectors; loop++) {
00245       result = fdcRw(block+loop, blockBuffer+(loop*512), TRUE, 1);
00246       }
00247     return result;
00248     }
00249   return fdcRw(block,blockBuffer,TRUE,numSectors);
00250   }
00251 
00252 bool writeBlock(int block,Int8 *blockBuffer, unsigned long numSectors) {
00253   return fdcRw(block,blockBuffer,FALSE, numSectors);
00254   }
00255 
00256 bool waitFdc(bool sensei) {
00257   timeOut = 50000;
00258   while (!done && timeOut);
00259   statSize = 0;
00260   while ((statSize < 7) && (inportByte(fdcMsr) & (1<<4))) {
00261     status[(int)statSize++] = getByte();
00262     }
00263   if (sensei) {
00264     sendByte(cmdSensei);
00265     sr0 = getByte();
00266     fdcTrack = getByte();
00267     }
00268   done = FALSE;
00269   if (!timeOut) {
00270     if (inportByte(fdcDir) & 0x80) {
00271       diskChange = TRUE;
00272       }
00273     return(FALSE);
00274     }
00275   else {
00276     return(TRUE);
00277     }
00278   }
00279 
00280 void recalibrate(void) {
00281   motorOn();
00282   sendByte(cmdRecal);
00283   sendByte(0);
00284   waitFdc(TRUE);
00285   motorOff();
00286   }
00287 
00288 void reset(void) {
00289   outportByte(fdcDor,0);
00290   motor = FALSE;
00291   outportByte(fdcDor,0x0c);
00292   done = TRUE;
00293   waitFdc(TRUE);
00294   sendByte(cmdSpecify);
00295   sendByte(0xdf);
00296   sendByte(0x02);
00297   seek(1);
00298   recalibrate();
00299   diskChange = FALSE;
00300   return;
00301   }
00302 
00303 void fdcRead(void *info,void *baseAddr,uInt32 startSector,uInt32 sectorCount) {
00304   spinLock(&fdcSpinLock);
00305   readBlock(startSector,baseAddr,sectorCount);
00306   spinUnlock(&fdcSpinLock);
00307   return;
00308   }
00309 void fdcWrite(void *info,void *baseAddr,uInt32 startSector,uInt32 sectorCount){
00310   writeBlock(startSector,baseAddr,sectorCount);
00311   return;
00312   }
00313 
00314 
00315 
00316