diff options
author | Jason Downs <downsj@cvs.openbsd.org> | 1997-06-24 09:51:01 +0000 |
---|---|---|
committer | Jason Downs <downsj@cvs.openbsd.org> | 1997-06-24 09:51:01 +0000 |
commit | 510a88f54dc54d289dd6b07f32d73fb52621856f (patch) | |
tree | 65bc9206ccd9874ef61fbf762ecbaf2566ea8772 /sys | |
parent | 734f2c9cc87b092301aeb95a554e4c8bed238cd1 (diff) |
New floppy and auxreg drivers, from NetBSD. fd.c has many changes preserved,
and uses our fdformat interface (same code base as NetBSD, with differently
named ioctls, but we have always preserved the names of the original code's
authors, unlike NetBSD...)
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/sparc/dev/fd.c | 489 | ||||
-rw-r--r-- | sys/arch/sparc/dev/fdreg.h | 15 | ||||
-rw-r--r-- | sys/arch/sparc/dev/fdvar.h | 5 | ||||
-rw-r--r-- | sys/arch/sparc/include/ioctl_fd.h | 130 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/auxreg.c | 32 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/auxreg.h | 85 | ||||
-rw-r--r-- | sys/arch/sparc/sparc/bsd_fdintr.s | 118 |
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: /* |