summaryrefslogtreecommitdiffstats
path: root/sys/dev/fdc
diff options
context:
space:
mode:
authorjkh <jkh@FreeBSD.org>1993-09-14 19:34:32 +0000
committerjkh <jkh@FreeBSD.org>1993-09-14 19:34:32 +0000
commitc9fee733230f268f2c0a1a9e48d05a1d03e21459 (patch)
tree0880662fa295f42d926d516fab8d6ba574055568 /sys/dev/fdc
parentf03267c6a399edcef4c15c98b1347213973dce6d (diff)
downloadFreeBSD-src-c9fee733230f268f2c0a1a9e48d05a1d03e21459.zip
FreeBSD-src-c9fee733230f268f2c0a1a9e48d05a1d03e21459.tar.gz
Bruce's multifarious patches for the floppy driver (not well tested, but
since what we have is crap as it is, it can't do much worse!).
Diffstat (limited to 'sys/dev/fdc')
-rw-r--r--sys/dev/fdc/fdc.c165
1 files changed, 142 insertions, 23 deletions
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c
index d4eda5a..914d562 100644
--- a/sys/dev/fdc/fdc.c
+++ b/sys/dev/fdc/fdc.c
@@ -46,12 +46,20 @@
* Largely rewritten to handle multiple controllers and drives
* By Julian Elischer, Sun Apr 4 16:34:33 WST 1993
*/
-char rev[] = "$Revision: 1.2 $";
+char rev[] = "$Revision: 1.3 $";
/*
- * $Header: /freefall/a/cvs/386BSD/src/sys/i386/isa/fd.c,v 1.2 1993/07/15 17:53:04 davidg Exp $
+ * $Header: /a/cvs/386BSD/src/sys/i386/isa/fd.c,v 1.3 1993/08/12 09:21:20 rgrimes Exp $
*/
/*
* $Log: fd.c,v $
+ * Revision 1.3 1993/08/12 09:21:20 rgrimes
+ * Fixed poor timeout code in out_fdc. The timeout counter was not being
+ * reinitialized between while loops. Added comments about what was going
+ * on in the out_fdc routine.
+ *
+ * out_fdc now returns if the direction bit is not set in time instead of
+ * trying to wait for MRQ to get cleared.
+ *
* Revision 1.2 1993/07/15 17:53:04 davidg
* Modified attach printf's so that the output is compatible with the "new"
* way of doing things. There still remain several drivers that need to
@@ -97,6 +105,7 @@ char rev[] = "$Revision: 1.2 $";
#include "conf.h"
#include "file.h"
#include "ioctl.h"
+#include "disklabel.h"
#include "buf.h"
#include "uio.h"
#include "i386/isa/isa.h"
@@ -292,8 +301,11 @@ struct isa_device *dev;
fdu++,fdsu++)
{
/* is there a unit? */
- if ((fdt & 0xf0) == RTCFDT_NONE)
+ if ((fdt & 0xf0) == RTCFDT_NONE) {
+#define NO_TYPE NUMTYPES
+ fd_data[fdu].type = NO_TYPE;
continue;
+ }
#ifdef notyet
/* select it */
@@ -403,7 +415,10 @@ bad:
/* motor control stuff */
/* remember to not deselect the drive we're working on */
/****************************************************************************/
-set_motor(fdcu_t fdcu, fdu_t fdu, int reset)
+set_motor(fdcu, fdu, reset)
+ fdcu_t fdcu;
+ fdu_t fdu;
+ int reset;
{
int m0,m1;
int selunit;
@@ -430,24 +445,35 @@ set_motor(fdcu_t fdcu, fdu_t fdu, int reset)
| (m1 ? FDO_MOEN1 : 0)));
}
-fd_turnoff(fdu_t fdu)
+fd_turnoff(fdu)
+ fdu_t fdu;
{
+ int s;
+
fd_p fd = fd_data + fdu;
+ s = splbio();
fd->flags &= ~FD_MOTOR;
set_motor(fd->fdc->fdcu,fd->fdsu,0);
+ splx(s);
}
-fd_motor_on(fdu_t fdu)
+fd_motor_on(fdu)
+ fdu_t fdu;
{
+ int s;
+
fd_p fd = fd_data + fdu;
+ s = splbio();
fd->flags &= ~FD_MOTOR_WAIT;
if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT))
{
- fd_pseudointr(fd->fdc->fdcu);
+ fdintr(fd->fdc->fdcu);
}
+ splx(s);
}
-fd_turnon(fdu_t fdu)
+fd_turnon(fdu)
+ fdu_t fdu;
{
fd_p fd = fd_data + fdu;
if(!(fd->flags & FD_MOTOR))
@@ -458,7 +484,8 @@ fd_turnon(fdu_t fdu)
}
}
-fd_turnon1(fdu_t fdu)
+fd_turnon1(fdu)
+ fdu_t fdu;
{
fd_p fd = fd_data + fdu;
fd->flags |= FD_MOTOR;
@@ -469,7 +496,8 @@ fd_turnon1(fdu_t fdu)
/* fdc in/out */
/****************************************************************************/
int
-in_fdc(fdcu_t fdcu)
+in_fdc(fdcu)
+ fdcu_t fdcu;
{
int baseport = fdc_data[fdcu].baseport;
int i, j = 100000;
@@ -487,7 +515,9 @@ in_fdc(fdcu_t fdcu)
#endif
}
-out_fdc(fdcu_t fdcu,int x)
+out_fdc(fdcu, x)
+ fdcu_t fdcu;
+ int x;
{
int baseport = fdc_data[fdcu].baseport;
int i;
@@ -508,7 +538,6 @@ out_fdc(fdcu_t fdcu,int x)
return (0);
}
-static fdopenf;
/****************************************************************************/
/* fdopen/fdclose */
/****************************************************************************/
@@ -521,7 +550,7 @@ Fdopen(dev, flags)
int s;
/* check bounds */
- if (fdu >= NFD) return(ENXIO);
+ if (fdu >= NFD || fd_data[fdu].type == NO_TYPE) return(ENXIO);
/*if (type >= NUMTYPES) return(ENXIO);*/
fd_data[fdu].flags |= FD_OPEN;
@@ -546,7 +575,8 @@ fdclose(dev, flags)
* If the controller is already busy, we need do nothing, as it *
* will pick up our work when the present work completes *
\***************************************************************/
-fdstart(fdcu_t fdcu)
+fdstart(fdcu)
+ fdcu_t fdcu;
{
register struct buf *dp,*bp;
int s;
@@ -560,13 +590,16 @@ fdstart(fdcu_t fdcu)
splx(s);
}
-fd_timeout(fdcu_t fdcu)
+fd_timeout(fdcu)
+ fdcu_t fdcu;
{
fdu_t fdu = fdc_data[fdcu].fdu;
int st0, st3, cyl;
struct buf *dp,*bp;
+ int s;
dp = &fdc_data[fdcu].head;
+ s = splbio();
bp = dp->b_actf;
out_fdc(fdcu,NE7CMD_SENSED);
@@ -598,11 +631,13 @@ fd_timeout(fdcu_t fdcu)
fdc_data[fdcu].fdu = -1;
fdc_data[fdcu].state = DEVIDLE;
}
- fd_pseudointr(fdcu);
+ fdintr(fdcu);
+ splx(s);
}
/* just ensure it has the right spl */
-fd_pseudointr(fdcu_t fdcu)
+fd_pseudointr(fdcu)
+ fdcu_t fdcu;
{
int s;
s = splbio();
@@ -615,7 +650,8 @@ fd_pseudointr(fdcu_t fdcu)
* keep calling the state machine until it returns a 0 *
* ALWAYS called at SPLBIO *
\***********************************************************************/
-fdintr(fdcu_t fdcu)
+fdintr(fdcu)
+ fdcu_t fdcu;
{
fdc_p fdc = fdc_data + fdcu;
while(fdstate(fdcu, fdc));
@@ -625,7 +661,9 @@ fdintr(fdcu_t fdcu)
* The controller state machine. *
* if it returns a non zero value, it should be called again immediatly *
\***********************************************************************/
-int fdstate(fdcu_t fdcu, fdc_p fdc)
+int fdstate(fdcu, fdc)
+ fdcu_t fdcu;
+ fdc_p fdc;
{
int read,head,trac,sec,i,s,sectrac,cyl,st0;
unsigned long blknum;
@@ -707,8 +745,10 @@ int fdstate(fdcu_t fdcu, fdc_p fdc)
out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac);
fd->track = -2;
fdc->state = SEEKWAIT;
+ timeout(fd_timeout,fdcu,2 * hz);
return(0); /* will return later */
case SEEKWAIT:
+ untimeout(fd_timeout,fdcu);
/* allow heads to settle */
timeout(fd_pseudointr,fdcu,hz/50);
fdc->state = SEEKCOMPLETE;
@@ -864,7 +904,8 @@ int fdstate(fdcu_t fdcu, fdc_p fdc)
return(1); /* Come back immediatly to new state */
}
-retrier(fdcu_t fdcu)
+retrier(fdcu)
+ fdcu_t fdcu;
{
fdc_p fdc = fdc_data + fdcu;
register struct buf *dp,*bp;
@@ -901,14 +942,92 @@ retrier(fdcu_t fdcu)
dp->b_actf = bp->av_forw;
fdc->fd->skip = 0;
biodone(bp);
- fdc->state = FINDWORK;
+ fdc->state = DEVIDLE;
fdc->fd = (fd_p) 0;
fdc->fdu = -1;
- return(1);
+ /* XXX abort current command, if any. */
+ return(0);
}
fdc->retry++;
return(1);
}
-#endif
+/*
+ * fdioctl() from jc@irbs.UUCP (John Capo)
+ * i386/i386/conf.c needs to have fdioctl() declared and remove the line that
+ * defines fdioctl to be enxio.
+ *
+ * TODO: Reformat.
+ * Think about allocating buffer off stack.
+ * Don't pass uncast 0's and NULL's to read/write/setdisklabel().
+ * Watch out for NetBSD's different *disklabel() interface.
+ */
+
+int
+fdioctl (dev, cmd, addr, flag)
+dev_t dev;
+int cmd;
+caddr_t addr;
+int flag;
+{
+ struct fd_type *fdt;
+ struct disklabel *dl;
+ char buffer[DEV_BSIZE];
+ int error;
+
+ error = 0;
+
+ switch (cmd)
+ {
+ case DIOCGDINFO:
+ bzero(buffer, sizeof (buffer));
+ dl = (struct disklabel *)buffer;
+ dl->d_secsize = FDBLK;
+ fdt = &fd_types[FDUNIT(minor(dev))];
+ dl->d_secpercyl = fdt->size / fdt->tracks;
+ dl->d_type = DTYPE_FLOPPY;
+
+ if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL)
+ error = 0;
+ else
+ error = EINVAL;
+
+ *(struct disklabel *)addr = *dl;
+ break;
+
+ case DIOCSDINFO:
+
+ if ((flag & FWRITE) == 0)
+ error = EBADF;
+ break;
+
+ case DIOCWLABEL:
+ if ((flag & FWRITE) == 0)
+ error = EBADF;
+
+ break;
+
+ case DIOCWDINFO:
+ if ((flag & FWRITE) == 0)
+ {
+ error = EBADF;
+ break;
+ }
+
+ dl = (struct disklabel *)addr;
+
+ if (error = setdisklabel ((struct disklabel *)buffer, dl, 0, NULL))
+ break;
+
+ error = writedisklabel(dev, fdstrategy, (struct disklabel *)buffer, NULL);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+ return (error);
+}
+
+#endif
OpenPOWER on IntegriCloud