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