# 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