diff --git a/src/sys/drivers/fdc.c b/src/sys/drivers/fdc.c index dab9e30..388d326 100755 --- a/src/sys/drivers/fdc.c +++ b/src/sys/drivers/fdc.c @@ -7,12 +7,25 @@ #include #include +#include #include #include #include #include +#include -static volatile BOOL done = FALSE; +static volatile bool done = FALSE; +static drvGeom geometry = { dg144Heads,dg144Tracks,dg144Spt }; +static bool diskChange = FALSE; +static bool motor = FALSE; +static int mTick = 0; +static byte fdcTrack = 0xff; +static byte sr0 = 0; +static volatile int timeOut = 0; +static byte statSize = 0; +static byte status[7] = { 0 }; + +unsigned long tbaddr = 0x80000L; void initFloppy() { setVector(floppyIsr, mVec+6, (dInt+dPresent+dDpl1)); @@ -65,4 +78,161 @@ inportByte(0x80); } return(-1); + } + +bool fdcRw(int block,byte *blockBuffer,bool read,unsigned long numSectors) { + int head,track,sector,tries, copyCount = 0; + unsigned char *p_tbaddr = (char *)0x80000; + unsigned char *p_blockbuff = blockBuffer; + 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(); + kprint("FDC: Error seeking to track\n"); + 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 bytes/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 = (char *) 0x80000; + for (copyCount=0; 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) { + mTick = -1; /* stop motor kill countdown */ + outportByte(fdcDor,0x1c); + motor = TRUE; + } + } + +void motorOff(void) { + if (motor) { + mTick = 13500; + } + } + +bool seek(int track) { + if (fdcTrack == track) { + return(TRUE); + } + sendByte(cmdSeek); + sendByte(0); + sendByte(track); + if (!waitFdc(TRUE)) { + return(FALSE); + } + if ((sr0 != 0x20) || (fdcTrack != track)) { + return(FALSE); + } + else { + return(TRUE); + } + } + +bool waitFdc(bool sensei) { + timeOut = 50000; + while (!done && timeOut); + statSize = 0; + while ((statSize < 7) && (inportByte(fdcMsr) & (1<<4))) { + status[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); + mTick = 0; + motor = FALSE; + outportByte(fdcDrs,0); + outportByte(fdcDor,0x0c); + done = TRUE; + waitFdc(TRUE); + sendByte(cmdSpecify); + sendByte(0xdf); + sendByte(0x02); + seek(1); + recalibrate(); + diskChange = FALSE; } \ No newline at end of file diff --git a/src/sys/include/drivers/fdc.h b/src/sys/include/drivers/fdc.h index 770a4a4..2b58589 100755 --- a/src/sys/include/drivers/fdc.h +++ b/src/sys/include/drivers/fdc.h @@ -8,14 +8,51 @@ #ifndef _FDC_H #define _FDC_H +#include + +typedef struct DrvGeom { + byte heads; + byte tracks; + byte spt; +} drvGeom; + #define fdcMsr (0x3f4) #define fdcData (0x3f5) +#define fdcDir (0x3f7) +#define fdcCcr (0x3f7) +#define fdcDor (0x3f2) +#define fdcDrs (0x3f4) + +#define cmdWrite (0xc5) +#define cmdRead (0xe6) +#define cmdSeek (0x0f) +#define cmdSensei (0x08) +#define cmdRecal (0x07) +#define cmdSpecify (0x03) + +#define dg144Heads 2 /* heads per drive (1.44M) */ +#define dg144Tracks 80 +#define dg144Spt 18 +#define dg144Gap3rw 0x1b +#define dg168Gap3rw 0x1c + + void initFloppy(); void floppyIsr(); void floppyIsrhndlr(); void sendByte(int byte); int getByte(); +bool fdcRw(int block,byte *blockBuffer,bool read,unsigned long numSectors); +void block2Hts(int block,int *head,int *track,int *sector); +void motorOn(void); +void motorOff(void); +bool seek(int track); +bool waitFdc(bool sensei); +int getByte(); +void sendByte(int byte); +void recalibrate(void); +void reset(void); #endif \ No newline at end of file diff --git a/src/sys/include/ubixos/dma.h b/src/sys/include/ubixos/dma.h new file mode 100755 index 0000000..0caac6f --- /dev/null +++ b/src/sys/include/ubixos/dma.h @@ -0,0 +1,15 @@ +/************************************************************************************** + Copyright (c) 2002 + The UbixOS Project + + $Id$ +**************************************************************************************/ + +#ifndef _DMA_H +#define _DMA_H + +#include + +int dmaXfer(uChar channel,uLong address,uInt length,uChar read); + +#endif \ No newline at end of file diff --git a/src/sys/include/ubixos/types.h b/src/sys/include/ubixos/types.h index c619c20..1da4581 100755 --- a/src/sys/include/ubixos/types.h +++ b/src/sys/include/ubixos/types.h @@ -8,6 +8,14 @@ #ifndef _TYPES_H #define _TYPES_H -typedef enum { FALSE=0,TRUE=1 } BOOL; +typedef unsigned char byte; /* 8-bit byte */ +typedef unsigned short word; /* 16-bit word */ +typedef unsigned long dWord; /* 32-bit dword */ + +typedef unsigned char uChar; +typedef unsigned long uLong; +typedef unsigned int uInt; + +typedef enum { FALSE=0,TRUE=1 } bool; #endif \ No newline at end of file diff --git a/src/sys/kernel/Makefile b/src/sys/kernel/Makefile index e9ec017..239f2da 100755 --- a/src/sys/kernel/Makefile +++ b/src/sys/kernel/Makefile @@ -14,7 +14,7 @@ REMOVE = rm -fr # Objects -OBJS = io.o version.o kprintf.o vsprintf.o idt.o schedule.o exec.o +OBJS = io.o version.o kprintf.o vsprintf.o idt.o schedule.o exec.o dma.o all: $(OBJS) diff --git a/src/sys/kernel/dma.c b/src/sys/kernel/dma.c new file mode 100755 index 0000000..58a9de9 --- /dev/null +++ b/src/sys/kernel/dma.c @@ -0,0 +1,11 @@ +/************************************************************************************** + Copyright (c) 2002 + The UbixOS Project + + $Id$ +**************************************************************************************/ + +#include + +int dmaXfer(uChar channel,uLong address,uInt length,uChar read) { + } diff --git a/ubixos.kdevprj b/ubixos.kdevprj index 4edfbd4..9262581 100755 --- a/ubixos.kdevprj +++ b/ubixos.kdevprj @@ -228,10 +228,16 @@ type=HEADER [src/sys/include/ubixos/Makefile.am] -files=src/sys/include/ubixos/gdt.h,src/sys/include/ubixos/io.h,src/sys/include/ubixos/idt.h,src/sys/include/ubixos/exec.h,src/sys/include/ubixos/schedule.h,src/sys/include/ubixos/types.h +files=src/sys/include/ubixos/gdt.h,src/sys/include/ubixos/io.h,src/sys/include/ubixos/idt.h,src/sys/include/ubixos/exec.h,src/sys/include/ubixos/schedule.h,src/sys/include/ubixos/types.h,src/sys/include/ubixos/dma.h sub_dirs= type=normal +[src/sys/include/ubixos/dma.h] +dist=true +install=false +install_location= +type=HEADER + [src/sys/include/ubixos/exec.h] dist=true install=false @@ -322,10 +328,16 @@ type=DATA [src/sys/kernel/Makefile.am] -files=src/sys/kernel/Makefile,src/sys/kernel/io.c,src/sys/kernel/version.c,src/sys/kernel/kprintf.c,src/sys/kernel/vsprintf.c,src/sys/kernel/idt.c,src/sys/kernel/exec.c,src/sys/kernel/schedule.c +files=src/sys/kernel/Makefile,src/sys/kernel/io.c,src/sys/kernel/version.c,src/sys/kernel/kprintf.c,src/sys/kernel/vsprintf.c,src/sys/kernel/idt.c,src/sys/kernel/exec.c,src/sys/kernel/schedule.c,src/sys/kernel/dma.c sub_dirs= type=static_library +[src/sys/kernel/dma.c] +dist=true +install=false +install_location= +type=SOURCE + [src/sys/kernel/exec.c] dist=true install=false