/*- * Copyright (c) 2002-2018 The UbixOS Project. * All rights reserved. * * This was developed by Christopher W. Olsen for the UbixOS Project. * * Redistribution and use in source and binary forms, with or without modification, are permitted * provided that the following conditions are met: * * 1) Redistributions of source code must retain the above copyright notice, this list of * conditions, the following disclaimer and the list of authors. * 2) Redistributions in binary form must reproduce the above copyright notice, this list of * conditions, the following disclaimer and the list of authors in the documentation and/or * other materials provided with the distribution. * 3) Neither the name of the UbixOS Project nor the names of its contributors may be used to * endorse or promote products derived from this software without specific prior written * permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <isa/fdc.h> #include <isa/8259.h> #include <sys/video.h> #include <sys/gdt.h> #include <sys/idt.h> #include <ubixos/spinlock.h> #include <sys/io.h> #include <sys/dma.h> #include <sys/device.h> #include <lib/kprintf.h> #include <lib/kmalloc.h> #include <devfs/devfs.h> static struct spinLock fdcSpinLock = SPIN_LOCK_INITIALIZER; static volatile bool done = FALSE; static drvGeom geometry = { dg144Heads, dg144Tracks, dg144Spt }; static bool diskChange = FALSE; static bool motor = FALSE; static volatile Int8 fdcTrack = 0xff; static Int8 sr0 = 0; static volatile int timeOut = 0; static Int8 statSize = 0; static Int8 status[7] = { 0 }; unsigned long tbaddr = 0x80000L; int fdcInit2(struct device_node *dev) { dev->devInfo->size = (1024 * 1450); return (0x0); } int fdc_init() { struct device_interface *devInfo = (struct device_interface *) kmalloc(sizeof(struct device_interface)); setVector(floppyIsr, mVec + 6, (dInt + dPresent)); irqEnable(6); reset(); devInfo->major = 0x0; devInfo->init = (void *) &fdcInit2; devInfo->read = fdcRead; devInfo->write = fdcWrite; devInfo->reset = (void *) reset; device_add(0, 'c', devInfo); devfs_makeNode("fd0", 'b', 0x0, 0x0); return (0x0); } asm( ".globl floppyIsr \n" "floppyIsr: \n" " pusha \n" " push %ss \n" " push %ds \n" " push %es \n" " push %fs \n" " push %gs \n" " call floppyIsrhndlr \n" " pop %gs \n" " pop %fs \n" " pop %es \n" " pop %ds \n" " pop %ss \n" " popa \n" " iret \n" ); void floppyIsrhndlr() { done = TRUE; outportByte(0x20, 0x20); } void sendByte(int Int8) { volatile int msr; int tmo; for (tmo = 0; tmo < 128; tmo++) { msr = inportByte(fdcMsr); if ((msr & 0xc0) == 0x80) { outportByte(fdcData, Int8); return; } inportByte(0x80); } } int getByte() { volatile int msr; int tmo; for (tmo = 0; tmo < 128; tmo++) { msr = inportByte(fdcMsr); if ((msr & 0xd0) == 0xd0) { return inportByte(fdcData); } inportByte(0x80); } return (-1); } bool fdcRw(int block, unsigned char *blockBuffer, bool read, unsigned long numSectors) { int head = 0x0, track = 0x0, sector = 0x0, tries = 0x0, copyCount = 0x0; unsigned char *p_tbaddr = (unsigned char *) 0x80000; unsigned char *p_blockbuff = blockBuffer; //kprintf("Block: [%i]\n",block); block2Hts(block, &head, &track, §or); motorOn(); if (!read && blockBuffer) { /* copy data from data buffer into track buffer */ for (copyCount = 0; copyCount < (numSectors * 512); copyCount++) { *p_tbaddr = *p_blockbuff; p_blockbuff++; p_tbaddr++; } } for (tries = 0; tries < 3; tries++) { if (inportByte(fdcDir) & 0x80) { diskChange = TRUE; seek(1); /* clear "disk change" status */ recalibrate(); motorOff(); kprint("FDC: Disk change detected. Trying again.\n"); return fdcRw(block, blockBuffer, read, numSectors); } if (!seek(track)) { motorOff(); kprintf("FDC: Error seeking to track [%i]\n", block); return FALSE; } outportByte(fdcCcr, 0); if (read) { dmaXfer(2, tbaddr, numSectors * 512, FALSE); sendByte(cmdRead); } else { dmaXfer(2, tbaddr, numSectors * 512, TRUE); sendByte(cmdWrite); } sendByte(head << 2); sendByte(track); sendByte(head); sendByte(sector); sendByte(2); /* 512 Int8s/sector */ sendByte(geometry.spt); if (geometry.spt == dg144Spt) { sendByte(dg144Gap3rw); /* gap 3 size for 1.44M read/write */ } else { sendByte(dg168Gap3rw); /* gap 3 size for 1.68M read/write */ } sendByte(0xff); /* DTL = unused */ if (!waitFdc(TRUE)) { kprint("Timed out, trying operation again after reset()\n"); reset(); return fdcRw(block, blockBuffer, read, numSectors); } if ((status[0] & 0xc0) == 0) break; /* worked! outta here! */ recalibrate(); /* oops, try again... */ } motorOff(); if (read && blockBuffer) { p_blockbuff = blockBuffer; p_tbaddr = (unsigned char *) 0x80000; for (copyCount = 0x0; copyCount < (numSectors * 512); copyCount++) { *p_blockbuff = *p_tbaddr; p_blockbuff++; p_tbaddr++; } } return (tries != 3); } void block2Hts(int block, int *head, int *track, int *sector) { *head = (block % (geometry.spt * geometry.heads)) / (geometry.spt); *track = block / (geometry.spt * geometry.heads); *sector = block % geometry.spt + 1; } void motorOn(void) { if (motor == FALSE) { outportByte(fdcDor, 0x1c); motor = TRUE; } } void motorOff(void) { if (motor == TRUE) { //outportByte(fdcDor,0x0); //outportByte(fdcDor,0x0C); motor = FALSE; } } bool seek(int track) { if (fdcTrack == track) { return (TRUE); } sendByte(cmdSeek); sendByte(0); sendByte(track); if (!waitFdc(TRUE)) { kprintf("wait fdc failed\n"); return (FALSE); } if ((sr0 != 0x20) || (fdcTrack != track)) { return (FALSE); } else { return (TRUE); } } bool readBlock(int block, Int8 *blockBuffer, unsigned long numSectors) { int result = 0x0, loop = 0x0; if (numSectors > 1) { for (loop = 0; loop < numSectors; loop++) { result = fdcRw(block + loop, blockBuffer + (loop * 512), TRUE, 1); } return result; } return fdcRw(block, blockBuffer, TRUE, numSectors); } bool writeBlock(int block, Int8 *blockBuffer, unsigned long numSectors) { return fdcRw(block, blockBuffer, FALSE, numSectors); } bool waitFdc(bool sensei) { timeOut = 50000; while (!done && timeOut) ; statSize = 0; while ((statSize < 7) && (inportByte(fdcMsr) & (1 << 4))) { status[(int) statSize++] = getByte(); } if (sensei) { sendByte(cmdSensei); sr0 = getByte(); fdcTrack = getByte(); } done = FALSE; if (!timeOut) { if (inportByte(fdcDir) & 0x80) { diskChange = TRUE; } return (FALSE); } else { return (TRUE); } } void recalibrate(void) { motorOn(); sendByte(cmdRecal); sendByte(0); waitFdc(TRUE); motorOff(); } void reset(void) { outportByte(fdcDor, 0); motor = FALSE; outportByte(fdcDor, 0x0c); done = TRUE; waitFdc(TRUE); sendByte(cmdSpecify); sendByte(0xdf); sendByte(0x02); seek(1); recalibrate(); diskChange = FALSE; return; } void fdcRead(void *info, void *baseAddr, uInt32 startSector, uInt32 sectorCount) { spinLock(&fdcSpinLock); readBlock(startSector, baseAddr, sectorCount); spinUnlock(&fdcSpinLock); return; } void fdcWrite(void *info, void *baseAddr, uInt32 startSector, uInt32 sectorCount) { writeBlock(startSector, baseAddr, sectorCount); return; } /*** $Log: fdc.c,v $ Revision 1.1.1.1 2006/06/01 12:46:12 reddawg ubix2 Revision 1.2 2005/10/12 00:13:37 reddawg Removed Revision 1.1.1.1 2005/09/26 17:24:01 reddawg no message Revision 1.24 2004/09/07 21:54:38 reddawg ok reverted back to old scheduling for now.... Revision 1.23 2004/09/06 15:13:25 reddawg Last commit before FreeBSD 6.0 Revision 1.22 2004/08/21 20:06:28 reddawg ok check out exec.c Revision 1.21 2004/08/15 16:47:49 reddawg Fixed Revision 1.20 2004/08/15 00:33:02 reddawg Wow the ide driver works again Revision 1.19 2004/08/01 20:40:45 reddawg Net related fixes Revision 1.18 2004/07/29 21:32:16 reddawg My quick lunchs breaks worth of updates.... Revision 1.17 2004/07/27 08:03:36 reddawg chg: stopped push all these extra registers I can't find a good reason as to why I was doing it Revision 1.16 2004/07/22 17:32:25 reddawg I broke it hopefully Revision 1.15 2004/07/21 10:02:09 reddawg devfs: renamed functions device system: renamed functions fdc: fixed a few potential bugs and cleaned up some unused variables strol: fixed definition endtask: made it print out freepage debug info kmalloc: fixed a huge memory leak we had some unhandled descriptor insertion so some descriptors were lost ld: fixed a pointer conversion file: cleaned up a few unused variables sched: broke task deletion kprintf: fixed ogPrintf definition Revision 1.14 2004/07/17 02:38:31 reddawg Fixed a few problems Revision 1.13 2004/07/14 12:42:46 reddawg fdc: fdcInit to fdc_init Changed Startup Routines Revision 1.12 2004/06/04 10:19:42 reddawg notes: we compile again, thank g-d anyways i was about to cry Revision 1.11 2004/05/20 22:51:09 reddawg Cleaned Up Warnings Revision 1.10 2004/05/19 23:36:52 reddawg Bug Fixes Revision 1.9 2004/05/19 15:31:27 reddawg Fixed up the rest of the references Revision 1.8 2004/05/19 15:26:33 reddawg Fixed reference issues due to changes in driver subsystem Revision 1.7 2004/05/10 02:23:24 reddawg Minor Changes To Source Code To Prepare It For Open Source Release Revision 1.6 2004/04/30 14:16:04 reddawg Fixed all the datatypes to be consistant uInt8,uInt16,uInt32,Int8,Int16,Int32 Revision 1.5 2004/04/29 15:29:20 reddawg Fixed All Running Issues Revision 1.4 2004/04/28 02:22:54 reddawg This is a fiarly large commit but we are starting to use new driver model all around Revision 1.3 2004/04/26 22:22:33 reddawg DevFS now uses correct size of device Revision 1.2 2004/04/22 21:20:05 reddawg FDC now adds drives to the devfs Revision 1.1.1.1 2004/04/15 12:07:09 reddawg UbixOS v1.0 Revision 1.6 2004/04/13 16:36:33 reddawg Changed our copyright, it is all now under a BSD-Style license END ***/