diff options
Diffstat (limited to 'sys/arch')
-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: /* |