summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sparc/dev/fd.c489
-rw-r--r--sys/arch/sparc/dev/fdreg.h15
-rw-r--r--sys/arch/sparc/dev/fdvar.h5
-rw-r--r--sys/arch/sparc/include/ioctl_fd.h130
-rw-r--r--sys/arch/sparc/sparc/auxreg.c32
-rw-r--r--sys/arch/sparc/sparc/auxreg.h85
-rw-r--r--sys/arch/sparc/sparc/bsd_fdintr.s118
7 files changed, 652 insertions, 222 deletions
diff --git a/sys/arch/sparc/dev/fd.c b/sys/arch/sparc/dev/fd.c
index c703e19e963..92db72bac52 100644
--- a/sys/arch/sparc/dev/fd.c
+++ b/sys/arch/sparc/dev/fd.c
@@ -1,5 +1,5 @@
-/* $OpenBSD: fd.c,v 1.17 1997/05/30 08:27:49 grr Exp $ */
-/* $NetBSD: fd.c,v 1.33.4.1 1996/06/12 20:52:25 pk Exp $ */
+/* $OpenBSD: fd.c,v 1.18 1997/06/24 09:50:56 downsj Exp $ */
+/* $NetBSD: fd.c,v 1.51 1997/05/24 20:16:19 pk Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995 Charles Hannum.
@@ -10,6 +10,12 @@
* This code is derived from software contributed to Berkeley by
* Don Ahn.
*
+ * Portions Copyright (c) 1993, 1994 by
+ * jc@irbs.UUCP (John Capo)
+ * vak@zebub.msk.su (Serge Vakulenko)
+ * ache@astral.msk.su (Andrew A. Chernov)
+ * joerg_wunsch@uriah.sax.de (Joerg Wunsch)
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
@@ -51,6 +57,8 @@
#include <sys/dkstat.h>
#include <sys/disk.h>
#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/mtio.h>
#include <sys/stat.h>
@@ -63,6 +71,7 @@
#include <machine/cpu.h>
#include <machine/autoconf.h>
#include <machine/conf.h>
+#include <machine/ioctl_fd.h>
#include <sparc/sparc/auxreg.h>
#include <sparc/dev/fdreg.h>
@@ -72,6 +81,9 @@
#define FDTYPE(dev) ((minor(dev) & 0x70) >> 4)
#define FDPART(dev) (minor(dev) & 0x0f)
+/* XXX misuse a flag to identify format operation */
+#define B_FORMAT B_XXX
+
#define b_cylin b_resid
#define FD_DEBUG
@@ -145,35 +157,15 @@ struct cfdriver fdc_cd = {
__inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t));
-/*
- * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
- * we tell them apart.
- */
-struct fd_type {
- int sectrac; /* sectors per track */
- int heads; /* number of heads */
- int seccyl; /* sectors per cylinder */
- int secsize; /* size code for sectors */
- int datalen; /* data len when secsize = 0 */
- int steprate; /* step rate and head unload time */
- int gap1; /* gap len between sectors */
- int gap2; /* formatting gap */
- int tracks; /* total num of tracks */
- int size; /* size of disk in sectors */
- int step; /* steps per cylinder */
- int rate; /* transfer speed code */
- char *name;
-};
-
/* The order of entries in the following table is important -- BEWARE! */
struct fd_type fd_types[] = {
- { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,"1.44MB" }, /* 1.44MB diskette */
- { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS,"1.2MB" }, /* 1.2 MB AT-diskettes */
- { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS,"360KB/AT" }, /* 360kB in 1.2MB drive */
- { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS,"360KB/PC" }, /* 360kB PC diskettes */
- { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,"720KB" }, /* 3.5" 720kB diskette */
- { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS,"720KB/x" }, /* 720kB in 1.2MB drive */
- { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,"360KB/x" }, /* 360kB in 720kB drive */
+ { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS, "1.44MB" }, /* 1.44MB diskette */
+ { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, "1.2MB" }, /* 1.2 MB AT-diskettes */
+ { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, "360KB/AT" }, /* 360kB in 1.2MB drive */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, "360KB/PC" }, /* 360kB PC diskettes */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, "720KB" }, /* 3.5" 720kB diskette */
+ { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, "720KB/x" }, /* 720kB in 1.2MB drive */
+ { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, "360KB/x" }, /* 360kB in 720kB drive */
};
/* software state, per disk (with up to 4 disks per ctlr) */
@@ -196,6 +188,7 @@ struct fd_softc {
#define FD_MOTOR 0x02 /* motor should be on */
#define FD_MOTOR_WAIT 0x04 /* motor coming up */
int sc_cylin; /* where we think the head is */
+ int sc_opts; /* user-set options */
void *sc_sdhook; /* shutdownhook cookie */
@@ -241,9 +234,11 @@ int fdchwintr __P((struct fdc_softc *));
void fdchwintr __P((void));
#endif
int fdcswintr __P((struct fdc_softc *));
+int fdcstate __P((struct fdc_softc *));
void fdcretry __P((struct fdc_softc *fdc));
void fdfinish __P((struct fd_softc *fd, struct buf *bp));
-void fd_do_eject __P((void));
+int fdformat __P((dev_t, struct fd_formb *, struct proc *));
+void fd_do_eject __P((struct fd_softc *));
void fd_mountroot_hook __P((struct device *));
static void fdconf __P((struct fdc_softc *));
@@ -253,6 +248,19 @@ static void fdconf __P((struct fdc_softc *));
#error 4
#endif
+#ifdef FDC_C_HANDLER
+#if defined(SUN4M)
+#define FD_SET_SWINTR do { \
+ if (CPU_ISSUN4M) \
+ raise(0, PIL_FDSOFT); \
+ else \
+ ienab_bis(IE_L4); \
+} while(0)
+#else
+#define AUDIO_SET_SWINTR ienab_bis(IE_FDSOFT)
+#endif /* defined(SUN4M) */
+#endif /* FDC_C_HANDLER */
+
#define OBP_FDNAME (CPU_ISSUN4M ? "SUNW,fdtwo" : "fd")
int
@@ -281,14 +289,6 @@ fdcmatch(parent, match, aux)
if ((CPU_ISSUN4M) && (ca->ca_bustype != BUS_OBIO))
return (0);
-#ifndef FDSUN4M
- /*
- * XXX Floppy doesn't work yet sun4m, nasty things happen if you try
- */
- if (CPU_ISSUN4M)
- return (0);
-#endif
-
/* Sun PROMs call the controller an "fd" or "SUNW,fdtwo" */
if (strcmp(OBP_FDNAME, ra->ra_name))
return (0);
@@ -326,7 +326,7 @@ fdprint(aux, fdc)
if (!fdc)
printf(" drive %d", fa->fa_drive);
- return QUIET;
+ return (QUIET);
}
static void
@@ -447,27 +447,35 @@ fdcattach(parent, self, aux)
*/
fa.fa_bootpath = 0;
if ((bp = ca->ca_ra.ra_bp) && strcmp(bp->name, OBP_FDNAME) == 0) {
- /*
- * WOAH THERE! It looks like we can get the bootpath
- * in several different formats!! The faked
- * bootpath (and some v2?) looks like /fd@0,0
- * but the real bootpath on some v2 OpenPROM
- * systems looks like /fd0. In the case of
- * a floppy controller on obio (such as on the sun4m),
- * we use "slot, offset" to determine if this is the
- * right one. --thorpej
- */
+
switch (ca->ca_bustype) {
case BUS_MAIN:
- if (((bp->val[0] == 0) && /* /fd@0,0 */
+ /*
+ * We can get the bootpath in several different
+ * formats! The faked v1 bootpath looks like /fd@0,0.
+ * The v2 bootpath is either just /fd0, in which case
+ * `bp->val[0]' will have been set to -1, or /fd@x,y
+ * where <x,y> is the prom address specifier.
+ */
+ if (((bp->val[0] == ca->ca_ra.ra_iospace) &&
+ (bp->val[1] == (int)ca->ca_ra.ra_paddr)) ||
+
+ ((bp->val[0] == -1) && /* v2: /fd0 */
(bp->val[1] == 0)) ||
- ((bp->val[0] == -1) && /* /fd0 */
- (bp->val[1] == 0)))
+
+ ((bp->val[0] == 0) && /* v1: /fd@0,0 */
+ (bp->val[1] == 0))
+ )
fa.fa_bootpath = bp;
break;
case BUS_OBIO:
- /* /obio0/SUNW,fdtwo@0,700000 */
+ /*
+ * floppy controller on obio (such as on the sun4m),
+ * e.g.: `/obio0/SUNW,fdtwo@0,700000'.
+ * We use "slot, offset" to determine if this is the
+ * right one.
+ */
if ((bp->val[0] == ca->ca_slot) &&
(bp->val[1] == ca->ca_offset))
fa.fa_bootpath = bp;
@@ -500,14 +508,14 @@ fdmatch(parent, match, aux)
int n, ok;
if (drive > 0)
- /* XXX - for now, punt > 1 drives */
- return 0;
+ /* XXX - for now, punt on more than one drive */
+ return (0);
if (fdc->sc_flags & FDC_82077) {
/* select drive and turn on motor */
*fdc->sc_reg_dor = drive | FDO_FRST | FDO_MOEN(drive);
} else {
- auxregbisc(AUXIO_FDS, 0);
+ auxregbisc(AUXIO4C_FDS, 0);
}
/* wait for motor to spin up */
delay(250000);
@@ -546,12 +554,14 @@ fdmatch(parent, match, aux)
ok = (n == 2 && (fdc->sc_status[0] & 0xf8) == 0x20) ? 1 : 0;
/* turn off motor */
- if (fdc->sc_flags & FDC_82077)
- *fdc->sc_reg_dor = FDO_FRST;
- else
- auxregbisc(0, AUXIO_FDS);
+ if (fdc->sc_flags & FDC_82077) {
+ /* deselect drive and turn motor off */
+ *fdc->sc_reg_dor = FDO_FRST | FDO_DS;
+ } else {
+ auxregbisc(0, AUXIO4C_FDS);
+ }
- return ok;
+ return (ok);
}
/*
@@ -571,7 +581,7 @@ fdattach(parent, self, aux)
/* XXX Allow `flags' to override device type? */
if (type)
- printf(": %s, %d cyl, %d head, %d sec\n", type->name,
+ printf(": %s %d cyl, %d head, %d sec\n", type->name,
type->tracks, type->heads, type->sectrac);
else
printf(": density unknown\n");
@@ -581,6 +591,10 @@ fdattach(parent, self, aux)
fd->sc_deftype = type;
fdc->sc_fd[drive] = fd;
+ out_fdc(fdc, NE7CMD_SPECIFY);
+ out_fdc(fdc, type->steprate);
+ out_fdc(fdc, 6 | NE7_SPECIFY_NODMA);
+
/*
* Initialize and attach the disk structure.
*/
@@ -615,8 +629,8 @@ fd_dev_to_type(fd, dev)
int type = FDTYPE(dev);
if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
- return NULL;
- return type ? &fd_types[type - 1] : fd->sc_deftype;
+ return (NULL);
+ return (type ? &fd_types[type - 1] : fd->sc_deftype);
}
void
@@ -632,7 +646,8 @@ fdstrategy(bp)
if (unit >= fd_cd.cd_ndevs ||
(fd = fd_cd.cd_devs[unit]) == 0 ||
bp->b_blkno < 0 ||
- (bp->b_bcount % FDC_BSIZE) != 0) {
+ ((bp->b_bcount % FDC_BSIZE) != 0 &&
+ (bp->b_flags & B_FORMAT) == 0)) {
bp->b_error = EINVAL;
goto bad;
}
@@ -744,12 +759,16 @@ fdc_reset(fdc)
struct fdc_softc *fdc;
{
if (fdc->sc_flags & FDC_82077) {
- *fdc->sc_reg_dor = FDO_MOEN(0);
+ *fdc->sc_reg_dor = FDO_FDMAEN | FDO_MOEN(0);
}
*fdc->sc_reg_drs = DRS_RESET;
delay(10);
*fdc->sc_reg_drs = 0;
+
+ if (fdc->sc_flags & FDC_82077) {
+ *fdc->sc_reg_dor = FDO_FRST | FDO_FDMAEN | FDO_DS;
+ }
#ifdef FD_DEBUG
if (fdc_debug)
printf("fdc reset\n");
@@ -780,9 +799,9 @@ fd_set_motor(fdc)
if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
on = 1;
if (on) {
- auxregbisc(AUXIO_FDS, 0);
+ auxregbisc(AUXIO4C_FDS, 0);
} else {
- auxregbisc(0, AUXIO_FDS);
+ auxregbisc(0, AUXIO4C_FDS);
}
}
}
@@ -811,7 +830,7 @@ fd_motor_on(arg)
s = splbio();
fd->sc_flags &= ~FD_MOTOR_WAIT;
if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
- (void) fdcswintr(fdc);
+ (void) fdcstate(fdc);
splx(s);
}
@@ -830,10 +849,11 @@ fdcresult(fdc)
if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
if (n >= sizeof(fdc->sc_status)) {
log(LOG_ERR, "fdcresult: overrun\n");
- return -1;
+ return (-1);
}
fdc->sc_status[n++] = *fdc->sc_reg_fifo;
- }
+ } else
+ delay(10);
}
log(LOG_ERR, "fdcresult: timeout\n");
return (fdc->sc_nstat = -1);
@@ -846,12 +866,13 @@ out_fdc(fdc, x)
{
int i = 100000;
- while (((*fdc->sc_reg_msr & (NE7_DIO|NE7_RQM)) != NE7_RQM) && i-- > 0);
+ while (((*fdc->sc_reg_msr & (NE7_DIO|NE7_RQM)) != NE7_RQM) && i-- > 0)
+ delay(1);
if (i <= 0)
- return -1;
+ return (-1);
*fdc->sc_reg_fifo = x;
- return 0;
+ return (0);
}
int
@@ -866,17 +887,17 @@ fdopen(dev, flags, fmt, p)
unit = FDUNIT(dev);
if (unit >= fd_cd.cd_ndevs)
- return ENXIO;
+ return (ENXIO);
fd = fd_cd.cd_devs[unit];
if (fd == 0)
- return ENXIO;
+ return (ENXIO);
type = fd_dev_to_type(fd, dev);
if (type == NULL)
- return ENXIO;
+ return (ENXIO);
if ((fd->sc_flags & FD_OPEN) != 0 &&
fd->sc_type != type)
- return EBUSY;
+ return (EBUSY);
fd->sc_type = type;
fd->sc_cylin = -1;
@@ -902,7 +923,7 @@ fdopen(dev, flags, fmt, p)
fd->sc_dk.dk_openmask =
fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask;
- return 0;
+ return (0);
}
int
@@ -915,6 +936,7 @@ fdclose(dev, flags, fmt, p)
int pmask = (1 << FDPART(dev));
fd->sc_flags &= ~FD_OPEN;
+ fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT);
switch (fmt) {
case S_IFCHR:
@@ -928,7 +950,7 @@ fdclose(dev, flags, fmt, p)
fd->sc_dk.dk_openmask =
fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask;
- return 0;
+ return (0);
}
int
@@ -964,7 +986,7 @@ fdcstart(fdc)
return;
}
#endif
- (void) fdcswintr(fdc);
+ (void) fdcstate(fdc);
}
void
@@ -974,6 +996,7 @@ fdcstatus(dv, n, s)
char *s;
{
struct fdc_softc *fdc = (void *)dv->dv_parent;
+ char bits[64];
#if 0
/*
* A 82072 seems to return <invalid command> on
@@ -996,7 +1019,7 @@ fdcstatus(dv, n, s)
printf("\n");
break;
case 2:
- printf(" (st0 %b cyl %d)\n",
+ printf(" (st0 %s cyl %d)\n",
fdc->sc_status[0], NE7_ST0BITS,
fdc->sc_status[1]);
break;
@@ -1031,7 +1054,7 @@ fdctimeout(arg)
else
fdc->sc_state = DEVIDLE;
- (void) fdcswintr(fdc);
+ (void) fdcstate(fdc);
splx(s);
}
@@ -1044,7 +1067,7 @@ fdcpseudointr(arg)
/* Just ensure it has the right spl. */
s = splbio();
- (void) fdcswintr(fdc);
+ (void) fdcstate(fdc);
splx(s);
}
@@ -1058,23 +1081,21 @@ int
fdchwintr(fdc)
struct fdc_softc *fdc;
{
- struct buf *bp;
- int read;
switch (fdc->sc_istate) {
+ case ISTATE_IDLE:
+ return (0);
case ISTATE_SENSEI:
out_fdc(fdc, NE7CMD_SENSEI);
fdcresult(fdc);
fdc->sc_istate = ISTATE_IDLE;
- ienab_bis(IE_FDSOFT);
+ FD_SET_SWINTR;
goto done;
- case ISTATE_IDLE:
case ISTATE_SPURIOUS:
- auxregbisc(0, AUXIO_FDS); /* Does this help? */
fdcresult(fdc);
fdc->sc_istate = ISTATE_SPURIOUS;
printf("fdc: stray hard interrupt... ");
- ienab_bis(IE_FDSOFT);
+ FD_SET_SWINTR;
goto done;
case ISTATE_DMA:
break;
@@ -1083,7 +1104,6 @@ fdchwintr(fdc)
goto done;
}
- read = bp->b_flags & B_READ;
for (;;) {
register int msr;
@@ -1101,25 +1121,15 @@ fdchwintr(fdc)
}
if (msr & NE7_DIO) {
-#ifdef DIAGNOSTIC
- if (!read)
- printf("fdxfer: false read\n");
-#endif
*fdc->sc_data++ = *fdc->sc_reg_fifo;
} else {
-#ifdef DIAGNOSTIC
- if (read)
- printf("fdxfer: false write\n");
-#endif
*fdc->sc_reg_fifo = *fdc->sc_data++;
}
if (--fdc->sc_tc == 0) {
- auxregbisc(AUXIO_FTC, 0);
- fdc->sc_istate = ISTATE_IDLE;
- delay(10);
- auxregbisc(0, AUXIO_FTC);
+ fdc->sc_istate = ISTATE_DONE;
+ FTC_FLIP;
fdcresult(fdc);
- ienab_bis(IE_FDSOFT);
+ FD_SET_SWINTR;
break;
}
}
@@ -1133,6 +1143,22 @@ int
fdcswintr(fdc)
struct fdc_softc *fdc;
{
+ int s;
+
+ if (fdc->sc_istate != ISTATE_DONE)
+ return (0);
+
+ fdc->sc_istate = ISTATE_IDLE;
+ s = splbio();
+ fdcstate(fdc);
+ splx(s);
+ return (1);
+}
+
+int
+fdcstate(fdc)
+ struct fdc_softc *fdc;
+{
#define st0 fdc->sc_status[0]
#define st1 fdc->sc_status[1]
#define cyl fdc->sc_status[1]
@@ -1143,6 +1169,7 @@ fdcswintr(fdc)
struct buf *bp;
int read, head, sec, nblks;
struct fd_type *type;
+ struct fd_formb *finfo = NULL;
if (fdc->sc_istate != ISTATE_IDLE) {
@@ -1162,7 +1189,7 @@ loop:
fd = fdc->sc_drives.tqh_first;
if (fd == NULL) {
fdc->sc_state = DEVIDLE;
- return 0;
+ return (0);
}
/* Is there a transfer to this drive? If not, deactivate drive. */
@@ -1174,6 +1201,9 @@ loop:
goto loop;
}
+ if (bp->b_flags & B_FORMAT)
+ finfo = (struct fd_formb *)bp->b_data;
+
switch (fdc->sc_state) {
case DEVIDLE:
fdc->sc_errors = 0;
@@ -1183,7 +1213,7 @@ loop:
untimeout(fd_motor_off, fd);
if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
fdc->sc_state = MOTORWAIT;
- return 1;
+ return (1);
}
if ((fd->sc_flags & FD_MOTOR) == 0) {
/* Turn on the motor, being careful about pairing. */
@@ -1202,15 +1232,16 @@ loop:
fd->sc_flags &= ~FD_MOTOR_WAIT;
goto loop;
}
- return 1;
+ return (1);
}
/* Make sure the right drive is selected. */
fd_set_motor(fdc);
- /* fall through */
+ /*FALLTHROUGH*/
case DOSEEK:
doseek:
- if (fdc->sc_flags & FDC_EIS) {
+ if ((fdc->sc_flags & FDC_EIS) &&
+ (bp->b_flags & B_FORMAT) == 0) {
fd->sc_cylin = bp->b_cylin;
/* We use implied seek */
goto doio;
@@ -1222,7 +1253,8 @@ loop:
/* specify command */
OUT_FDC(fdc, NE7CMD_SPECIFY, SEEKTIMEDOUT);
OUT_FDC(fdc, fd->sc_type->steprate, SEEKTIMEDOUT);
- OUT_FDC(fdc, 6, SEEKTIMEDOUT); /* XXX head load time == 6ms */
+ /* XXX head load time == 6ms */
+ OUT_FDC(fdc, 6 | NE7_SPECIFY_NODMA, SEEKTIMEDOUT);
fdc->sc_istate = ISTATE_SENSEI;
/* seek function */
@@ -1238,17 +1270,20 @@ loop:
disk_busy(&fd->sc_dk);
timeout(fdctimeout, fdc, 4 * hz);
- return 1;
+ return (1);
case DOIO:
doio:
+ if (finfo != NULL)
+ fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
+ (char *)finfo;
type = fd->sc_type;
sec = fd->sc_blkno % type->seccyl;
nblks = type->seccyl - sec;
nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
fd->sc_nblks = nblks;
- fd->sc_nbytes = nblks * FDC_BSIZE;
+ fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE;
head = sec / type->sectrac;
sec -= head * type->sectrac;
#ifdef DIAGNOSTIC
@@ -1277,24 +1312,34 @@ loop:
fdc->sc_state = IOCOMPLETE;
fdc->sc_istate = ISTATE_DMA;
fdc->sc_nstat = 0;
- if (read)
- OUT_FDC(fdc, NE7CMD_READ, IOTIMEDOUT); /* READ */
- else
- OUT_FDC(fdc, NE7CMD_WRITE, IOTIMEDOUT); /* WRITE */
- OUT_FDC(fdc, (head << 2) | fd->sc_drive, IOTIMEDOUT);
- OUT_FDC(fdc, fd->sc_cylin, IOTIMEDOUT); /* track */
- OUT_FDC(fdc, head, IOTIMEDOUT);
- OUT_FDC(fdc, sec + 1, IOTIMEDOUT); /* sector +1 */
- OUT_FDC(fdc, type->secsize, IOTIMEDOUT);/* sector size */
- OUT_FDC(fdc, type->sectrac, IOTIMEDOUT);/* sectors/track */
- OUT_FDC(fdc, type->gap1, IOTIMEDOUT); /* gap1 size */
- OUT_FDC(fdc, type->datalen, IOTIMEDOUT);/* data length */
+ if (finfo != NULL) {
+ /* formatting */
+ OUT_FDC(fdc, NE7CMD_FORMAT, IOTIMEDOUT);
+ OUT_FDC(fdc, (head << 2) | fd->sc_drive, IOTIMEDOUT);
+ OUT_FDC(fdc, finfo->fd_formb_secshift, IOTIMEDOUT);
+ OUT_FDC(fdc, finfo->fd_formb_nsecs, IOTIMEDOUT);
+ OUT_FDC(fdc, finfo->fd_formb_gaplen, IOTIMEDOUT);
+ OUT_FDC(fdc, finfo->fd_formb_fillbyte, IOTIMEDOUT);
+ } else {
+ if (read)
+ OUT_FDC(fdc, NE7CMD_READ, IOTIMEDOUT);
+ else
+ OUT_FDC(fdc, NE7CMD_WRITE, IOTIMEDOUT);
+ OUT_FDC(fdc, (head << 2) | fd->sc_drive, IOTIMEDOUT);
+ OUT_FDC(fdc, fd->sc_cylin, IOTIMEDOUT); /*track*/
+ OUT_FDC(fdc, head, IOTIMEDOUT);
+ OUT_FDC(fdc, sec + 1, IOTIMEDOUT); /*sector+1*/
+ OUT_FDC(fdc, type->secsize, IOTIMEDOUT);/*sector size*/
+ OUT_FDC(fdc, type->sectrac, IOTIMEDOUT);/*secs/track*/
+ OUT_FDC(fdc, type->gap1, IOTIMEDOUT); /*gap1 size*/
+ OUT_FDC(fdc, type->datalen, IOTIMEDOUT);/*data length*/
+ }
disk_busy(&fd->sc_dk);
/* allow 2 seconds for operation */
timeout(fdctimeout, fdc, 2 * hz);
- return 1; /* will return later */
+ return (1); /* will return later */
case SEEKWAIT:
untimeout(fdctimeout, fdc);
@@ -1302,9 +1347,9 @@ loop:
if (fdc->sc_flags & FDC_NEEDHEADSETTLE) {
/* allow 1/50 second for heads to settle */
timeout(fdcpseudointr, fdc, hz / 50);
- return 1; /* will return later */
+ return (1); /* will return later */
}
-
+ /*FALLTHROUGH*/
case SEEKCOMPLETE:
disk_unbusy(&fd->sc_dk, 0); /* no data on seek */
@@ -1322,10 +1367,9 @@ loop:
goto doio;
case IOTIMEDOUT:
- auxregbisc(AUXIO_FTC, 0);
- delay(10);
- auxregbisc(0, AUXIO_FTC);
+ FTC_FLIP;
(void)fdcresult(fdc);
+ /*FALLTHROUGH*/
case SEEKTIMEDOUT:
case RECALTIMEDOUT:
case RESETTIMEDOUT:
@@ -1337,14 +1381,17 @@ loop:
disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid));
- if (fdc->sc_nstat != 7 || (st0 & 0xf8) != 0 || st1 != 0) {
+ if (fdc->sc_nstat != 7 || st1 != 0 ||
+ ((st0 & 0xf8) != 0 &&
+ ((st0 & 0xf8) != 0x20 || (fdc->sc_cfg & CFG_EIS) == 0))) {
#ifdef FD_DEBUG
if (fdc_debug) {
fdcstatus(&fd->sc_dv, 7,
bp->b_flags & B_READ
? "read failed" : "write failed");
- printf("blkno %d nblks %d tc %d\n",
- fd->sc_blkno, fd->sc_nblks, fdc->sc_tc);
+ printf("blkno %d nblks %d nstat %d tc %d\n",
+ fd->sc_blkno, fd->sc_nblks,
+ fdc->sc_nstat, fdc->sc_tc);
}
#endif
if (fdc->sc_nstat == 7 &&
@@ -1398,7 +1445,7 @@ loop:
fd->sc_blkno += fd->sc_nblks;
fd->sc_skip += fd->sc_nbytes;
fd->sc_bcount -= fd->sc_nbytes;
- if (fd->sc_bcount > 0) {
+ if (finfo == NULL && fd->sc_bcount > 0) {
bp->b_cylin = fd->sc_blkno / fd->sc_type->seccyl;
goto doseek;
}
@@ -1415,7 +1462,7 @@ loop:
fdc->sc_istate = ISTATE_SENSEI;
fdc->sc_state = RESETCOMPLETE;
timeout(fdctimeout, fdc, hz / 2);
- return 1; /* will return later */
+ return (1); /* will return later */
case RESETCOMPLETE:
untimeout(fdctimeout, fdc);
@@ -1430,7 +1477,7 @@ loop:
OUT_FDC(fdc, NE7CMD_RECAL, RECALTIMEDOUT);
OUT_FDC(fdc, fd->sc_drive, RECALTIMEDOUT);
timeout(fdctimeout, fdc, 5 * hz);
- return 1; /* will return later */
+ return (1); /* will return later */
case RECALWAIT:
untimeout(fdctimeout, fdc);
@@ -1438,7 +1485,7 @@ loop:
if (fdc->sc_flags & FDC_NEEDHEADSETTLE) {
/* allow 1/30 second for heads to settle */
timeout(fdcpseudointr, fdc, hz / 30);
- return 1; /* will return later */
+ return (1); /* will return later */
}
case RECALCOMPLETE:
@@ -1455,12 +1502,12 @@ loop:
case MOTORWAIT:
if (fd->sc_flags & FD_MOTOR_WAIT)
- return 1; /* time's not up yet */
+ return (1); /* time's not up yet */
goto doseek;
default:
fdcstatus(&fd->sc_dv, 0, "stray interrupt");
- return 1;
+ return (1);
}
#ifdef DIAGNOSTIC
panic("fdcintr: impossible");
@@ -1474,6 +1521,7 @@ void
fdcretry(fdc)
struct fdc_softc *fdc;
{
+ char bits[64];
struct fd_softc *fd;
struct buf *bp;
@@ -1481,6 +1529,8 @@ fdcretry(fdc)
bp = fd->sc_q.b_actf;
fdc->sc_overruns = 0;
+ if (fd->sc_opts & FDOPT_NORETRY)
+ goto fail;
switch (fdc->sc_errors) {
case 0:
@@ -1500,14 +1550,19 @@ fdcretry(fdc)
break;
default:
- diskerr(bp, "fd", "hard error", LOG_PRINTF,
- fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
-
- printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
- fdc->sc_status[0], NE7_ST0BITS,
- fdc->sc_status[1], NE7_ST1BITS,
- fdc->sc_status[2], NE7_ST2BITS,
- fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
+ fail:
+ if ((fd->sc_opts & FDOPT_SILENT) == 0) {
+ diskerr(bp, "fd", "hard error", LOG_PRINTF,
+ fd->sc_skip / FDC_BSIZE,
+ (struct disklabel *)NULL);
+
+ printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
+ fdc->sc_status[0], NE7_ST0BITS,
+ fdc->sc_status[1], NE7_ST1BITS,
+ fdc->sc_status[2], NE7_ST2BITS,
+ fdc->sc_status[3], fdc->sc_status[4],
+ fdc->sc_status[5]);
+ }
bp->b_flags |= B_ERROR;
bp->b_error = EIO;
@@ -1522,7 +1577,7 @@ fdsize(dev)
{
/* Swapping to floppies would not make sense. */
- return -1;
+ return (-1);
}
int
@@ -1534,7 +1589,7 @@ fddump(dev, blkno, va, size)
{
/* Not implemented. */
- return EINVAL;
+ return (EINVAL);
}
int
@@ -1546,6 +1601,11 @@ fdioctl(dev, cmd, addr, flag, p)
struct proc *p;
{
struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
+ struct fdformat_parms *form_parms;
+ struct fdformat_cmd *form_cmd;
+ struct fd_formb fd_formbbuf;
+ int il[FD_MAX_NSEC + 1];
+ int i, j;
int error;
switch (cmd) {
@@ -1557,28 +1617,28 @@ fdioctl(dev, cmd, addr, flag, p)
if ((flag & FWRITE) == 0)
return EBADF;
/* XXX do something */
- return 0;
+ return (0);
case DIOCWDINFO:
if ((flag & FWRITE) == 0)
- return EBADF;
+ return (EBADF);
error = setdisklabel(fd->sc_dk.dk_label,
(struct disklabel *)addr, 0,
fd->sc_dk.dk_cpulabel);
if (error)
- return error;
+ return (error);
error = writedisklabel(dev, fdstrategy,
fd->sc_dk.dk_label,
fd->sc_dk.dk_cpulabel);
- return error;
+ return (error);
case DIOCLOCK:
/*
* Nothing to do here, really.
*/
- return 0;
+ return (0);
case MTIOCTOP:
if (((struct mtop *)addr)->mt_op != MTOFFL)
@@ -1588,8 +1648,30 @@ fdioctl(dev, cmd, addr, flag, p)
case SUNOS_FDIOCEJECT:
#endif
case DIOCEJECT:
- fd_do_eject();
- return 0;
+ fd_do_eject(fd);
+ return (0);
+
+ case FD_FORM:
+ if((flag & FWRITE) == 0)
+ return EBADF; /* must be opened for writing */
+ else if(((struct fd_formb *)addr)->format_version !=
+ FD_FORMAT_VERSION)
+ return EINVAL; /* wrong version of formatting prog */
+ else
+ return fdformat(dev, (struct fd_formb *)addr, p);
+ break;
+
+ case FD_GTYPE: /* get drive type */
+ *(struct fd_type *)addr = *fd->sc_type;
+ return (0);
+
+ case FD_GOPTS: /* get drive options */
+ *(int *)addr = fd->sc_opts;
+ return (0);
+
+ case FD_SOPTS: /* set drive options */
+ fd->sc_opts = *(int *)addr;
+ return (0);
#ifdef DEBUG
case _IO('f', 100):
@@ -1606,14 +1688,14 @@ fdioctl(dev, cmd, addr, flag, p)
printf(">\n");
}
- return 0;
+ return (0);
case _IOW('f', 101, int):
((struct fdc_softc *)fd->sc_dv.dv_parent)->sc_cfg &=
~CFG_THRHLD_MASK;
((struct fdc_softc *)fd->sc_dv.dv_parent)->sc_cfg |=
(*(int *)addr & CFG_THRHLD_MASK);
fdconf((struct fdc_softc *) fd->sc_dv.dv_parent);
- return 0;
+ return (0);
case _IO('f', 102):
{
int i;
@@ -1626,10 +1708,10 @@ fdioctl(dev, cmd, addr, flag, p)
printf(" 0x%x", fdc->sc_status[i]);
}
printf(">\n");
- return 0;
+ return (0);
#endif
default:
- return ENOTTY;
+ return (ENOTTY);
}
#ifdef DIAGNOSTIC
@@ -1637,6 +1719,69 @@ fdioctl(dev, cmd, addr, flag, p)
#endif
}
+int
+fdformat(dev, finfo, p)
+ dev_t dev;
+ struct fd_formb *finfo;
+ struct proc *p;
+{
+ int rv = 0, s;
+ struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
+ struct fd_type *type = fd->sc_type;
+ struct buf *bp;
+
+ /* set up a buffer header for fdstrategy() */
+ bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
+ if (bp == 0)
+ return (ENOBUFS);
+
+ PHOLD(p);
+ bzero((void *)bp, sizeof(struct buf));
+ bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
+ bp->b_proc = p;
+ bp->b_dev = dev;
+
+ /*
+ * Calculate a fake blkno, so fdstrategy() would initiate a
+ * seek to the requested cylinder.
+ */
+ bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
+ + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE;
+
+ bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
+ bp->b_data = (caddr_t)finfo;
+
+#ifdef FD_DEBUG
+ if (fdc_debug)
+ printf("fdformat: blkno %x count %ld\n",
+ bp->b_blkno, bp->b_bcount);
+#endif
+
+ /* now do the format */
+ fdstrategy(bp);
+
+ /* ...and wait for it to complete */
+ s = splbio();
+ while (!(bp->b_flags & B_DONE)) {
+ rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
+ if (rv == EWOULDBLOCK)
+ break;
+ }
+ splx(s);
+
+ if (rv == EWOULDBLOCK) {
+ /* timed out */
+ rv = EIO;
+ biodone(bp);
+ }
+ if (bp->b_flags & B_ERROR) {
+ rv = bp->b_error;
+ }
+ PRELE(p);
+ free(bp, M_TEMP);
+ return (rv);
+}
+
void
fdgetdisklabel(dev)
dev_t dev;
@@ -1684,12 +1829,24 @@ fdgetdisklabel(dev)
}
void
-fd_do_eject()
+fd_do_eject(fd)
+ struct fd_softc *fd;
{
+ struct fdc_softc *fdc = (void *)fd->sc_dv.dv_parent;
- auxregbisc(AUXIO_FDS, AUXIO_FEJ);
- delay(10);
- auxregbisc(AUXIO_FEJ, AUXIO_FDS);
+ if (CPU_ISSUN4C) {
+ auxregbisc(AUXIO4C_FDS, AUXIO4C_FEJ);
+ delay(10);
+ auxregbisc(AUXIO4C_FEJ, AUXIO4C_FDS);
+ return;
+ }
+ if (CPU_ISSUN4M && (fdc->sc_flags & FDC_82077)) {
+ int dor = FDO_FRST | FDO_FDMAEN | FDO_MOEN(0);
+ *fdc->sc_reg_dor = dor | FDO_EJ;
+ delay(10);
+ *fdc->sc_reg_dor = FDO_FRST | FDO_DS;
+ return;
+ }
}
/*
@@ -1705,7 +1862,7 @@ fd_mountroot_hook(dev)
{
int c;
- fd_do_eject();
+ fd_do_eject((struct fd_softc *)dev);
if (dev) {
printf("Insert filesystem floppy and press return.");
@@ -1713,7 +1870,7 @@ fd_mountroot_hook(dev)
c = cngetc();
if ((c == '\r') || (c == '\n')) {
printf("\n");
- return;
+ break;
}
}
}
diff --git a/sys/arch/sparc/dev/fdreg.h b/sys/arch/sparc/dev/fdreg.h
index 4166d58b0ba..bbe97ecb7c4 100644
--- a/sys/arch/sparc/dev/fdreg.h
+++ b/sys/arch/sparc/dev/fdreg.h
@@ -1,4 +1,5 @@
-/* $NetBSD: fdreg.h,v 1.5 1996/02/01 22:32:27 mycroft Exp $ */
+/* $OpenBSD: fdreg.h,v 1.3 1997/06/24 09:50:57 downsj Exp $ */
+/* $NetBSD: fdreg.h,v 1.6 1997/05/02 13:03:44 pk Exp $ */
/*-
* Copyright (c) 1991 The Regents of the University of California.
@@ -79,11 +80,13 @@ union fdreg {
#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */
#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */
-/* Digital Output Register bits */
-#define FDO_FDSEL 0x03 /* floppy device select */
-#define FDO_FRST 0x04 /* floppy controller reset */
+/* Digital Output Register bits (modified on suns) */
+#define FDO_DS 0x01 /* floppy device select (neg) */
+#define FDO_FRST 0x04 /* floppy controller reset (neg) */
#define FDO_FDMAEN 0x08 /* enable floppy DMA and Interrupt */
-#define FDO_MOEN(n) ((1 << n) * 0x10) /* motor enable */
+#define FDO_MOEN(n) ((1 << n) << 4) /* motor enable */
+#define FDO_DEN 0x40 /* Density select */
+#define FDO_EJ 0x80 /* Eject disk */
#define FDI_DCHG 0x80 /* diskette has been changed */
@@ -105,4 +108,4 @@ union fdreg {
#define ST1_OVERRUN 0x10
-
+#define NE7_SPECIFY_NODMA 0x01
diff --git a/sys/arch/sparc/dev/fdvar.h b/sys/arch/sparc/dev/fdvar.h
index fdc0461e77a..c727ae374db 100644
--- a/sys/arch/sparc/dev/fdvar.h
+++ b/sys/arch/sparc/dev/fdvar.h
@@ -1,6 +1,6 @@
-/* $OpenBSD: fdvar.h,v 1.4 1996/08/11 23:16:36 downsj Exp $ */
+/* $OpenBSD: fdvar.h,v 1.5 1997/06/24 09:50:57 downsj Exp $ */
/*
- * $NetBSD: fdvar.h,v 1.4 1996/02/01 22:32:29 mycroft Exp $
+ * $NetBSD: fdvar.h,v 1.5 1996/12/08 23:40:34 pk Exp $
*
* Copyright (c) 1995 Paul Kranenburg
* All rights reserved.
@@ -72,6 +72,7 @@ struct fdcio {
#define ISTATE_SPURIOUS 1 /* Spurious HW interrupt detected */
#define ISTATE_SENSEI 2 /* Do SENSEI on next HW interrupt */
#define ISTATE_DMA 3 /* Pseudo-DMA in progress */
+#define ISTATE_DONE 4 /* Interrupt processing complete */
#define SUNOS_FDIOCEJECT _IO('f', 24)
diff --git a/sys/arch/sparc/include/ioctl_fd.h b/sys/arch/sparc/include/ioctl_fd.h
new file mode 100644
index 00000000000..20ed00830f2
--- /dev/null
+++ b/sys/arch/sparc/include/ioctl_fd.h
@@ -0,0 +1,130 @@
+/* $OpenBSD: ioctl_fd.h,v 1.1 1997/06/24 09:50:58 downsj Exp $ */
+/* from: ioctl_fd.h,v 1.4 1995/06/29 03:49:32 jtk Exp */
+
+/*
+ * Copyright (C) 1992-1994 by Joerg Wunsch, Dresden
+ * All rights reserved.
+ *
+ * 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 and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``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 AUTHOR(S) 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.
+ *
+ * From: Id: ioctl_fd.h,v 1.7 1994/10/30 19:17:39 joerg Exp
+ */
+
+#ifndef _SPARC_IOCTL_FD_H_
+#define _SPARC_IOCTL_FD_H_
+
+#define FD_FORMAT_VERSION 110 /* used to validate before formatting */
+#define FD_MAX_NSEC 36 /* highest known number of spt - allow for */
+ /* 2.88 MB drives */
+
+struct fd_formb {
+ int format_version; /* == FD_FORMAT_VERSION */
+ int cyl, head;
+ int transfer_rate; /* fdreg.h: FDC_???KBPS */
+
+ union {
+ struct fd_form_data {
+ /*
+ * DO NOT CHANGE THE LAYOUT OF THIS STRUCTS
+ * it is hardware-dependant since it exactly
+ * matches the byte sequence to write to FDC
+ * during its `format track' operation
+ */
+ u_char secshift; /* 0 -> 128, ...; usually 2 -> 512 */
+ u_char nsecs; /* must be <= FD_MAX_NSEC */
+ u_char gaplen; /* GAP 3 length; usually 84 */
+ u_char fillbyte; /* usually 0xf6 */
+ struct fd_idfield_data {
+ /*
+ * data to write into id fields;
+ * for obscure formats, they mustn't match
+ * the real values (but mostly do)
+ */
+ u_char cylno; /* 0 thru 79 (or 39) */
+ u_char headno; /* 0, or 1 */
+ u_char secno; /* starting at 1! */
+ u_char secsize; /* usually 2 */
+ } idfields[FD_MAX_NSEC]; /* 0 <= idx < nsecs used */
+ } structured;
+ u_char raw[1]; /* to have continuous indexed access */
+ } format_info;
+};
+
+/* make life easier */
+# define fd_formb_secshift format_info.structured.secshift
+# define fd_formb_nsecs format_info.structured.nsecs
+# define fd_formb_gaplen format_info.structured.gaplen
+# define fd_formb_fillbyte format_info.structured.fillbyte
+/* these data must be filled in for(i = 0; i < fd_formb_nsecs; i++) */
+# define fd_formb_cylno(i) format_info.structured.idfields[i].cylno
+# define fd_formb_headno(i) format_info.structured.idfields[i].headno
+# define fd_formb_secno(i) format_info.structured.idfields[i].secno
+# define fd_formb_secsize(i) format_info.structured.idfields[i].secsize
+
+/*
+ * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
+ * we tell them apart.
+ */
+struct fd_type {
+ int sectrac; /* sectors per track */
+ int heads; /* number of heads */
+ int seccyl; /* sectors per cylinder */
+ int secsize; /* size code for sectors */
+ int datalen; /* data len when secsize = 0 */
+ int steprate; /* step rate and head unload time */
+ int gap1; /* gap len between sectors */
+ int gap2; /* formatting gap */
+ int tracks; /* total num of tracks */
+ int size; /* size of disk in sectors */
+ int step; /* steps per cylinder */
+ int rate; /* transfer speed code */
+ char *name;
+};
+
+
+#define FD_FORM _IOW('F', 61, struct fd_formb) /* format a track */
+#define FD_GTYPE _IOR('F', 62, struct fd_type) /* get drive type */
+#define FD_STYPE _IOW('F', 63, struct fd_type) /* set drive type */
+
+#define FD_GOPTS _IOR('F', 64, int) /* drive options, see below */
+#define FD_SOPTS _IOW('F', 65, int)
+
+#define FDOPT_NORETRY 0x0001 /* no retries on failure (cleared on close) */
+#define FDOPT_SILENT 0x0002
+
+/*
+ * The following definitions duplicate those in sys/i386/isa/fdreg.h
+ * They are here since their values are to be used in the above
+ * structure when formatting a floppy. For very obvious reasons, both
+ * definitions must match ;-)
+ */
+#ifndef FDC_500KBPS
+#define FDC_500KBPS 0x00 /* 500KBPS MFM drive transfer rate */
+#define FDC_300KBPS 0x01 /* 300KBPS MFM drive transfer rate */
+#define FDC_250KBPS 0x02 /* 250KBPS MFM drive transfer rate */
+#define FDC_125KBPS 0x03 /* 125KBPS FM drive transfer rate */
+ /* for some controllers 1MPBS instead */
+#endif /* FDC_500KBPS */
+
+
+#endif /* !_SPARC_IOCTL_FD_H__ */
diff --git a/sys/arch/sparc/sparc/auxreg.c b/sys/arch/sparc/sparc/auxreg.c
index 1b44aee9bbf..2a28ec0d7e5 100644
--- a/sys/arch/sparc/sparc/auxreg.c
+++ b/sys/arch/sparc/sparc/auxreg.c
@@ -1,4 +1,4 @@
-/* $NetBSD: auxreg.c,v 1.14 1996/04/13 17:40:03 abrown Exp $ */
+/* $NetBSD: auxreg.c,v 1.21 1997/05/24 20:15:59 pk Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -93,9 +93,9 @@ blink(zero)
* The OPENPROM calls this "auxiliary-io".
*/
static int
-auxregmatch(parent, vcf, aux)
+auxregmatch(parent, cf, aux)
struct device *parent;
- void *aux, *vcf;
+ void *cf, *aux;
{
register struct confargs *ca = aux;
@@ -121,7 +121,14 @@ auxregattach(parent, self, aux)
struct romaux *ra = &ca->ca_ra;
(void)mapdev(ra->ra_reg, AUXREG_VA, 0, sizeof(long), ca->ca_bustype);
- auxio_reg = AUXIO_REG;
+ if (CPU_ISSUN4M) {
+ auxio_reg = AUXIO4M_REG;
+ auxio_regval = *AUXIO4M_REG | AUXIO4M_MB1;
+ } else {
+ auxio_reg = AUXIO4C_REG;
+ auxio_regval = *AUXIO4C_REG | AUXIO4C_FEJ | AUXIO4C_MB1;
+ }
+
printf("\n");
#ifdef BLINK
blink((caddr_t)0);
@@ -132,11 +139,18 @@ unsigned int
auxregbisc(bis, bic)
int bis, bic;
{
- register int v, s = splhigh();
+ register int s;
- v = *AUXIO_REG;
- *AUXIO_REG = ((v | bis) & ~bic) | AUXIO_MB1;
+ if (auxio_reg == 0)
+ /*
+ * Not all machines have an `aux' register; devices that
+ * depend on it should not get configured if it's absent.
+ */
+ panic("no aux register");
+
+ s = splhigh();
+ auxio_regval = (auxio_regval | bis) & ~bic;
+ *auxio_reg = auxio_regval;
splx(s);
- return v;
+ return (auxio_regval);
}
-
diff --git a/sys/arch/sparc/sparc/auxreg.h b/sys/arch/sparc/sparc/auxreg.h
index 321c9a38a83..477028390d6 100644
--- a/sys/arch/sparc/sparc/auxreg.h
+++ b/sys/arch/sparc/sparc/auxreg.h
@@ -1,4 +1,4 @@
-/* $NetBSD: auxreg.h,v 1.5 1996/03/14 21:08:54 christos Exp $ */
+/* $NetBSD: auxreg.h,v 1.7 1997/05/17 17:52:52 pk Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -49,32 +49,81 @@
* (if it exists) and the front-panel LED.
*/
-#define AUXIO_MB1 0xf0 /* must be set on write */
-#define AUXIO_FHD 0x20 /* floppy: high density (unreliable?)*/
-#define AUXIO_FDC 0x10 /* floppy: diskette was changed */
-#define AUXIO_FDS 0x08 /* floppy: drive select */
-#define AUXIO_FTC 0x04 /* floppy: drives Terminal Count pin */
-#define AUXIO_FEJ 0x02 /* floppy: eject disk */
-#define AUXIO_LED 0x01 /* front panel LED */
+#define AUXIO4C_MB1 0xf0 /* must be set on write */
+#define AUXIO4C_FHD 0x20 /* floppy: high density (unreliable?)*/
+#define AUXIO4C_FDC 0x10 /* floppy: diskette was changed */
+#define AUXIO4C_FDS 0x08 /* floppy: drive select */
+#define AUXIO4C_FTC 0x04 /* floppy: drives Terminal Count pin */
+#define AUXIO4C_FEJ 0x02 /* floppy: eject disk */
+#define AUXIO4C_LED 0x01 /* front panel LED */
+
+#define AUXIO4M_MB1 0xc0 /* must be set on write? */
+#define AUXIO4M_FHD 0x20 /* floppy: high density (unreliable?)*/
+#define AUXIO4M_LTE 0x08 /* link-test enable */
+#define AUXIO4M_MMX 0x04 /* Monitor/Mouse MUX; what is it? */
+#define AUXIO4M_FTC 0x02 /* floppy: drives Terminal Count pin */
+#define AUXIO4M_LED 0x01 /* front panel LED */
/*
* We use a fixed virtual address for the register because we use it for
* timing short sections of code (via external hardware attached to the LED).
*/
-#define AUXIO_REG ((volatile u_char *)(AUXREG_VA + 3))
+#define AUXIO4C_REG ((volatile u_char *)(AUXREG_VA + 3))
+#define AUXIO4M_REG ((volatile u_char *)(AUXREG_VA))
+
+#define LED_ON do { \
+ if (CPU_ISSUN4M) { \
+ auxio_regval |= AUXIO4M_LED; \
+ *AUXIO4M_REG = auxio_regval; \
+ } else { \
+ auxio_regval |= AUXIO4C_LED; \
+ *AUXIO4C_REG = auxio_regval; \
+ } \
+} while(0)
+
+#define LED_OFF do { \
+ if (CPU_ISSUN4M) { \
+ auxio_regval &= ~AUXIO4M_LED; \
+ *AUXIO4M_REG = auxio_regval; \
+ } else { \
+ auxio_regval &= ~AUXIO4C_LED; \
+ *AUXIO4C_REG = auxio_regval; \
+ } \
+} while(0)
-#define LED_ON *AUXIO_REG = AUXIO_MB1|AUXIO_FEJ|AUXIO_LED
-#define LED_OFF *AUXIO_REG = AUXIO_MB1|AUXIO_FEJ
-#define LED_FLIP *AUXIO_REG = (*AUXIO_REG | AUXIO_MB1) ^ AUXIO_LED
+#define LED_FLIP do { \
+ if (CPU_ISSUN4M) { \
+ auxio_regval ^= AUXIO4M_LED; \
+ *AUXIO4M_REG = auxio_regval; \
+ } else { \
+ auxio_regval ^= AUXIO4C_LED; \
+ *AUXIO4C_REG = auxio_regval; \
+ } \
+} while(0)
-#define AUXIO_BITS "\20\6FHD\5FDC\4FDS\3FTC\2FEJ\1LED"
+#define FTC_FLIP do { \
+ if (CPU_ISSUN4M) { \
+ auxio_regval |= AUXIO4M_FTC; \
+ *AUXIO4M_REG = auxio_regval; \
+ *AUXIO4M_REG = *AUXIO4M_REG | AUXIO4M_MB1 | AUXIO4M_FTC;\
+ } else { \
+ auxio_regval |= AUXIO4C_FTC; \
+ *AUXIO4C_REG = auxio_regval; \
+ DELAY(10); \
+ auxio_regval &= ~AUXIO4C_FTC; \
+ *AUXIO4C_REG = auxio_regval; \
+ } \
+} while(0)
+
+#define AUXIO_BITS ( \
+ CPU_ISSUN4M \
+ ? "\20\6FHD\4LTE\3MMX\2FTC\1LED" \
+ : "\20\6FHD\5FDC\4FDS\3FTC\2FEJ\1LED" \
+)
#ifndef _LOCORE
-/*
- * Copy of AUXIO_REG for the benefit of assembler modules (eg. trap handlers)
- * as AUXREG_VA depends on NBPG which is not a constant.
- */
-volatile u_char *auxio_reg;
+volatile u_char *auxio_reg; /* Copy of AUXIO_REG */
+u_char auxio_regval;
unsigned int auxregbisc __P((int, int));
#endif
diff --git a/sys/arch/sparc/sparc/bsd_fdintr.s b/sys/arch/sparc/sparc/bsd_fdintr.s
index e0e52a690e8..e4e92a8e6d2 100644
--- a/sys/arch/sparc/sparc/bsd_fdintr.s
+++ b/sys/arch/sparc/sparc/bsd_fdintr.s
@@ -1,4 +1,4 @@
-/* $NetBSD: bsd_fdintr.s,v 1.8 1996/03/31 23:45:00 pk Exp $ */
+/* $NetBSD: bsd_fdintr.s,v 1.11 1997/04/07 21:00:36 pk Exp $ */
/*
* Copyright (c) 1995 Paul Kranenburg
@@ -33,13 +33,100 @@
#ifndef FDC_C_HANDLER
#include "assym.h"
+#include <machine/param.h>
+#include <machine/psl.h>
#include <sparc/sparc/intreg.h>
#include <sparc/sparc/auxreg.h>
#include <sparc/sparc/vaddrs.h>
#include <sparc/dev/fdreg.h>
#include <sparc/dev/fdvar.h>
-/* XXX this goes in a header file -- currently, it's hidden in locore.s */
-#define INTREG_ADDR 0xf8002000
+
+#define FD_SET_SWINTR_4C \
+ sethi %hi(INTRREG_VA), %l5; \
+ ldub [%l5 + %lo(INTRREG_VA)], %l6; \
+ or %l6, IE_L4, %l6; \
+ stb %l6, [%l5 + %lo(INTRREG_VA)]
+
+! raise(0,PIL_AUSOFT) ! NOTE: CPU#0 and PIL_AUSOFT=4
+#define FD_SET_SWINTR_4M \
+ sethi %hi(1 << (16 + 4)), %l5; \
+ set ICR_PI_SET, %l6; \
+ st %l5, [%l6]
+
+/* set software interrupt */
+#if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M)
+#define FD_SET_SWINTR FD_SET_SWINTR_4C
+#elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M)
+#define FD_SET_SWINTR FD_SET_SWINTR_4M
+#else
+#define FD_SET_SWINTR \
+ sethi %hi(_cputyp), %l5; \
+ ld [%l5 + %lo(_cputyp)], %l5; \
+ cmp %l5, CPU_SUN4M; \
+ be 8f; \
+ FD_SET_SWINTR_4C; \
+ ba,a 9f; \
+8: \
+ FD_SET_SWINTR_4M; \
+9:
+#endif
+
+! flip TC bit in auxreg
+! assumes %l6 remains unchanged between ASSERT and DEASSERT
+#define FD_ASSERT_TC_4C \
+ sethi %hi(AUXREG_VA), %l6; \
+ ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \
+ or %l7, AUXIO4C_MB1|AUXIO4C_FTC, %l7; \
+ stb %l7, [%l6 + %lo(AUXREG_VA) + 3];
+
+#define FD_DEASSERT_TC_4C \
+ ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \
+ andn %l7, AUXIO4C_FTC, %l7; \
+ or %l7, AUXIO4C_MB1, %l7; \
+ stb %l7, [%l6 + %lo(AUXREG_VA) + 3];
+
+! flip TC bit in auxreg
+#define FD_ASSERT_TC_4M \
+ sethi %hi(AUXREG_VA), %l6; \
+ ldub [%l6 + %lo(AUXREG_VA) + 3], %l7; \
+ or %l7, AUXIO4M_MB1|AUXIO4M_FTC, %l7; \
+ stb %l7, [%l6 + %lo(AUXREG_VA) + 3];
+
+#define FD_DEASSERT_TC_4M
+
+/*
+ * flip TC bit in auxreg
+ * assumes %l5 remains unchanged between ASSERT and DEASSERT
+ */
+#if (defined(SUN4) || defined(SUN4C)) && !defined(SUN4M)
+#define FD_ASSERT_TC FD_ASSERT_TC_4C
+#define FD_DEASSERT_TC FD_DEASSERT_TC_4C
+#elif !(defined(SUN4) || defined(SUN4C)) && defined(SUN4M)
+#define FD_ASSERT_TC FD_ASSERT_TC_4M
+#define FD_DEASSERT_TC FD_DEASSERT_TC_4M
+#else
+#define FD_ASSERT_TC \
+ sethi %hi(_cputyp), %l5; \
+ ld [%l5 + %lo(_cputyp)], %l5; \
+ cmp %l5, CPU_SUN4M; \
+ be 8f; \
+ nop; \
+ FD_ASSERT_TC_4C; \
+ ba,a 9f; \
+8: \
+ FD_ASSERT_TC_4M; \
+9:
+#define FD_DEASSERT_TC \
+ cmp %l5, CPU_SUN4M; \
+ be 8f; \
+ nop; \
+ FD_DEASSERT_TC_4C; \
+ ba,a 9f; \
+8: \
+ FD_DEASSERT_TC_4M; \
+9:
+#endif
+
/* Timeout waiting for chip ready */
#define POLL_TIMO 100000
@@ -140,16 +227,12 @@ nextc:
bne,a nextc ! if (--fdc->sc_tc) goto ...
ldub [R_msr], %l7 ! get MSR value
- ! xfer done: update fdc->sc_buf & fdc->sc_tc, mark istate IDLE
+ ! xfer done: update fdc->sc_buf & fdc->sc_tc, mark istate DONE
st R_tc, [R_fdc + FDC_TC]
st R_buf, [R_fdc + FDC_DATA]
! flip TC bit in auxreg
- sethi %hi(_auxio_reg), %l6
- ld [%l6 + %lo(_auxio_reg)], %l6
- ldub [%l6], %l7
- or %l7, AUXIO_MB1|AUXIO_FTC, %l7
- stb %l7, [%l6]
+ FD_ASSERT_TC
! we have some time to kill; anticipate on upcoming
! result phase.
@@ -157,12 +240,8 @@ nextc:
mov -1, %l7
st %l7, [R_fdc + FDC_NSTAT] ! fdc->sc_nstat = -1;
- ldub [%l6], %l7
- andn %l7, AUXIO_FTC, %l7
- or %l7, AUXIO_MB1, %l7
- stb %l7, [%l6]
- b resultphase1
- nop
+ FD_DEASSERT_TC
+ b,a resultphase1
spurious:
mov ISTATE_SPURIOUS, %l7
@@ -210,17 +289,14 @@ resultphase1:
ldub [R_msr], %l7
3:
- ! got status, update sc_nstat and mark istate IDLE
+ ! got status, update sc_nstat and mark istate DONE
st R_stcnt, [R_fdc + FDC_NSTAT]
- mov ISTATE_IDLE, %l7
+ mov ISTATE_DONE, %l7
st %l7, [R_fdc + FDC_ISTATE]
ssi:
! set software interrupt
- sethi %hi(INTREG_ADDR), %l7
- ldsb [%l7 + %lo(INTREG_ADDR)], %l6
- or %l6, IE_L4, %l6
- stb %l6, [%l7 + %lo(INTREG_ADDR)]
+ FD_SET_SWINTR
x:
/*