123248Smckusick /* 235049Skarels * Copyright (c) 1982, 1988 Regents of the University of California. 323248Smckusick * All rights reserved. The Berkeley software License Agreement 423248Smckusick * specifies the terms and conditions for redistribution. 523248Smckusick * 6*35522Sbostic * @(#)up.c 7.8 (Berkeley) 09/17/88 723248Smckusick */ 89974Ssam 910023Ssam /* 1033647Sbostic * UNIBUS peripheral standalone driver with ECC correction and bad 1133647Sbostic * block forwarding. Also supports header operation and write check 1233647Sbostic * for data and/or header. 1310023Ssam */ 1432196Skarels #include "param.h" 1532196Skarels #include "inode.h" 1632196Skarels #include "fs.h" 1732196Skarels #include "dkbad.h" 1833647Sbostic #include "disklabel.h" 199974Ssam 2033408Skarels #include "../vax/pte.h" 219974Ssam 2233408Skarels #include "../vaxuba/upreg.h" 2333408Skarels #include "../vaxuba/ubareg.h" 2433408Skarels 2510023Ssam #include "saio.h" 269974Ssam #include "savax.h" 279974Ssam 2825443Skarels #define RETRIES 27 2925443Skarels 3010352Shelge #define MAXBADDESC 126 /* max number of bad sectors recorded */ 3110352Shelge #define SECTSIZ 512 /* sector size in bytes */ 3210352Shelge #define HDRSIZ 4 /* number of bytes in sector header */ 3311365Ssam 3433647Sbostic #define MAXUNIT 8 3533533Sbostic #define MAXCTLR 1 /* all addresses must be specified */ 36*35522Sbostic static u_short upstd[MAXCTLR] = { 0776700 }; 37*35522Sbostic static struct disklabel uplabel[MAXNUBA][MAXCTLR][MAXUNIT]; 38*35522Sbostic static char lbuf[SECTSIZ]; 399974Ssam 4011143Ssam extern struct st upst[]; 4110023Ssam 4232196Skarels #ifndef SMALL 4333647Sbostic struct dkbad upbad[MAXNUBA][MAXCTLR][MAXUNIT]; /* bad sector table */ 4432196Skarels #endif 4533647Sbostic int sectsiz; /* real sector size */ 4611365Ssam 4725443Skarels struct up_softc { 4825443Skarels char gottype; 4925443Skarels char type; 5025443Skarels char debug; 5125443Skarels # define UPF_BSEDEBUG 01 /* debugging bad sector forwarding */ 5225443Skarels # define UPF_ECCDEBUG 02 /* debugging ecc correction */ 5325443Skarels int retries; 5425443Skarels int ecclim; 5533647Sbostic } up_softc[MAXNUBA][MAXCTLR][MAXUNIT]; 5625443Skarels 579974Ssam u_char up_offset[16] = { 589974Ssam UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400, 599974Ssam UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800, 609974Ssam UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200, 619974Ssam 0, 0, 0, 0 629974Ssam }; 639974Ssam 649974Ssam upopen(io) 659974Ssam register struct iob *io; 669974Ssam { 6710023Ssam register struct updevice *upaddr; 6833533Sbostic register struct up_softc *sc; 6911118Ssam register struct st *st; 7035049Skarels register struct disklabel *lp; 7135049Skarels struct disklabel *dlp; 7233647Sbostic register int unit; 7335049Skarels int error = 0, uba, ctlr; 749974Ssam 7535049Skarels if ((u_int)(uba = io->i_adapt) >= nuba) 7635049Skarels return (EADAPT); 7735049Skarels if ((u_int)(ctlr = io->i_ctlr) >= MAXCTLR) 7833533Sbostic return (ECTLR); 7933647Sbostic unit = io->i_unit; 8035049Skarels if ((u_int)unit >= MAXUNIT) 8135049Skarels return (EUNIT); 82*35522Sbostic upaddr = (struct updevice *)ubamem(uba, upstd[ctlr]); 8335049Skarels upaddr->upcs2 = unit; 8433533Sbostic while ((upaddr->upcs1 & UP_DVA) == 0); 8535049Skarels sc = &up_softc[uba][ctlr][unit]; 8635049Skarels lp = &uplabel[uba][ctlr][unit]; 8725443Skarels if (sc->gottype == 0) { 8810023Ssam register int i; 8910023Ssam struct iob tio; 9010023Ssam 9133647Sbostic #ifndef SMALL 9225443Skarels sc->retries = RETRIES; 9325443Skarels sc->ecclim = 11; 9425443Skarels sc->debug = 0; 9533647Sbostic #endif 9633647Sbostic /* Read in the pack label. */ 9733647Sbostic lp->d_nsectors = 32; 9833647Sbostic lp->d_secpercyl = 19*32; 9933647Sbostic tio = *io; 10033647Sbostic tio.i_bn = LABELSECTOR; 10133647Sbostic tio.i_ma = lbuf; 10233647Sbostic tio.i_cc = SECTSIZ; 10333647Sbostic tio.i_flgs |= F_RDDATA; 10433647Sbostic if (upstrategy(&tio, READ) != SECTSIZ) 10534520Skarels error = ERDLAB; 10633647Sbostic dlp = (struct disklabel *)(lbuf + LABELOFFSET); 10734520Skarels if (error == 0 && (dlp->d_magic != DISKMAGIC || 10834520Skarels dlp->d_magic2 != DISKMAGIC)) 10934520Skarels error = EUNLAB; 11034520Skarels if (error == 0) 11134520Skarels *lp = *dlp; 11234520Skarels else 11333647Sbostic #ifdef COMPAT_42 11434520Skarels if (upmaptype(unit, upaddr, lp) == 0) 11533647Sbostic #endif 11634520Skarels return (error); 11733647Sbostic 11832196Skarels #ifndef SMALL 11933647Sbostic /* Read in the bad sector table. */ 12033647Sbostic tio.i_bn = lp->d_secpercyl * lp->d_ncylinders - lp->d_nsectors; 12135049Skarels tio.i_ma = (char *)&upbad[uba][ctlr][unit]; 12233647Sbostic tio.i_cc = sizeof(struct dkbad); 12310023Ssam tio.i_flgs |= F_RDDATA; 12410023Ssam for (i = 0; i < 5; i++) { 12533647Sbostic if (upstrategy(&tio, READ) == sizeof(struct dkbad)) 12610023Ssam break; 1279974Ssam tio.i_bn += 2; 1289974Ssam } 1299974Ssam if (i == 5) { 13033647Sbostic printf("up: can't read bad sector table\n"); 13110352Shelge for (i = 0; i < MAXBADDESC; i++) { 13235049Skarels upbad[uba][ctlr][unit].bt_bad[i].bt_cyl = -1; 13335049Skarels upbad[uba][ctlr][unit].bt_bad[i].bt_trksec = -1; 1349974Ssam } 13533647Sbostic } 13632196Skarels #endif 13725443Skarels sc->gottype = 1; 1389974Ssam } 13933647Sbostic if (io->i_part >= lp->d_npartitions || 14033647Sbostic lp->d_partitions[io->i_part].p_size == 0) 14135049Skarels return (EPART); 14233647Sbostic io->i_boff = lp->d_partitions[io->i_part].p_offset; 14310023Ssam io->i_flgs &= ~F_TYPEMASK; 14433408Skarels return (0); 1459974Ssam } 1469974Ssam 1479974Ssam upstrategy(io, func) 1489974Ssam register struct iob *io; 14933647Sbostic int func; 1509974Ssam { 15111317Ssam int cn, tn, sn, o; 15210352Shelge register unit = io->i_unit; 15333408Skarels register daddr_t bn; 1549974Ssam int recal, info, waitdry; 15533533Sbostic register struct updevice *upaddr; 15633647Sbostic register struct disklabel *lp; 15733533Sbostic struct up_softc *sc; 15833408Skarels int error, rv = io->i_cc; 15933408Skarels #ifndef SMALL 16033408Skarels int doprintf = 0; 16133408Skarels #endif 1629974Ssam 163*35522Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, upstd[io->i_ctlr]); 16433533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 16533647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 16610352Shelge sectsiz = SECTSIZ; 16735049Skarels #ifndef SMALL 16811085Ssam if (io->i_flgs & (F_HDR|F_HCHECK)) 16910352Shelge sectsiz += HDRSIZ; 17035049Skarels #endif 17135049Skarels upaddr->upcs2 = unit; 1729974Ssam if ((upaddr->upds & UPDS_VV) == 0) { 1739974Ssam upaddr->upcs1 = UP_DCLR|UP_GO; 1749974Ssam upaddr->upcs1 = UP_PRESET|UP_GO; 1759974Ssam upaddr->upof = UPOF_FMT22; 1769974Ssam } 17725443Skarels if ((upaddr->upds & UPDS_DREADY) == 0) { 17835049Skarels printf("up%d not ready\n", unit); 17925443Skarels return (-1); 18025443Skarels } 1819974Ssam info = ubasetup(io, 1); 1829974Ssam upaddr->upwc = -io->i_cc / sizeof (short); 18311085Ssam recal = 0; 18411085Ssam io->i_errcnt = 0; 18511085Ssam 18610638Shelge restart: 18711317Ssam o = io->i_cc + (upaddr->upwc * sizeof (short)); 18811317Ssam upaddr->upba = info + o; 18911317Ssam bn = io->i_bn + o / sectsiz; 19033408Skarels #ifndef SMALL 19135049Skarels error = 0; 19225443Skarels if (doprintf && sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) 19311386Ssam printf("wc=%d o=%d i_bn=%d bn=%d\n", 19411365Ssam upaddr->upwc, o, io->i_bn, bn); 19533408Skarels #endif 19635049Skarels upwaitdry(upaddr); 19733647Sbostic if (upstart(io, bn, lp) != 0) { 19825443Skarels rv = -1; 19925443Skarels goto done; 20010352Shelge } 20135049Skarels upwaitrdy(upaddr); 20211085Ssam /* 20311085Ssam * If transfer has completed, free UNIBUS 20411085Ssam * resources and return transfer size. 20511085Ssam */ 20615067Skarels if ((upaddr->upds&UPDS_ERR) == 0 && (upaddr->upcs1&UP_TRE) == 0) 20715067Skarels goto done; 20825443Skarels bn = io->i_bn + 20925443Skarels (io->i_cc + upaddr->upwc * sizeof (short)) / sectsiz; 21025443Skarels if (upaddr->uper1 & (UPER1_DCK|UPER1_ECH)) 21125443Skarels bn--; 21233647Sbostic cn = bn / lp->d_secpercyl; 21333647Sbostic sn = bn % lp->d_secpercyl; 21433647Sbostic tn = sn / lp->d_nsectors; 21533647Sbostic sn = sn % lp->d_nsectors; 21632196Skarels #ifndef SMALL 21725443Skarels if (sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) { 21825443Skarels printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ", 21925443Skarels bn, cn, tn, sn); 22011386Ssam printf("cs2=%b er1=%b er2=%b wc=%d\n", 22111365Ssam upaddr->upcs2, UPCS2_BITS, upaddr->uper1, 22211386Ssam UPER1_BITS, upaddr->uper2, UPER2_BITS, upaddr->upwc); 22311365Ssam } 22432196Skarels #endif 2259974Ssam waitdry = 0; 22611386Ssam while ((upaddr->upds&UPDS_DRY) == 0 && ++waitdry < sectsiz) 22710023Ssam DELAY(5); 22832196Skarels #ifndef SMALL 22911085Ssam if (upaddr->uper1&UPER1_WLE) { 23011085Ssam /* 23111085Ssam * Give up on write locked devices immediately. 23211085Ssam */ 23311085Ssam printf("up%d: write locked\n", unit); 23425443Skarels rv = -1; 23525443Skarels goto done; 23611085Ssam } 23725443Skarels if (upaddr->uper2 & UPER2_BSE) { 23825443Skarels if ((io->i_flgs&F_NBSF) == 0 && upecc(io, BSE) == 0) 23925443Skarels goto success; 24025443Skarels error = EBSE; 24125443Skarels goto hard; 24225443Skarels } 24325443Skarels /* 24425443Skarels * ECC error. If a soft error, correct it; 24525443Skarels * if correction is too large, no more retries. 24625443Skarels */ 24725443Skarels if ((upaddr->uper1 & (UPER1_DCK|UPER1_ECH|UPER1_HCRC)) == UPER1_DCK) { 24825443Skarels if (upecc(io, ECC) == 0) 24925443Skarels goto success; 25025443Skarels error = EECC; 25125443Skarels goto hard; 25225443Skarels } 25325443Skarels /* 25433647Sbostic * If the error is a header CRC, check if a replacement sector 25533647Sbostic * exists in the bad sector table. 25625443Skarels */ 25725443Skarels if ((upaddr->uper1&UPER1_HCRC) && (io->i_flgs&F_NBSF) == 0 && 25825443Skarels upecc(io, BSE) == 0) 25925443Skarels goto success; 26032196Skarels #endif 26125443Skarels if (++io->i_errcnt > sc->retries) { 2629974Ssam /* 2639974Ssam * After 28 retries (16 without offset, and 2649974Ssam * 12 with offset positioning) give up. 2659974Ssam */ 26610352Shelge hard: 26735049Skarels #ifndef SMALL 26825443Skarels if (error == 0) { 26925443Skarels error = EHER; 27025443Skarels if (upaddr->upcs2 & UPCS2_WCE) 27125443Skarels error = EWCK; 27225443Skarels } 27335049Skarels io->i_error = error; 27435049Skarels #endif 27525443Skarels printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ", 27625443Skarels bn, cn, tn, sn); 27725443Skarels printf("cs2=%b er1=%b er2=%b\n", 27811085Ssam upaddr->upcs2, UPCS2_BITS, upaddr->uper1, 27911085Ssam UPER1_BITS, upaddr->uper2, UPER2_BITS); 2809974Ssam upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; 28110352Shelge io->i_errblk = bn; 28215067Skarels if (io->i_errcnt >= 16) { 28315067Skarels upaddr->upof = UPOF_FMT22; 28415067Skarels upaddr->upcs1 = UP_RTC|UP_GO; 28535049Skarels upwaitdry(upaddr); 28615067Skarels } 28725443Skarels rv = -1; 28825443Skarels goto done; 28911085Ssam } 29011085Ssam /* 29133647Sbostic * Clear drive error and, every eight attempts, (starting with the 29233647Sbostic * fourth) recalibrate to clear the slate. 2939974Ssam */ 2949974Ssam upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; 29510638Shelge if ((io->i_errcnt&07) == 4 ) { 2969974Ssam upaddr->upcs1 = UP_RECAL|UP_GO; 29735049Skarels upwaitdry(upaddr); 2989974Ssam upaddr->updc = cn; 2999974Ssam upaddr->upcs1 = UP_SEEK|UP_GO; 30035049Skarels upwaitdry(upaddr); 30115067Skarels } 30215067Skarels if (io->i_errcnt >= 16 && (func & READ)) { 3039974Ssam upaddr->upof = up_offset[io->i_errcnt & 017] | UPOF_FMT22; 3049974Ssam upaddr->upcs1 = UP_OFFSET|UP_GO; 30535049Skarels upwaitdry(upaddr); 3069974Ssam } 30710638Shelge goto restart; 30811085Ssam 3099974Ssam success: 31011386Ssam #define rounddown(x, y) (((x) / (y)) * (y)) 31111386Ssam upaddr->upwc = rounddown(upaddr->upwc, sectsiz / sizeof (short)); 31211386Ssam if (upaddr->upwc) { 31333408Skarels #ifndef SMALL 31411317Ssam doprintf++; 31533408Skarels #endif 31610638Shelge goto restart; 31711317Ssam } 31815067Skarels done: 3199974Ssam ubafree(io, info); 32015067Skarels /* 32115067Skarels * If we were offset positioning, 32215067Skarels * return to centerline. 32315067Skarels */ 32415067Skarels if (io->i_errcnt >= 16) { 32515067Skarels upaddr->upof = UPOF_FMT22; 32615067Skarels upaddr->upcs1 = UP_RTC|UP_GO; 32735049Skarels upwaitdry(upaddr); 32815067Skarels } 32925443Skarels return (rv); 3309974Ssam } 3319974Ssam 33235049Skarels upwaitrdy(upaddr) 33335049Skarels register struct updevice *upaddr; 33435049Skarels { 33535049Skarels do { 33635049Skarels DELAY(25); 33735049Skarels } while ((upaddr->upcs1 & UP_RDY) == 0); 33835049Skarels } 33935049Skarels 34035049Skarels upwaitdry(upaddr) 34135049Skarels register struct updevice *upaddr; 34235049Skarels { 34335049Skarels while ((upaddr->upds&UPDS_DRY) == 0) 34435049Skarels DELAY(25); 34535049Skarels } 34635049Skarels 34732196Skarels #ifndef SMALL 3489974Ssam /* 34933647Sbostic * Correct an ECC error, and restart the i/o to complete the transfer (if 35033647Sbostic * necessary). This is quite complicated because the transfer may be going 35133647Sbostic * to an odd memory address base and/or across a page boundary. 3529974Ssam */ 35310023Ssam upecc(io, flag) 3549974Ssam register struct iob *io; 3559974Ssam int flag; 3569974Ssam { 35733533Sbostic register i, unit; 35833533Sbostic register struct up_softc *sc; 35933533Sbostic register struct updevice *up; 36033647Sbostic register struct disklabel *lp; 3619974Ssam caddr_t addr; 36210410Shelge int bn, twc, npf, mask, cn, tn, sn; 36310352Shelge daddr_t bbn; 3649974Ssam 3659974Ssam /* 36611143Ssam * Npf is the number of sectors transferred 36711143Ssam * before the sector containing the ECC error; 36811143Ssam * bn is the current block number. 3699974Ssam */ 37033533Sbostic unit = io->i_unit; 37133533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 37233647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 373*35522Sbostic up = (struct updevice *)ubamem(io->i_adapt, upstd[io->i_ctlr]); 37410352Shelge twc = up->upwc; 37511143Ssam npf = ((twc * sizeof(short)) + io->i_cc) / sectsiz; 37615067Skarels if (flag == ECC) 37715067Skarels npf--; 37825443Skarels if (sc->debug & UPF_ECCDEBUG) 37911386Ssam printf("npf=%d mask=0x%x ec1=%d wc=%d\n", 38011386Ssam npf, up->upec2, up->upec1, twc); 38111317Ssam bn = io->i_bn + npf; 38233647Sbostic cn = bn / lp->d_secpercyl; 38333647Sbostic sn = bn % lp->d_secpercyl; 38433647Sbostic tn = sn / lp->d_nsectors; 38533647Sbostic sn = sn % lp->d_nsectors; 38611143Ssam 3879974Ssam /* 38811143Ssam * ECC correction. 3899974Ssam */ 3909974Ssam if (flag == ECC) { 39125443Skarels int bit, o; 39211085Ssam 3939974Ssam mask = up->upec2; 39411365Ssam printf("up%d: soft ecc sn%d\n", unit, bn); 39525443Skarels for (i = mask, bit = 0; i; i >>= 1) 39625443Skarels if (i & 1) 39725443Skarels bit++; 39825443Skarels if (bit > sc->ecclim) { 39925443Skarels printf("%d-bit error\n", bit); 40025443Skarels return (1); 40125443Skarels } 4029974Ssam /* 40311317Ssam * Compute the byte and bit position of 40411317Ssam * the error. o is the byte offset in 40511317Ssam * the transfer at which the correction 40611317Ssam * applied. 4079974Ssam */ 4089974Ssam i = up->upec1 - 1; /* -1 makes 0 origin */ 40911386Ssam bit = i & 07; 41011386Ssam o = (i & ~07) >> 3; 4119974Ssam up->upcs1 = UP_TRE|UP_DCLR|UP_GO; 4129974Ssam /* 41311143Ssam * Correct while possible bits remain of mask. 41411143Ssam * Since mask contains 11 bits, we continue while 41511143Ssam * the bit offset is > -11. Also watch out for 41611143Ssam * end of this block and the end of the transfer. 4179974Ssam */ 41811317Ssam while (o < sectsiz && (npf*sectsiz)+o < io->i_cc && bit > -11) { 4199974Ssam /* 42011143Ssam * addr = 42111317Ssam * (base address of transfer) + 42211143Ssam * (# sectors transferred before the error) * 42311143Ssam * (sector size) + 42411317Ssam * (byte offset to incorrect data) 4259974Ssam */ 42611317Ssam addr = io->i_ma + (npf * sectsiz) + o; 42711317Ssam /* 42811317Ssam * No data transfer occurs with a write check, 42911317Ssam * so don't correct the resident copy of data. 43011317Ssam */ 43111365Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 43225443Skarels if (sc->debug & UPF_ECCDEBUG) 43311365Ssam printf("addr=0x%x old=0x%x ", addr, 43411365Ssam (*addr&0xff)); 43510352Shelge *addr ^= (mask << bit); 43625443Skarels if (sc->debug & UPF_ECCDEBUG) 43711365Ssam printf("new=0x%x\n", (*addr&0xff)); 43811365Ssam } 43911317Ssam o++, bit -= 8; 4409974Ssam } 44111085Ssam return (0); 44211085Ssam } 44311143Ssam 44411143Ssam /* 44511143Ssam * Bad sector forwarding. 44611143Ssam */ 44711085Ssam if (flag == BSE) { 4489974Ssam /* 44911143Ssam * If not in bad sector table, 45011143Ssam * indicate a hard error to caller. 4519974Ssam */ 45210352Shelge up->upcs1 = UP_TRE|UP_DCLR|UP_GO; 45333533Sbostic if ((bbn = isbad(&upbad[io->i_adapt][io->i_ctlr][unit], cn, tn, sn)) < 0) 45411085Ssam return (1); 45533647Sbostic bbn = (lp->d_ncylinders * lp->d_secpercyl) - 45633647Sbostic lp->d_nsectors - 1 - bbn; 45710352Shelge twc = up->upwc + sectsiz; 45811085Ssam up->upwc = - (sectsiz / sizeof (short)); 45925443Skarels if (sc->debug & UPF_BSEDEBUG) 46011365Ssam printf("revector sn %d to %d\n", sn, bbn); 4619974Ssam /* 46211143Ssam * Clear the drive & read the replacement 46311143Ssam * sector. If this is in the middle of a 46411143Ssam * transfer, then set up the controller 46511143Ssam * registers in a normal fashion. 46611143Ssam * The UNIBUS address need not be changed. 46711143Ssam */ 46835049Skarels upwaitrdy(up); 46933647Sbostic if (upstart(io, bbn, lp)) 47010352Shelge return (1); /* error */ 47110352Shelge io->i_errcnt = 0; /* success */ 47235049Skarels upwaitrdy(up); 47311386Ssam if ((up->upds & UPDS_ERR) || (up->upcs1 & UP_TRE)) { 47411386Ssam up->upwc = twc - sectsiz; 47510352Shelge return (1); 4769974Ssam } 4779974Ssam } 47810638Shelge if (twc) 4799974Ssam up->upwc = twc; 48010352Shelge return (0); 4819974Ssam } 48233533Sbostic #endif /* !SMALL */ 4839974Ssam 48433647Sbostic upstart(io, bn, lp) 48510023Ssam register struct iob *io; 48610023Ssam daddr_t bn; 48733647Sbostic register struct disklabel *lp; 4889974Ssam { 48933533Sbostic register struct updevice *upaddr; 49033533Sbostic register struct up_softc *sc; 4919974Ssam int sn, tn; 4929974Ssam 493*35522Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, upstd[io->i_ctlr]); 49433533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][io->i_unit]; 49533647Sbostic sn = bn % lp->d_secpercyl; 49633647Sbostic tn = sn / lp->d_nsectors; 49733647Sbostic sn = sn % lp->d_nsectors; 49833647Sbostic upaddr->updc = bn / lp->d_secpercyl; 4999974Ssam upaddr->upda = (tn << 8) + sn; 50010352Shelge switch (io->i_flgs & F_TYPEMASK) { 50110023Ssam 50210023Ssam case F_RDDATA: 50310023Ssam upaddr->upcs1 = UP_RCOM|UP_GO; 5049974Ssam break; 50510023Ssam 50610023Ssam case F_WRDATA: 50710023Ssam upaddr->upcs1 = UP_WCOM|UP_GO; 5089974Ssam break; 50910023Ssam 51032196Skarels #ifndef SMALL 51133533Sbostic case F_HDR|F_RDDATA: 51210023Ssam upaddr->upcs1 = UP_RHDR|UP_GO; 51310023Ssam break; 51410023Ssam 51510023Ssam case F_HDR|F_WRDATA: 51610023Ssam upaddr->upcs1 = UP_WHDR|UP_GO; 51710023Ssam break; 51810023Ssam 51910023Ssam case F_CHECK|F_WRDATA: 52010023Ssam case F_CHECK|F_RDDATA: 5219974Ssam upaddr->upcs1 = UP_WCDATA|UP_GO; 5229974Ssam break; 52310023Ssam 52410023Ssam case F_HCHECK|F_WRDATA: 52510023Ssam case F_HCHECK|F_RDDATA: 5269974Ssam upaddr->upcs1 = UP_WCHDR|UP_GO; 5279974Ssam break; 52832196Skarels #endif 52910023Ssam 5309974Ssam default: 53110023Ssam io->i_error = ECMD; 53210023Ssam io->i_flgs &= ~F_TYPEMASK; 53310023Ssam return (1); 5349974Ssam } 53510023Ssam return (0); 5369974Ssam } 5379974Ssam 53833533Sbostic #ifndef SMALL 53910023Ssam /*ARGSUSED*/ 54010023Ssam upioctl(io, cmd, arg) 54110023Ssam struct iob *io; 54210023Ssam int cmd; 54310023Ssam caddr_t arg; 54410023Ssam { 54533533Sbostic register struct up_softc *sc; 54610352Shelge 54733647Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][io->i_unit]; 54810352Shelge switch(cmd) { 54911365Ssam case SAIODEBUG: 55025443Skarels sc->debug = (int)arg; 55125443Skarels break; 55210352Shelge case SAIODEVDATA: 55333647Sbostic *(struct disklabel *)arg = 55433647Sbostic uplabel[io->i_adapt][io->i_ctlr][io->i_unit]; 55525443Skarels break; 55625443Skarels case SAIOGBADINFO: 55733647Sbostic *(struct dkbad *)arg = 55833647Sbostic upbad[io->i_adapt][io->i_ctlr][io->i_unit]; 55925443Skarels break; 56025443Skarels case SAIOECCLIM: 56125443Skarels sc->ecclim = (int)arg; 56225443Skarels break; 56325443Skarels case SAIORETRIES: 56425443Skarels sc->retries = (int)arg; 56525443Skarels break; 56625443Skarels default: 56725443Skarels return (ECMD); 56810352Shelge } 56925443Skarels return (0); 57010023Ssam } 57133533Sbostic #endif /* !SMALL */ 572