123248Smckusick /* 232196Skarels * Copyright (c) 1982 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*33647Sbostic * @(#)up.c 7.5 (Berkeley) 03/04/88 723248Smckusick */ 89974Ssam 910023Ssam /* 10*33647Sbostic * UNIBUS peripheral standalone driver with ECC correction and bad 11*33647Sbostic * block forwarding. Also supports header operation and write check 12*33647Sbostic * for data and/or header. 1310023Ssam */ 1432196Skarels #include "param.h" 1532196Skarels #include "inode.h" 1632196Skarels #include "fs.h" 1732196Skarels #include "dkbad.h" 18*33647Sbostic #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 34*33647Sbostic #define MAXUNIT 8 3533533Sbostic #define MAXCTLR 1 /* all addresses must be specified */ 3633533Sbostic u_short ubastd[MAXCTLR] = { 0776700 }; 37*33647Sbostic struct disklabel uplabel[MAXNUBA][MAXCTLR][MAXUNIT]; 38*33647Sbostic char lbuf[SECTSIZ]; 399974Ssam 4011143Ssam extern struct st upst[]; 4110023Ssam 4232196Skarels #ifndef SMALL 43*33647Sbostic struct dkbad upbad[MAXNUBA][MAXCTLR][MAXUNIT]; /* bad sector table */ 4432196Skarels #endif 45*33647Sbostic 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; 55*33647Sbostic } 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; 70*33647Sbostic register int unit; 71*33647Sbostic struct disklabel *dlp, *lp; 729974Ssam 7333533Sbostic if ((u_int)io->i_ctlr >= MAXCTLR) 7433533Sbostic return (ECTLR); 75*33647Sbostic if ((u_int)io->i_part >= MAXUNIT) 7633533Sbostic return (EPART); 7733533Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, ubastd[io->i_ctlr]); 78*33647Sbostic unit = io->i_unit; 7915067Skarels upaddr->upcs2 = unit % 8; 8033533Sbostic while ((upaddr->upcs1 & UP_DVA) == 0); 8133533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 82*33647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 8325443Skarels if (sc->gottype == 0) { 8410023Ssam register int i; 8510023Ssam struct iob tio; 8610023Ssam 87*33647Sbostic #ifndef SMALL 8825443Skarels sc->retries = RETRIES; 8925443Skarels sc->ecclim = 11; 9025443Skarels sc->debug = 0; 91*33647Sbostic #endif 92*33647Sbostic /* Read in the pack label. */ 93*33647Sbostic lp->d_nsectors = 32; 94*33647Sbostic lp->d_secpercyl = 19*32; 95*33647Sbostic tio = *io; 96*33647Sbostic tio.i_bn = LABELSECTOR; 97*33647Sbostic tio.i_ma = lbuf; 98*33647Sbostic tio.i_cc = SECTSIZ; 99*33647Sbostic tio.i_flgs |= F_RDDATA; 100*33647Sbostic if (upstrategy(&tio, READ) != SECTSIZ) 101*33647Sbostic return (ERDLAB); 102*33647Sbostic dlp = (struct disklabel *)(lbuf + LABELOFFSET); 103*33647Sbostic if (dlp->d_magic != DISKMAGIC || dlp->d_magic2 != DISKMAGIC) 104*33647Sbostic #ifdef COMPAT_42 105*33647Sbostic { 106*33647Sbostic printf("up%d: unlabeled\n", unit); 107*33647Sbostic if (!upmaptype(unit, upaddr, dlp)) { 108*33647Sbostic printf("up: unknown drive type\n"); 109*33647Sbostic return (ENXIO); 110*33647Sbostic } 11133533Sbostic } 112*33647Sbostic #else 113*33647Sbostic return (EUNLAB); 114*33647Sbostic #endif 115*33647Sbostic else 116*33647Sbostic *lp = *dlp; 117*33647Sbostic 11832196Skarels #ifndef SMALL 119*33647Sbostic /* Read in the bad sector table. */ 120*33647Sbostic tio.i_bn = lp->d_secpercyl * lp->d_ncylinders - lp->d_nsectors; 121*33647Sbostic tio.i_ma = (char *)&upbad[io->i_adapt][io->i_ctlr][io->i_unit]; 122*33647Sbostic tio.i_cc = sizeof(struct dkbad); 12310023Ssam tio.i_flgs |= F_RDDATA; 12410023Ssam for (i = 0; i < 5; i++) { 125*33647Sbostic if (upstrategy(&tio, READ) == sizeof(struct dkbad)) 12610023Ssam break; 1279974Ssam tio.i_bn += 2; 1289974Ssam } 1299974Ssam if (i == 5) { 130*33647Sbostic printf("up: can't read bad sector table\n"); 13110352Shelge for (i = 0; i < MAXBADDESC; i++) { 13233533Sbostic upbad[tio.i_adapt][tio.i_ctlr][unit].bt_bad[i].bt_cyl = -1; 13333533Sbostic upbad[tio.i_adapt][tio.i_ctlr][unit].bt_bad[i].bt_trksec = -1; 1349974Ssam } 135*33647Sbostic } 13632196Skarels #endif 13725443Skarels sc->gottype = 1; 1389974Ssam } 139*33647Sbostic if (io->i_part >= lp->d_npartitions || 140*33647Sbostic lp->d_partitions[io->i_part].p_size == 0) 141*33647Sbostic return (EPART); 142*33647Sbostic 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; 149*33647Sbostic 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; 156*33647Sbostic 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 16333533Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, ubastd[io->i_ctlr]); 16433533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 165*33647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 16610352Shelge sectsiz = SECTSIZ; 16711085Ssam if (io->i_flgs & (F_HDR|F_HCHECK)) 16810352Shelge sectsiz += HDRSIZ; 16911365Ssam upaddr->upcs2 = unit % 8; 1709974Ssam if ((upaddr->upds & UPDS_VV) == 0) { 1719974Ssam upaddr->upcs1 = UP_DCLR|UP_GO; 1729974Ssam upaddr->upcs1 = UP_PRESET|UP_GO; 1739974Ssam upaddr->upof = UPOF_FMT22; 1749974Ssam } 17525443Skarels if ((upaddr->upds & UPDS_DREADY) == 0) { 17625443Skarels printf("up%d not ready", unit); 17725443Skarels return (-1); 17825443Skarels } 1799974Ssam info = ubasetup(io, 1); 1809974Ssam upaddr->upwc = -io->i_cc / sizeof (short); 18111085Ssam recal = 0; 18211085Ssam io->i_errcnt = 0; 18311085Ssam 18410638Shelge restart: 18525443Skarels error = 0; 18611317Ssam o = io->i_cc + (upaddr->upwc * sizeof (short)); 18711317Ssam upaddr->upba = info + o; 18811317Ssam bn = io->i_bn + o / sectsiz; 18933408Skarels #ifndef SMALL 19025443Skarels if (doprintf && sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) 19111386Ssam printf("wc=%d o=%d i_bn=%d bn=%d\n", 19211365Ssam upaddr->upwc, o, io->i_bn, bn); 19333408Skarels #endif 19410023Ssam while((upaddr->upds & UPDS_DRY) == 0) 19510023Ssam ; 196*33647Sbostic if (upstart(io, bn, lp) != 0) { 19725443Skarels rv = -1; 19825443Skarels goto done; 19910352Shelge } 2009974Ssam do { 2019974Ssam DELAY(25); 2029974Ssam } while ((upaddr->upcs1 & UP_RDY) == 0); 20311085Ssam /* 20411085Ssam * If transfer has completed, free UNIBUS 20511085Ssam * resources and return transfer size. 20611085Ssam */ 20715067Skarels if ((upaddr->upds&UPDS_ERR) == 0 && (upaddr->upcs1&UP_TRE) == 0) 20815067Skarels goto done; 20925443Skarels bn = io->i_bn + 21025443Skarels (io->i_cc + upaddr->upwc * sizeof (short)) / sectsiz; 21125443Skarels if (upaddr->uper1 & (UPER1_DCK|UPER1_ECH)) 21225443Skarels bn--; 213*33647Sbostic cn = bn / lp->d_secpercyl; 214*33647Sbostic sn = bn % lp->d_secpercyl; 215*33647Sbostic tn = sn / lp->d_nsectors; 216*33647Sbostic sn = sn % lp->d_nsectors; 21732196Skarels #ifndef SMALL 21825443Skarels if (sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) { 21925443Skarels printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ", 22025443Skarels bn, cn, tn, sn); 22111386Ssam printf("cs2=%b er1=%b er2=%b wc=%d\n", 22211365Ssam upaddr->upcs2, UPCS2_BITS, upaddr->uper1, 22311386Ssam UPER1_BITS, upaddr->uper2, UPER2_BITS, upaddr->upwc); 22411365Ssam } 22532196Skarels #endif 2269974Ssam waitdry = 0; 22711386Ssam while ((upaddr->upds&UPDS_DRY) == 0 && ++waitdry < sectsiz) 22810023Ssam DELAY(5); 22932196Skarels #ifndef SMALL 23011085Ssam if (upaddr->uper1&UPER1_WLE) { 23111085Ssam /* 23211085Ssam * Give up on write locked devices immediately. 23311085Ssam */ 23411085Ssam printf("up%d: write locked\n", unit); 23525443Skarels rv = -1; 23625443Skarels goto done; 23711085Ssam } 23825443Skarels if (upaddr->uper2 & UPER2_BSE) { 23925443Skarels if ((io->i_flgs&F_NBSF) == 0 && upecc(io, BSE) == 0) 24025443Skarels goto success; 24125443Skarels error = EBSE; 24225443Skarels goto hard; 24325443Skarels } 24425443Skarels /* 24525443Skarels * ECC error. If a soft error, correct it; 24625443Skarels * if correction is too large, no more retries. 24725443Skarels */ 24825443Skarels if ((upaddr->uper1 & (UPER1_DCK|UPER1_ECH|UPER1_HCRC)) == UPER1_DCK) { 24925443Skarels if (upecc(io, ECC) == 0) 25025443Skarels goto success; 25125443Skarels error = EECC; 25225443Skarels goto hard; 25325443Skarels } 25425443Skarels /* 255*33647Sbostic * If the error is a header CRC, check if a replacement sector 256*33647Sbostic * exists in the bad sector table. 25725443Skarels */ 25825443Skarels if ((upaddr->uper1&UPER1_HCRC) && (io->i_flgs&F_NBSF) == 0 && 25925443Skarels upecc(io, BSE) == 0) 26025443Skarels goto success; 26132196Skarels #endif 26225443Skarels if (++io->i_errcnt > sc->retries) { 2639974Ssam /* 2649974Ssam * After 28 retries (16 without offset, and 2659974Ssam * 12 with offset positioning) give up. 2669974Ssam */ 26710352Shelge hard: 26825443Skarels if (error == 0) { 26925443Skarels error = EHER; 27025443Skarels if (upaddr->upcs2 & UPCS2_WCE) 27125443Skarels error = EWCK; 27225443Skarels } 27325443Skarels printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ", 27425443Skarels bn, cn, tn, sn); 27525443Skarels printf("cs2=%b er1=%b er2=%b\n", 27611085Ssam upaddr->upcs2, UPCS2_BITS, upaddr->uper1, 27711085Ssam UPER1_BITS, upaddr->uper2, UPER2_BITS); 2789974Ssam upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; 27910352Shelge io->i_errblk = bn; 28015067Skarels if (io->i_errcnt >= 16) { 28115067Skarels upaddr->upof = UPOF_FMT22; 28215067Skarels upaddr->upcs1 = UP_RTC|UP_GO; 28315067Skarels while ((upaddr->upds&UPDS_DRY) == 0) 28415067Skarels DELAY(25); 28515067Skarels } 28625443Skarels rv = -1; 28725443Skarels goto done; 28811085Ssam } 28911085Ssam /* 290*33647Sbostic * Clear drive error and, every eight attempts, (starting with the 291*33647Sbostic * fourth) recalibrate to clear the slate. 2929974Ssam */ 2939974Ssam upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; 29410638Shelge if ((io->i_errcnt&07) == 4 ) { 2959974Ssam upaddr->upcs1 = UP_RECAL|UP_GO; 29615067Skarels while ((upaddr->upds&UPDS_DRY) == 0) 29715067Skarels DELAY(25); 2989974Ssam upaddr->updc = cn; 2999974Ssam upaddr->upcs1 = UP_SEEK|UP_GO; 30015067Skarels while ((upaddr->upds&UPDS_DRY) == 0) 30115067Skarels DELAY(25); 30215067Skarels } 30315067Skarels if (io->i_errcnt >= 16 && (func & READ)) { 3049974Ssam upaddr->upof = up_offset[io->i_errcnt & 017] | UPOF_FMT22; 3059974Ssam upaddr->upcs1 = UP_OFFSET|UP_GO; 30610638Shelge while ((upaddr->upds&UPDS_DRY) == 0) 30710638Shelge DELAY(25); 3089974Ssam } 30910638Shelge goto restart; 31011085Ssam 3119974Ssam success: 31211386Ssam #define rounddown(x, y) (((x) / (y)) * (y)) 31311386Ssam upaddr->upwc = rounddown(upaddr->upwc, sectsiz / sizeof (short)); 31411386Ssam if (upaddr->upwc) { 31533408Skarels #ifndef SMALL 31611317Ssam doprintf++; 31733408Skarels #endif 31810638Shelge goto restart; 31911317Ssam } 32015067Skarels done: 3219974Ssam ubafree(io, info); 32215067Skarels /* 32315067Skarels * If we were offset positioning, 32415067Skarels * return to centerline. 32515067Skarels */ 32615067Skarels if (io->i_errcnt >= 16) { 32715067Skarels upaddr->upof = UPOF_FMT22; 32815067Skarels upaddr->upcs1 = UP_RTC|UP_GO; 32915067Skarels while ((upaddr->upds&UPDS_DRY) == 0) 33015067Skarels DELAY(25); 33115067Skarels } 33225443Skarels return (rv); 3339974Ssam } 3349974Ssam 33532196Skarels #ifndef SMALL 3369974Ssam /* 337*33647Sbostic * Correct an ECC error, and restart the i/o to complete the transfer (if 338*33647Sbostic * necessary). This is quite complicated because the transfer may be going 339*33647Sbostic * to an odd memory address base and/or across a page boundary. 3409974Ssam */ 34110023Ssam upecc(io, flag) 3429974Ssam register struct iob *io; 3439974Ssam int flag; 3449974Ssam { 34533533Sbostic register i, unit; 34633533Sbostic register struct up_softc *sc; 34733533Sbostic register struct updevice *up; 348*33647Sbostic register struct disklabel *lp; 3499974Ssam caddr_t addr; 35010410Shelge int bn, twc, npf, mask, cn, tn, sn; 35110352Shelge daddr_t bbn; 3529974Ssam 3539974Ssam /* 35411143Ssam * Npf is the number of sectors transferred 35511143Ssam * before the sector containing the ECC error; 35611143Ssam * bn is the current block number. 3579974Ssam */ 35833533Sbostic unit = io->i_unit; 35933533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 360*33647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 36133533Sbostic up = (struct updevice *)ubamem(io->i_adapt, ubastd[io->i_ctlr]); 36210352Shelge twc = up->upwc; 36311143Ssam npf = ((twc * sizeof(short)) + io->i_cc) / sectsiz; 36415067Skarels if (flag == ECC) 36515067Skarels npf--; 36625443Skarels if (sc->debug & UPF_ECCDEBUG) 36711386Ssam printf("npf=%d mask=0x%x ec1=%d wc=%d\n", 36811386Ssam npf, up->upec2, up->upec1, twc); 36911317Ssam bn = io->i_bn + npf; 370*33647Sbostic cn = bn / lp->d_secpercyl; 371*33647Sbostic sn = bn % lp->d_secpercyl; 372*33647Sbostic tn = sn / lp->d_nsectors; 373*33647Sbostic sn = sn % lp->d_nsectors; 37411143Ssam 3759974Ssam /* 37611143Ssam * ECC correction. 3779974Ssam */ 3789974Ssam if (flag == ECC) { 37925443Skarels int bit, o; 38011085Ssam 3819974Ssam mask = up->upec2; 38211365Ssam printf("up%d: soft ecc sn%d\n", unit, bn); 38325443Skarels for (i = mask, bit = 0; i; i >>= 1) 38425443Skarels if (i & 1) 38525443Skarels bit++; 38625443Skarels if (bit > sc->ecclim) { 38725443Skarels printf("%d-bit error\n", bit); 38825443Skarels return (1); 38925443Skarels } 3909974Ssam /* 39111317Ssam * Compute the byte and bit position of 39211317Ssam * the error. o is the byte offset in 39311317Ssam * the transfer at which the correction 39411317Ssam * applied. 3959974Ssam */ 3969974Ssam i = up->upec1 - 1; /* -1 makes 0 origin */ 39711386Ssam bit = i & 07; 39811386Ssam o = (i & ~07) >> 3; 3999974Ssam up->upcs1 = UP_TRE|UP_DCLR|UP_GO; 4009974Ssam /* 40111143Ssam * Correct while possible bits remain of mask. 40211143Ssam * Since mask contains 11 bits, we continue while 40311143Ssam * the bit offset is > -11. Also watch out for 40411143Ssam * end of this block and the end of the transfer. 4059974Ssam */ 40611317Ssam while (o < sectsiz && (npf*sectsiz)+o < io->i_cc && bit > -11) { 4079974Ssam /* 40811143Ssam * addr = 40911317Ssam * (base address of transfer) + 41011143Ssam * (# sectors transferred before the error) * 41111143Ssam * (sector size) + 41211317Ssam * (byte offset to incorrect data) 4139974Ssam */ 41411317Ssam addr = io->i_ma + (npf * sectsiz) + o; 41511317Ssam /* 41611317Ssam * No data transfer occurs with a write check, 41711317Ssam * so don't correct the resident copy of data. 41811317Ssam */ 41911365Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 42025443Skarels if (sc->debug & UPF_ECCDEBUG) 42111365Ssam printf("addr=0x%x old=0x%x ", addr, 42211365Ssam (*addr&0xff)); 42310352Shelge *addr ^= (mask << bit); 42425443Skarels if (sc->debug & UPF_ECCDEBUG) 42511365Ssam printf("new=0x%x\n", (*addr&0xff)); 42611365Ssam } 42711317Ssam o++, bit -= 8; 4289974Ssam } 42911085Ssam return (0); 43011085Ssam } 43111143Ssam 43211143Ssam /* 43311143Ssam * Bad sector forwarding. 43411143Ssam */ 43511085Ssam if (flag == BSE) { 4369974Ssam /* 43711143Ssam * If not in bad sector table, 43811143Ssam * indicate a hard error to caller. 4399974Ssam */ 44010352Shelge up->upcs1 = UP_TRE|UP_DCLR|UP_GO; 44133533Sbostic if ((bbn = isbad(&upbad[io->i_adapt][io->i_ctlr][unit], cn, tn, sn)) < 0) 44211085Ssam return (1); 443*33647Sbostic bbn = (lp->d_ncylinders * lp->d_secpercyl) - 444*33647Sbostic lp->d_nsectors - 1 - bbn; 44510352Shelge twc = up->upwc + sectsiz; 44611085Ssam up->upwc = - (sectsiz / sizeof (short)); 44725443Skarels if (sc->debug & UPF_BSEDEBUG) 44811365Ssam printf("revector sn %d to %d\n", sn, bbn); 4499974Ssam /* 45011143Ssam * Clear the drive & read the replacement 45111143Ssam * sector. If this is in the middle of a 45211143Ssam * transfer, then set up the controller 45311143Ssam * registers in a normal fashion. 45411143Ssam * The UNIBUS address need not be changed. 45511143Ssam */ 45611386Ssam while ((up->upcs1 & UP_RDY) == 0) 4579974Ssam ; 458*33647Sbostic if (upstart(io, bbn, lp)) 45910352Shelge return (1); /* error */ 46010352Shelge io->i_errcnt = 0; /* success */ 4619974Ssam do { 4629974Ssam DELAY(25); 46311386Ssam } while ((up->upcs1 & UP_RDY) == 0) ; 46411386Ssam if ((up->upds & UPDS_ERR) || (up->upcs1 & UP_TRE)) { 46511386Ssam up->upwc = twc - sectsiz; 46610352Shelge return (1); 4679974Ssam } 4689974Ssam } 46910638Shelge if (twc) 4709974Ssam up->upwc = twc; 47110352Shelge return (0); 4729974Ssam } 47333533Sbostic #endif /* !SMALL */ 4749974Ssam 475*33647Sbostic upstart(io, bn, lp) 47610023Ssam register struct iob *io; 47710023Ssam daddr_t bn; 478*33647Sbostic register struct disklabel *lp; 4799974Ssam { 48033533Sbostic register struct updevice *upaddr; 48133533Sbostic register struct up_softc *sc; 4829974Ssam int sn, tn; 4839974Ssam 48433533Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, ubastd[io->i_ctlr]); 48533533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][io->i_unit]; 486*33647Sbostic sn = bn % lp->d_secpercyl; 487*33647Sbostic tn = sn / lp->d_nsectors; 488*33647Sbostic sn = sn % lp->d_nsectors; 489*33647Sbostic upaddr->updc = bn / lp->d_secpercyl; 4909974Ssam upaddr->upda = (tn << 8) + sn; 49110352Shelge switch (io->i_flgs & F_TYPEMASK) { 49210023Ssam 49310023Ssam case F_RDDATA: 49410023Ssam upaddr->upcs1 = UP_RCOM|UP_GO; 4959974Ssam break; 49610023Ssam 49710023Ssam case F_WRDATA: 49810023Ssam upaddr->upcs1 = UP_WCOM|UP_GO; 4999974Ssam break; 50010023Ssam 50132196Skarels #ifndef SMALL 50233533Sbostic case F_HDR|F_RDDATA: 50310023Ssam upaddr->upcs1 = UP_RHDR|UP_GO; 50410023Ssam break; 50510023Ssam 50610023Ssam case F_HDR|F_WRDATA: 50710023Ssam upaddr->upcs1 = UP_WHDR|UP_GO; 50810023Ssam break; 50910023Ssam 51010023Ssam case F_CHECK|F_WRDATA: 51110023Ssam case F_CHECK|F_RDDATA: 5129974Ssam upaddr->upcs1 = UP_WCDATA|UP_GO; 5139974Ssam break; 51410023Ssam 51510023Ssam case F_HCHECK|F_WRDATA: 51610023Ssam case F_HCHECK|F_RDDATA: 5179974Ssam upaddr->upcs1 = UP_WCHDR|UP_GO; 5189974Ssam break; 51932196Skarels #endif 52010023Ssam 5219974Ssam default: 52210023Ssam io->i_error = ECMD; 52310023Ssam io->i_flgs &= ~F_TYPEMASK; 52410023Ssam return (1); 5259974Ssam } 52610023Ssam return (0); 5279974Ssam } 5289974Ssam 52933533Sbostic #ifndef SMALL 53010023Ssam /*ARGSUSED*/ 53110023Ssam upioctl(io, cmd, arg) 53210023Ssam struct iob *io; 53310023Ssam int cmd; 53410023Ssam caddr_t arg; 53510023Ssam { 53633533Sbostic register struct up_softc *sc; 53710352Shelge 538*33647Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][io->i_unit]; 53910352Shelge switch(cmd) { 54011365Ssam case SAIODEBUG: 54125443Skarels sc->debug = (int)arg; 54225443Skarels break; 54310352Shelge case SAIODEVDATA: 544*33647Sbostic *(struct disklabel *)arg = 545*33647Sbostic uplabel[io->i_adapt][io->i_ctlr][io->i_unit]; 54625443Skarels break; 54725443Skarels case SAIOGBADINFO: 548*33647Sbostic *(struct dkbad *)arg = 549*33647Sbostic upbad[io->i_adapt][io->i_ctlr][io->i_unit]; 55025443Skarels break; 55125443Skarels case SAIOECCLIM: 55225443Skarels sc->ecclim = (int)arg; 55325443Skarels break; 55425443Skarels case SAIORETRIES: 55525443Skarels sc->retries = (int)arg; 55625443Skarels break; 55725443Skarels default: 55825443Skarels return (ECMD); 55910352Shelge } 56025443Skarels return (0); 56110023Ssam } 56233533Sbostic #endif /* !SMALL */ 563