fdc.c

Go to the documentation of this file.
00001 /*****************************************************************************************
00002  Copyright (c) 2002-2004 The UbixOS Project
00003  All rights reserved.
00004 
00005  Redistribution and use in source and binary forms, with or without modification, are
00006  permitted provided that the following conditions are met:
00007 
00008  Redistributions of source code must retain the above copyright notice, this list of
00009  conditions, the following disclaimer and the list of authors.  Redistributions in binary
00010  form must reproduce the above copyright notice, this list of conditions, the following
00011  disclaimer and the list of authors in the documentation and/or other materials provided
00012  with the distribution. Neither the name of the UbixOS Project nor the names of its
00013  contributors may be used to endorse or promote products derived from this software
00014  without specific prior written permission.
00015 
00016  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
00017  EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00018  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
00019  THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00020  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
00021  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00022  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
00023  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00024  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025 
00026  $Id: fdc_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
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   //kprintf("Block: [%i]\n",block);
00134   block2Hts(block,&head,&track,&sector);
00135   motorOn();
00136   if (!read && blockBuffer) {
00137     /* copy data from data buffer into track buffer */
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);  /* clear "disk change" status */
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);               /* 512 Int8s/sector */
00172     sendByte(geometry.spt);
00173     if (geometry.spt == dg144Spt) {
00174       sendByte(dg144Gap3rw);  /* gap 3 size for 1.44M read/write */
00175       }
00176     else {
00177       sendByte(dg168Gap3rw);  /* gap 3 size for 1.68M read/write */
00178       }
00179     sendByte(0xff);            /* DTL = unused */
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;   /* worked! outta here! */
00186     recalibrate();  /* oops, try again... */
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     //outportByte(fdcDor,0x0);
00217     //outportByte(fdcDor,0x0C);
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  $Log: fdc_8c-source.html,v $
00316  Revision 1.7  2006/12/15 17:47:05  reddawg
00316  Updates
00316 
00317  Revision 1.1.1.1  2006/06/01 12:46:12  reddawg
00318  ubix2
00319 
00320  Revision 1.2  2005/10/12 00:13:37  reddawg
00321  Removed
00322 
00323  Revision 1.1.1.1  2005/09/26 17:24:01  reddawg
00324  no message
00325 
00326  Revision 1.24  2004/09/07 21:54:38  reddawg
00327  ok reverted back to old scheduling for now....
00328 
00329  Revision 1.23  2004/09/06 15:13:25  reddawg
00330  Last commit before FreeBSD 6.0
00331 
00332  Revision 1.22  2004/08/21 20:06:28  reddawg
00333  ok check out exec.c
00334 
00335  Revision 1.21  2004/08/15 16:47:49  reddawg
00336  Fixed
00337 
00338  Revision 1.20  2004/08/15 00:33:02  reddawg
00339  Wow the ide driver works again
00340 
00341  Revision 1.19  2004/08/01 20:40:45  reddawg
00342  Net related fixes
00343 
00344  Revision 1.18  2004/07/29 21:32:16  reddawg
00345  My quick lunchs breaks worth of updates....
00346 
00347  Revision 1.17  2004/07/27 08:03:36  reddawg
00348  chg: stopped push all these extra registers I can't find a good reason as to why I was doing it
00349 
00350  Revision 1.16  2004/07/22 17:32:25  reddawg
00351  I broke it hopefully
00352 
00353  Revision 1.15  2004/07/21 10:02:09  reddawg
00354  devfs: renamed functions
00355  device system: renamed functions
00356  fdc: fixed a few potential bugs and cleaned up some unused variables
00357  strol: fixed definition
00358  endtask: made it print out freepage debug info
00359  kmalloc: fixed a huge memory leak we had some unhandled descriptor insertion so some descriptors were lost
00360  ld: fixed a pointer conversion
00361  file: cleaned up a few unused variables
00362  sched: broke task deletion
00363  kprintf: fixed ogPrintf definition
00364 
00365  Revision 1.14  2004/07/17 02:38:31  reddawg
00366  Fixed a few problems
00367 
00368  Revision 1.13  2004/07/14 12:42:46  reddawg
00369  fdc: fdcInit to fdc_init
00370  Changed Startup Routines
00371 
00372  Revision 1.12  2004/06/04 10:19:42  reddawg
00373  notes: we compile again, thank g-d anyways i was about to cry
00374 
00375  Revision 1.11  2004/05/20 22:51:09  reddawg
00376  Cleaned Up Warnings
00377 
00378  Revision 1.10  2004/05/19 23:36:52  reddawg
00379  Bug Fixes
00380 
00381  Revision 1.9  2004/05/19 15:31:27  reddawg
00382  Fixed up the rest of the references
00383 
00384  Revision 1.8  2004/05/19 15:26:33  reddawg
00385  Fixed reference issues due to changes in driver subsystem
00386 
00387  Revision 1.7  2004/05/10 02:23:24  reddawg
00388  Minor Changes To Source Code To Prepare It For Open Source Release
00389 
00390  Revision 1.6  2004/04/30 14:16:04  reddawg
00391  Fixed all the datatypes to be consistant uInt8,uInt16,uInt32,Int8,Int16,Int32
00392 
00393  Revision 1.5  2004/04/29 15:29:20  reddawg
00394  Fixed All Running Issues
00395 
00396  Revision 1.4  2004/04/28 02:22:54  reddawg
00397  This is a fiarly large commit but we are starting to use new driver model
00398  all around
00399 
00400  Revision 1.3  2004/04/26 22:22:33  reddawg
00401  DevFS now uses correct size of device
00402 
00403  Revision 1.2  2004/04/22 21:20:05  reddawg
00404  FDC now adds drives to the devfs
00405 
00406  Revision 1.1.1.1  2004/04/15 12:07:09  reddawg
00407  UbixOS v1.0
00408 
00409  Revision 1.6  2004/04/13 16:36:33  reddawg
00410  Changed our copyright, it is all now under a BSD-Style license
00411 
00412  END
00413  ***/
00414 

Generated on Fri Dec 15 11:18:55 2006 for UbixOS V2 by  doxygen 1.4.7