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 
00317 
00318 
00319 
00320 
00321 
00322 
00323 
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390 
00391 
00392 
00393 
00394 
00395 
00396 
00397 
00398 
00399 
00400 
00401 
00402 
00403 
00404 
00405 
00406 
00407 
00408 
00409 
00410 
00411 
00412 
00413 
00414