1*11649Shelge /* rx.c 4.6 83/03/23 */ 210773Ssam 310773Ssam #include "rx.h" 410773Ssam #if NFX > 0 510773Ssam /* 610773Ssam * RX02 floppy disk device driver 710773Ssam * 8*11649Shelge * -- WARNING, UNTESTED -- 910773Ssam */ 1011205Ssam #include "../machine/pte.h" 1111205Ssam 1210773Ssam #include "../h/param.h" 1311205Ssam #include "../h/buf.h" 1410773Ssam #include "../h/systm.h" 1510773Ssam #include "../h/conf.h" 1611214Shelge #include "../h/errno.h" 1711214Shelge #include "../h/time.h" 1811205Ssam #include "../h/kernel.h" 1911205Ssam #include "../h/uio.h" 2011214Shelge #include "../h/file.h" 2110773Ssam 2211205Ssam #include "../vax/cpu.h" 2310773Ssam #include "../vax/nexus.h" 2410773Ssam #include "../vaxuba/ubavar.h" 2510773Ssam #include "../vaxuba/ubareg.h" 2610773Ssam #include "../vaxuba/rxreg.h" 2710773Ssam 2810773Ssam /* per-controller data */ 2910773Ssam struct rx_ctlr { 3010773Ssam int rxc_state; /* controller state */ 3110773Ssam #define RXS_READ 1 /* read started */ 3210773Ssam #define RXS_EMPTY 2 /* empty started */ 3310773Ssam #define RXS_FILL 3 /* fill started */ 3410773Ssam #define RXS_WRITE 4 /* write started */ 3510773Ssam #define RXS_FORMAT 5 /* format started */ 3610773Ssam #define RXS_RDSTAT 6 /* status read started */ 3710773Ssam #define RXS_RDERR 7 /* error read started */ 3811205Ssam #define RXS_IDLE 8 /* device is idle */ 3910773Ssam u_short rxc_rxcs; /* extended error status */ 4010773Ssam u_short rxc_rxdb; 4110773Ssam u_short rxc_rxxt[4]; 4211205Ssam #define RX_MAXTIMEOUT 30 /* # seconds to wait before giving up */ 4310773Ssam } rx_ctlr[NFX]; 4410773Ssam 45*11649Shelge /* per-drive buffers */ 46*11649Shelge struct buf rrxbuf[NRX]; /* buffers for I/O */ 47*11649Shelge struct buf erxbuf[NRX]; /* buffers for reading error status */ 48*11649Shelge 4910773Ssam /* per-drive data */ 5010773Ssam struct rx_softc { 5111205Ssam int sc_flags; /* drive status flags */ 5210773Ssam #define RXF_DBLDEN 0x01 /* use double density */ 5310773Ssam #define RXF_DIRECT 0x02 /* use direct sector mapping */ 5410773Ssam #define RXF_TRKZERO 0x04 /* start mapping on track 0 */ 5510773Ssam #define RXF_DEVTYPE 0x07 /* density and mapping flags */ 5610773Ssam #define RXF_OPEN 0x10 /* open */ 5710773Ssam #define RXF_DDMK 0x20 /* deleted-data mark detected */ 5810773Ssam #define RXF_USEWDDS 0x40 /* write deleted-data sector */ 5911205Ssam int sc_csbits; /* constant bits for CS register */ 6011205Ssam int sc_tocnt; /* for watchdog routine */ 6110773Ssam } rx_softc[NRX]; 6210773Ssam 6311205Ssam struct rxerr { 6411205Ssam short rxcs; 6511205Ssam short rxdb; 6611205Ssam short rxxt[4]; /* error code dump from controller */ 6711633Shelge } rxerr[NRX]; 6811633Shelge /* End of per-drive data */ 6911205Ssam 7010773Ssam struct uba_device *rxdinfo[NRX]; 7110773Ssam struct uba_ctlr *rxminfo[NFX]; 7211633Shelge int rxprobe(), rxslave(), rxattach(), rxdgo(), rxintr(), rxwatch(), rxphys(); 7310773Ssam u_short rxstd[] = { 0177170, 0177150, 0 }; 7410773Ssam struct uba_driver fxdriver = 7510773Ssam { rxprobe, rxslave, rxattach, rxdgo, rxstd, "rx", rxdinfo, "fx", rxminfo }; 7610773Ssam 7710773Ssam int rxwstart; 7811633Shelge #define RXUNIT(dev) (minor(dev)>>3) 79*11649Shelge #define MASKREG(reg) (reg&0xffff) 8010773Ssam 8110773Ssam /* constants related to floppy data capacity */ 8210773Ssam #define RXSECS 2002 /* # sectors on a floppy */ 8311205Ssam #define DDSTATE (sc->sc_flags&RXF_DBLDEN) 8410773Ssam #define NBPS (DDSTATE ? 256 : 128) /* # bytes per sector */ 8510773Ssam #define NWPS (DDSTATE ? 128 : 64) /* # words per sector */ 8610773Ssam #define RXSIZE (DDSTATE ? 512512 : 256256) /* # bytes per disk */ 8710773Ssam #define SECSHFT (DDSTATE ? 8 : 7) /* # bits to shift for sctr # */ 8810773Ssam #define SECMASK (DDSTATE ? 0xff : 0x7f) /* shifted-out bits of offset */ 8910773Ssam 9011205Ssam #define B_CTRL 0x80000000 /* control (format) request */ 9110773Ssam 9210773Ssam /*ARGSUSED*/ 9310773Ssam rxprobe (reg) 9410773Ssam caddr_t reg; 9510773Ssam { 9611205Ssam register int br, cvec; /* value-result */ 9710773Ssam struct rxdevice *rxaddr = (struct rxdevice *)reg; 9810773Ssam 9910773Ssam #ifdef lint 10010773Ssam br = 0; cvec = br; br = cvec; 10111205Ssam rxintr(0); 10210773Ssam #endif lint 10310773Ssam rxaddr->rxcs = RX_INTR; 10410773Ssam DELAY(10); 10510773Ssam rxaddr->rxcs = 0; 10610773Ssam return (sizeof (*rxaddr)); 10710773Ssam } 10810773Ssam 10910773Ssam rxslave(ui,reg) 11010773Ssam struct uba_device *ui; 11110773Ssam caddr_t reg; 11210773Ssam { 11310773Ssam 11410773Ssam ui->ui_dk = 1; 11510773Ssam return (ui->ui_slave == 0 || ui->ui_slave == 1); 11610773Ssam } 11710773Ssam 11810773Ssam /*ARGSUSED*/ 11910773Ssam rxattach(ui) 12010773Ssam struct uba_device *ui; 12110773Ssam { 12210773Ssam 12310773Ssam } 12410773Ssam 12510773Ssam /*ARGSUSED1*/ 12610773Ssam rxopen(dev, flag) 12710773Ssam dev_t dev; 12810773Ssam int flag; 12910773Ssam { 13010773Ssam register int unit = RXUNIT(dev); 13110773Ssam register struct rx_softc *sc; 13210773Ssam register struct uba_device *ui; 13310773Ssam 13411633Shelge if (unit >= NRX || (ui = rxdinfo[unit]) == 0 || ui->ui_alive == 0) 13511205Ssam return (ENXIO); 13610773Ssam sc = &rx_softc[unit]; 13711205Ssam if (sc->sc_flags & RXF_OPEN) 13811205Ssam return (EBUSY); 13911205Ssam sc->sc_flags = RXF_OPEN | (minor(dev) & RXF_DEVTYPE); 14011205Ssam sc->sc_csbits = RX_INTR; 14111205Ssam sc->sc_csbits |= ui->ui_slave == 0 ? RX_DRV0 : RX_DRV1; 14211205Ssam sc->sc_csbits |= minor(dev) & RXF_DBLDEN ? RX_DDEN : RX_SDEN; 14311205Ssam return (0); 14410773Ssam } 14510773Ssam 14610773Ssam /*ARGSUSED1*/ 14710773Ssam rxclose(dev, flag) 14810773Ssam dev_t dev; 14910773Ssam int flag; 15010773Ssam { 15110773Ssam register struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; 15210773Ssam 15310773Ssam sc->sc_flags &= ~RXF_OPEN; 15410773Ssam sc->sc_csbits = 0; 15510773Ssam } 15610773Ssam 15710773Ssam rxstrategy(bp) 15810773Ssam register struct buf *bp; 15910773Ssam { 16010773Ssam struct uba_device *ui; 16110773Ssam register struct uba_ctlr *um; 16211205Ssam int s; 16310773Ssam 16410773Ssam ui = rxdinfo[RXUNIT(bp->b_dev)]; 16510773Ssam if (ui == 0 || ui->ui_alive == 0) { 16610773Ssam bp->b_flags |= B_ERROR; 16710773Ssam iodone(bp); 16810773Ssam return; 16910773Ssam } 17010773Ssam um = ui->ui_mi; 17110773Ssam bp->b_actf = NULL; 17211205Ssam s = spl5(); 173*11649Shelge if (um->um_tab.b_actf == NULL) 174*11649Shelge um->um_tab.b_actf = bp; 17510773Ssam else 176*11649Shelge um->um_tab.b_actl->b_forw = bp; 177*11649Shelge um->um_tab.b_actl = bp; 178*11649Shelge rxstart(um); 17910773Ssam splx(s); 18010773Ssam } 18110773Ssam 18210773Ssam /* 18310773Ssam * Sector mapping routine. 18410773Ssam * Two independent sets of choices are available: 18510773Ssam * 18610773Ssam * (a) The first logical sector may either be on track 1 or track 0. 18710773Ssam * (b) The sectors on a track may either be taken in 2-for-1 interleaved 18810773Ssam * fashion or directly. 18910773Ssam * This gives a total of four possible mapping schemes. 19010773Ssam * 19110773Ssam * Physical tracks on the RX02 are numbered 0-76. Physical sectors on 19210773Ssam * each track are numbered 1-26. 19310773Ssam * 19410773Ssam * When interleaving is used, sectors on the first logical track are 19510773Ssam * taken in the order 1, 3, 5, ..., 25, 2, 4, 6, ..., 26. A skew of 19610773Ssam * six sectors per track is also used (to allow time for the heads to 19710773Ssam * move); hence, the sectors on the second logical track are taken in 19810773Ssam * the order 7, 9, 11, ..., 25, 1, 3, 5, 8, 10, 12, ..., 26, 2, 4, 6; 19910773Ssam * the third logical track starts with sector 13; and so on. 20010773Ssam * 20110773Ssam * When the mapping starts with track 1, track 0 is the last logical 20210773Ssam * track, and this track is always handled directly (without inter- 20310773Ssam * leaving), even when the rest of the disk is interleaved. (This is 20410773Ssam * still compatible with DEC RT-11, which does not use track 0 at all.) 20510773Ssam */ 20611205Ssam rxmap(bp, psector, ptrack) 20711205Ssam struct buf *bp; 20811205Ssam int *psector, *ptrack; 20910773Ssam { 21010773Ssam register int lt, ls, ptoff; 21111205Ssam struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)]; 21210773Ssam 213*11649Shelge ls = ( bp->b_blkno * DEV_BSIZE ) / NBPS; 21411205Ssam lt = ls / 26; 21511205Ssam ls %= 26; 21610773Ssam /* 21710773Ssam * The "physical track offset" (ptoff) takes the 21810773Ssam * starting physical track (0 or 1) and the desired 21910773Ssam * interleaving into account. If lt+ptoff >= 77, 22010773Ssam * then interleaving is not performed. 22110773Ssam */ 22210773Ssam ptoff = 0; 22311205Ssam if (sc->sc_flags&RXF_DIRECT) 22411205Ssam ptoff = 77; 22511205Ssam if (sc->sc_flags&RXF_TRKZERO) 22610773Ssam ptoff++; 22710773Ssam if (lt + ptoff < 77) 22810773Ssam ls = ((ls << 1) + (ls >= 13) + (6*lt)) % 26; 22911205Ssam *ptrack = (lt + ptoff) % 77; 23011205Ssam *psector = ls + 1; 23110773Ssam } 23210773Ssam 23310773Ssam rxstart(um) 23410773Ssam register struct uba_ctlr *um; 23510773Ssam { 23610773Ssam register struct rxdevice *rxaddr; 23710773Ssam register struct rx_ctlr *rxc; 23810773Ssam register struct rx_softc *sc; 23910773Ssam struct buf *bp; 24011205Ssam int unit, sector, track; 24110773Ssam 242*11649Shelge if (um->um_tab.b_active || (bp = um->um_tab.b_actf) == NULL) 24310773Ssam return; 24411205Ssam um->um_tab.b_active++; 24510773Ssam unit = RXUNIT(bp->b_dev); 24610773Ssam sc = &rx_softc[unit]; 24710773Ssam rxaddr = (struct rxdevice *)um->um_addr; 24810773Ssam rxc = &rx_ctlr[um->um_ctlr]; 24911205Ssam rxtimo(bp->b_dev); /* start watchdog */ 25011205Ssam if (bp->b_flags&B_CTRL) { /* format */ 25110773Ssam rxc->rxc_state = RXS_FORMAT; 25210773Ssam rxaddr->rxcs = RX_FORMAT | sc->sc_csbits; 25311205Ssam while ((rxaddr->rxcs&RX_TREQ) == 0) 25410773Ssam ; 25510773Ssam rxaddr->rxdb = 'I'; 25610773Ssam return; 25710773Ssam } 25811205Ssam if (bp->b_flags&B_READ) { /* read */ 25911205Ssam rxmap(bp, §or, &track); 26010773Ssam rxc->rxc_state = RXS_READ; 26110773Ssam rxaddr->rxcs = RX_READ | sc->sc_csbits; 26211633Shelge printf("rxstart: (read) track=%d, sector=%d\n", track, sector); 26311205Ssam while ((rxaddr->rxcs&RX_TREQ) == 0) 26410773Ssam ; 26511205Ssam rxaddr->rxdb = (u_short)sector; 26611205Ssam while ((rxaddr->rxcs&RX_TREQ) == 0) 26710773Ssam ; 26811205Ssam rxaddr->rxdb = (u_short)track; 26910773Ssam return; 27010773Ssam } 27111205Ssam rxc->rxc_state = RXS_FILL; /* write */ 27210773Ssam um->um_cmd = RX_FILL; 27310773Ssam (void) ubago(rxdinfo[unit]); 27410773Ssam } 27510773Ssam 27610773Ssam rxdgo(um) 27710773Ssam struct uba_ctlr *um; 27810773Ssam { 27910773Ssam register struct rxdevice *rxaddr = (struct rxdevice *)um->um_addr; 28010773Ssam int ubinfo = um->um_ubinfo; 281*11649Shelge struct buf *bp = um->um_tab.b_actf; 28210773Ssam struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)]; 28310773Ssam struct rx_ctlr *rxc = &rx_ctlr[um->um_ctlr]; 28410773Ssam 28511205Ssam sc->sc_tocnt = 0; 28610773Ssam if (rxc->rxc_state != RXS_RDERR) { 28711205Ssam while ((rxaddr->rxcs&RX_TREQ) == 0) 28810773Ssam ; 28911205Ssam rxaddr->rxdb = bp->b_bcount >> 1; 29010773Ssam } 29111205Ssam while ((rxaddr->rxcs&RX_TREQ) == 0) 29210773Ssam ; 29311205Ssam rxaddr->rxdb = ubinfo; 29410773Ssam rxaddr->rxcs = um->um_cmd | ((ubinfo & 0x30000) >> 4) | sc->sc_csbits; 29510773Ssam } 29610773Ssam 29711205Ssam rxintr(dev) 29811205Ssam dev_t dev; 29910773Ssam { 30011205Ssam int unit = RXUNIT(dev), sector, track; 30111205Ssam struct uba_ctlr *um = rxminfo[unit]; 30211205Ssam register struct rxdevice *rxaddr; 30311205Ssam register struct buf *bp; 30410773Ssam register struct rx_softc *sc = &rx_softc[unit]; 30510773Ssam struct uba_device *ui = rxdinfo[unit]; 30611205Ssam struct rxerr *er; 30711205Ssam register struct rx_ctlr *rxc; 30810773Ssam 30911205Ssam sc->sc_tocnt = 0; 31011205Ssam if (!um->um_tab.b_active) 31110773Ssam return; 31211205Ssam rxaddr = (struct rxdevice *)um->um_addr; 31311205Ssam rxc = &rx_ctlr[um->um_ctlr]; 314*11649Shelge er = &rxerr[unit]; 315*11649Shelge bp = um->um_tab.b_actf; 316*11649Shelge printf("rxintr: unit=%d, state=0x%x, ctrlr status=0x%x\n", 317*11649Shelge unit, rxc->rxc_state, rxaddr->rxcs); 31811205Ssam if ((rxaddr->rxcs & RX_ERR) && 31911205Ssam rxc->rxc_state != RXS_RDSTAT && rxc->rxc_state != RXS_RDERR) 32011205Ssam goto error; 32110773Ssam switch (rxc->rxc_state) { 32210773Ssam 32311205Ssam /* 32411205Ssam * Incomplete commands. Perform next step 32511205Ssam * and return. Note that b_active is set on 32611205Ssam * entrance and, therefore, also on exit. 32711205Ssam */ 32810773Ssam case RXS_READ: 32910773Ssam if (rxaddr->rxdb & RXES_DDMARK) 33010773Ssam sc->sc_flags |= RXF_DDMK; 33110773Ssam else 33210773Ssam sc->sc_flags &= ~RXF_DDMK; 33310773Ssam rxc->rxc_state = RXS_EMPTY; 33410773Ssam um->um_cmd = RX_EMPTY; 33510773Ssam (void) ubago(ui); 33610773Ssam return; 33710773Ssam 33810773Ssam case RXS_FILL: 33910773Ssam rxc->rxc_state = RXS_WRITE; 34010773Ssam if (sc->sc_flags & RXF_USEWDDS) { 34110773Ssam rxaddr->rxcs = RX_WDDS | sc->sc_csbits; 34210773Ssam sc->sc_flags &= ~RXF_USEWDDS; 34310773Ssam } else 34410773Ssam rxaddr->rxcs = RX_WRITE | sc->sc_csbits; 34511205Ssam while ((rxaddr->rxcs&RX_TREQ) == 0) 34610773Ssam ; 34711205Ssam rxmap(bp, §or, &track); 34811205Ssam rxaddr->rxdb = sector; 34911205Ssam while ((rxaddr->rxcs&RX_TREQ) == 0) 35010773Ssam ; 35111205Ssam rxaddr->rxdb = track; 35210773Ssam return; 35310773Ssam 35411205Ssam /* 35511205Ssam * Possibly completed command. 35611205Ssam */ 35710773Ssam case RXS_RDSTAT: 35811205Ssam if (rxaddr->rxdb&RXES_READY) 35910773Ssam goto rderr; 36010773Ssam bp->b_error = EBUSY; 36110773Ssam bp->b_flags |= B_ERROR; 36211205Ssam goto done; 36310773Ssam 36411205Ssam /* 36511205Ssam * Command completed. 36611205Ssam */ 36711205Ssam case RXS_EMPTY: 36811205Ssam case RXS_WRITE: 36911205Ssam case RXS_FORMAT: 37011205Ssam goto done; 37111205Ssam 37210773Ssam case RXS_RDERR: 37311205Ssam rxmap(bp, §or, &track); 37411205Ssam printf("rx%d: hard error, lsn%d (trk %d psec %d) ", 37511214Shelge unit, bp->b_blkno * (NBPS / DEV_BSIZE), 37611205Ssam track, sector); 377*11649Shelge printf("cs=%b, db=%b, err=%x\n", MASKREG(er->rxcs), 378*11649Shelge RXCS_BITS, MASKREG(er->rxdb), RXES_BITS, 379*11649Shelge MASKREG(er->rxxt[0])); 380*11649Shelge printf("errstatus: 0x%x, 0x%x, 0x%x, 0x%x\n", er->rxxt[0], 381*11649Shelge er->rxxt[1], er->rxxt[2], er->rxxt[3]); 38211205Ssam goto done; 38310773Ssam 38410773Ssam default: 38511205Ssam printf("rx%d: state %d (reset)", unit, rxc->rxc_state); 38611205Ssam rxreset(um->um_ubanum); 38710773Ssam printf("\n"); 38810773Ssam return; 38910773Ssam } 39010773Ssam error: 39110773Ssam /* 39210773Ssam * In case of an error: 39310773Ssam * (a) Give up now if a format (ioctl) was in progress, or if a 39410773Ssam * density error was detected. 39510773Ssam * (b) Retry up to nine times if a CRC (data) error was detected, 39610773Ssam * then give up if the error persists. 39710773Ssam * (c) In all other cases, reinitialize the drive and try the 39810773Ssam * operation once more before giving up. 39910773Ssam */ 40011205Ssam if (rxc->rxc_state == RXS_FORMAT || (rxaddr->rxdb&RXES_DENERR)) 40110773Ssam goto giveup; 40210773Ssam if (rxaddr->rxdb & RXES_CRCERR) { 40310773Ssam if (++bp->b_errcnt >= 10) 40410773Ssam goto giveup; 40510773Ssam goto retry; 40610773Ssam } 40710773Ssam bp->b_errcnt += 9; 40810773Ssam if (bp->b_errcnt >= 10) 40910773Ssam goto giveup; 41010773Ssam rxaddr->rxcs = RX_INIT; 41110773Ssam /* no way to get an interrupt for "init done", so just wait */ 41211205Ssam while ((rxaddr->rxdb&RX_DONE) == 0) 41310773Ssam ; 41410773Ssam retry: 41511205Ssam /* 41611205Ssam * In case we already have UNIBUS resources, give 41711205Ssam * them back since we reallocate things in rxstart. 418*11649Shelge * Also, the active flag must be reset, otherwise rxstart 419*11649Shelge * will refuse to restart the transfer 42011205Ssam */ 42111205Ssam if (um->um_ubinfo) 42211205Ssam ubadone(um); 423*11649Shelge um->um_tab.b_active = 0; 42411205Ssam rxstart(um); 42510773Ssam return; 42611205Ssam 42710773Ssam giveup: 42810773Ssam /* 42910773Ssam * Hard I/O error -- 43011205Ssam * Density errors are not noted on the console since the 43111205Ssam * only way to determine the density of an unknown disk 43211205Ssam * is to try one density or the other at random and see 43311205Ssam * which one doesn't give a density error. 43410773Ssam */ 43510773Ssam if (rxaddr->rxdb & RXES_DENERR) { 43611205Ssam bp->b_error = EIO; 43710773Ssam bp->b_flags |= B_ERROR; 43810773Ssam goto done; 43910773Ssam } 44010773Ssam rxc->rxc_state = RXS_RDSTAT; 44110773Ssam rxaddr->rxcs = RX_RDSTAT | sc->sc_csbits; 44210773Ssam return; 44311205Ssam 44410773Ssam rderr: 44510773Ssam /* 44610773Ssam * A hard error (other than not ready or density) has occurred. 44710773Ssam * Read the extended error status information. 44810773Ssam * Before doing this, save the current CS and DB register values, 44910773Ssam * because the read error status operation may modify them. 45011205Ssam * Insert buffer with request at the head of the queue. 45110773Ssam */ 45210773Ssam bp->b_error = EIO; 45310773Ssam bp->b_flags |= B_ERROR; 45410773Ssam ubadone(um); 45510773Ssam er->rxcs = rxaddr->rxcs; 45610773Ssam er->rxdb = rxaddr->rxdb; 45711214Shelge bp = &erxbuf[unit]; 45810773Ssam bp->b_un.b_addr = (caddr_t)er->rxxt; 45910773Ssam bp->b_bcount = sizeof (er->rxxt); 46010773Ssam bp->b_flags &= ~(B_DIRTY|B_UAREA|B_PHYS|B_PAGET); 461*11649Shelge if (um->um_tab.b_actf == NULL) 462*11649Shelge um->um_tab.b_actl = bp; 463*11649Shelge bp->b_forw = um->um_tab.b_actf; 464*11649Shelge um->um_tab.b_actf = bp; 46510773Ssam rxc->rxc_state = RXS_RDERR; 46610773Ssam um->um_cmd = RX_RDERR; 46710773Ssam (void) ubago(ui); 46811205Ssam return; 46911205Ssam done: 47011205Ssam um->um_tab.b_active = 0; 471*11649Shelge um->um_tab.b_actf = bp->b_forw; 47211205Ssam bp->b_resid = 0; 47311205Ssam iodone(bp); 47411205Ssam rxc->rxc_state = RXS_IDLE; 47511205Ssam ubadone(um); 47611205Ssam /* 477*11649Shelge * If this unit (controller) has more work to do, 47811205Ssam * start it up right away 47911205Ssam */ 480*11649Shelge if (um->um_tab.b_actf) 48111214Shelge rxstart(um); 48210773Ssam } 48310773Ssam 48410773Ssam /*ARGSUSED*/ 48510773Ssam minrxphys(bp) 48610773Ssam struct buf *bp; 48710773Ssam { 48811214Shelge struct rx_softc *sc = &rx_softc[RXUNIT(bp->b_dev)]; 48910773Ssam 49010773Ssam if (bp->b_bcount > NBPS) 49110773Ssam bp->b_bcount = NBPS; 49210773Ssam } 49310773Ssam 49411205Ssam rxtimo(dev) 49511205Ssam dev_t dev; 49610773Ssam { 49710773Ssam register struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; 49810773Ssam 49911205Ssam if (sc->sc_flags & RXF_OPEN) 50011205Ssam timeout(rxtimo, (caddr_t)dev, hz); 50110773Ssam if (++sc->sc_tocnt < RX_MAXTIMEOUT) 50210773Ssam return; 503*11649Shelge printf("rx: timeout on dev %d\n", dev); 50410773Ssam rxintr(dev); 50510773Ssam } 50610773Ssam 50710773Ssam rxreset(uban) 50810773Ssam int uban; 50910773Ssam { 51010773Ssam register struct uba_ctlr *um; 51110773Ssam register struct rxdevice *rxaddr; 51210773Ssam register int ctlr; 51310773Ssam 51410773Ssam for (ctlr = 0; ctlr < NFX; ctlr++) { 51510773Ssam if ((um = rxminfo[ctlr]) == 0 || um->um_ubanum != uban || 51610773Ssam um->um_alive == 0) 51710773Ssam continue; 51811633Shelge printf(" fx%d: ", ctlr); 51910773Ssam if (um->um_ubinfo) { 52010773Ssam printf("<%d>", (um->um_ubinfo>>28)&0xf); 52111205Ssam um->um_ubinfo = 0; 52210773Ssam } 52310773Ssam rx_ctlr[ctlr].rxc_state = RXS_IDLE; 52410773Ssam rxaddr = (struct rxdevice *)um->um_addr; 52511205Ssam rxaddr->rxcs = RX_INIT; 52611205Ssam while ((rxaddr->rxdb&RX_DONE) == 0) 52710773Ssam ; 52811205Ssam rxstart(um); 52910773Ssam } 53010773Ssam } 53110773Ssam 53211205Ssam rxread(dev, uio) 53310773Ssam dev_t dev; 53411205Ssam struct uio *uio; 53510773Ssam { 53610773Ssam int unit = RXUNIT(dev), ctlr = rxdinfo[unit]->ui_ctlr; 53711214Shelge struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; 53810773Ssam 53911205Ssam if (uio->uio_offset + uio->uio_resid > RXSIZE) 54011205Ssam return (ENXIO); 54111205Ssam if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0) 54211205Ssam return (EIO); 54311633Shelge return (physio(rxstrategy, &rrxbuf[ctlr], dev, B_READ, minrxphys, uio)); 54410773Ssam } 54510773Ssam 54611205Ssam rxwrite(dev, uio) 54710773Ssam dev_t dev; 54811205Ssam struct uio *uio; 54910773Ssam { 55010773Ssam int unit = RXUNIT(dev), ctlr = rxdinfo[unit]->ui_ctlr; 55111214Shelge struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; 55210773Ssam 55311205Ssam if (uio->uio_offset + uio->uio_resid > RXSIZE) 55411205Ssam return (ENXIO); 55511205Ssam if (uio->uio_offset < 0 || (uio->uio_offset & SECMASK) != 0) 55611205Ssam return (EIO); 55711633Shelge return(physio(rxstrategy, &rrxbuf[ctlr], dev, B_WRITE, minrxphys, uio)); 55810773Ssam } 55910773Ssam 56010773Ssam /* 56110773Ssam * Control routine: 56210773Ssam * processes three kinds of requests: 56310773Ssam * 56411633Shelge * (1) Set density (i.e., format the diskette) according to 56511633Shelge * that specified by the open device. 56610773Ssam * (2) Arrange for the next sector to be written with a deleted- 56710773Ssam * data mark. 56810773Ssam * (3) Report whether the last sector read had a deleted-data mark 56910773Ssam * (by returning with an EIO error code if it did). 57010773Ssam * 57110773Ssam * Requests relating to deleted-data marks can be handled right here. 57210773Ssam * A "set density" request, however, must additionally be processed 57310773Ssam * through "rxstart", just like a read or write request. 57410773Ssam */ 57510773Ssam /*ARGSUSED3*/ 57611205Ssam rxioctl(dev, cmd, data, flag) 57710773Ssam dev_t dev; 57810773Ssam int cmd; 57911205Ssam caddr_t data; 58010773Ssam int flag; 58110773Ssam { 58210773Ssam int unit = RXUNIT(dev); 58310773Ssam struct rx_softc *sc = &rx_softc[unit]; 58410773Ssam 58510773Ssam switch (cmd) { 58610773Ssam 58711205Ssam case RXIOC_FORMAT: 58810773Ssam if ((flag&FWRITE) == 0) 58911205Ssam return (EBADF); 59011214Shelge return (rxformat(dev)); 59110773Ssam 59211205Ssam case RXIOC_WDDS: 59311205Ssam sc->sc_flags |= RXF_USEWDDS; 59411205Ssam return (0); 59510773Ssam 59611205Ssam case RXIOC_RDDSMK: 59711205Ssam *(int *)data = sc->sc_flags & RXF_DDMK; 59811205Ssam return (0); 59910773Ssam } 60011205Ssam return (ENXIO); 60111205Ssam } 60210773Ssam 60311205Ssam /* 60411205Ssam * Initiate a format command. 60511205Ssam */ 60611214Shelge rxformat(dev) 60711214Shelge dev_t dev; 60811205Ssam { 60911214Shelge int ctlr = rxdinfo[RXUNIT(dev)]->ui_mi->um_ctlr; 61011205Ssam struct buf *bp; 61111214Shelge struct rx_softc *sc = &rx_softc[RXUNIT(dev)]; 61211205Ssam int s, error = 0; 61311205Ssam 614*11649Shelge bp = &rrxbuf[RXUNIT(dev)]; 61510773Ssam s = spl5(); 61610773Ssam while (bp->b_flags & B_BUSY) 61710773Ssam sleep(bp, PRIBIO); 61810773Ssam bp->b_flags = B_BUSY | B_CTRL; 61910773Ssam splx(s); 62011205Ssam sc->sc_flags = RXS_FORMAT; 62110773Ssam bp->b_dev = dev; 62210773Ssam bp->b_error = 0; 62311205Ssam bp->b_resid = 0; 62410773Ssam rxstrategy (bp); 62510773Ssam iowait(bp); 62611205Ssam if (bp->b_flags & B_ERROR) 62711205Ssam error = bp->b_error; 62810773Ssam bp->b_flags &= ~B_BUSY; 62911205Ssam wakeup((caddr_t)bp); 63011205Ssam return (error); 63110773Ssam } 63210773Ssam #endif 633