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*45803Sbostic * @(#)up.c 7.10 (Berkeley) 12/16/90 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 */ 14*45803Sbostic #include "sys/param.h" 15*45803Sbostic #include "sys/dkbad.h" 16*45803Sbostic #include "sys/disklabel.h" 179974Ssam 18*45803Sbostic #include "../include/pte.h" 199974Ssam 20*45803Sbostic #include "../uba/upreg.h" 21*45803Sbostic #include "../uba/ubareg.h" 2233408Skarels 23*45803Sbostic #include "stand/saio.h" 249974Ssam #include "savax.h" 259974Ssam 2625443Skarels #define RETRIES 27 2725443Skarels 2810352Shelge #define MAXBADDESC 126 /* max number of bad sectors recorded */ 2910352Shelge #define SECTSIZ 512 /* sector size in bytes */ 3010352Shelge #define HDRSIZ 4 /* number of bytes in sector header */ 3111365Ssam 3233647Sbostic #define MAXUNIT 8 3333533Sbostic #define MAXCTLR 1 /* all addresses must be specified */ 3435522Sbostic static u_short upstd[MAXCTLR] = { 0776700 }; 3535522Sbostic static struct disklabel uplabel[MAXNUBA][MAXCTLR][MAXUNIT]; 3635522Sbostic static char lbuf[SECTSIZ]; 379974Ssam 3811143Ssam extern struct st upst[]; 3910023Ssam 4032196Skarels #ifndef SMALL 4133647Sbostic struct dkbad upbad[MAXNUBA][MAXCTLR][MAXUNIT]; /* bad sector table */ 4232196Skarels #endif 4333647Sbostic int sectsiz; /* real sector size */ 4411365Ssam 4525443Skarels struct up_softc { 4625443Skarels char gottype; 4725443Skarels char type; 4825443Skarels char debug; 4925443Skarels # define UPF_BSEDEBUG 01 /* debugging bad sector forwarding */ 5025443Skarels # define UPF_ECCDEBUG 02 /* debugging ecc correction */ 5125443Skarels int retries; 5225443Skarels int ecclim; 5333647Sbostic } up_softc[MAXNUBA][MAXCTLR][MAXUNIT]; 5425443Skarels 559974Ssam u_char up_offset[16] = { 569974Ssam UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400, 579974Ssam UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800, 589974Ssam UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200, 599974Ssam 0, 0, 0, 0 609974Ssam }; 619974Ssam 629974Ssam upopen(io) 639974Ssam register struct iob *io; 649974Ssam { 6510023Ssam register struct updevice *upaddr; 6633533Sbostic register struct up_softc *sc; 6711118Ssam register struct st *st; 6835049Skarels register struct disklabel *lp; 6935049Skarels struct disklabel *dlp; 7033647Sbostic register int unit; 7135049Skarels int error = 0, uba, ctlr; 729974Ssam 7335049Skarels if ((u_int)(uba = io->i_adapt) >= nuba) 7435049Skarels return (EADAPT); 7535049Skarels if ((u_int)(ctlr = io->i_ctlr) >= MAXCTLR) 7633533Sbostic return (ECTLR); 7733647Sbostic unit = io->i_unit; 7835049Skarels if ((u_int)unit >= MAXUNIT) 7935049Skarels return (EUNIT); 8035522Sbostic upaddr = (struct updevice *)ubamem(uba, upstd[ctlr]); 8135049Skarels upaddr->upcs2 = unit; 8233533Sbostic while ((upaddr->upcs1 & UP_DVA) == 0); 8335049Skarels sc = &up_softc[uba][ctlr][unit]; 8435049Skarels lp = &uplabel[uba][ctlr][unit]; 8525443Skarels if (sc->gottype == 0) { 8610023Ssam register int i; 8710023Ssam struct iob tio; 8810023Ssam 8933647Sbostic #ifndef SMALL 9025443Skarels sc->retries = RETRIES; 9125443Skarels sc->ecclim = 11; 9225443Skarels sc->debug = 0; 9333647Sbostic #endif 9433647Sbostic /* Read in the pack label. */ 9533647Sbostic lp->d_nsectors = 32; 9633647Sbostic lp->d_secpercyl = 19*32; 9733647Sbostic tio = *io; 9833647Sbostic tio.i_bn = LABELSECTOR; 9933647Sbostic tio.i_ma = lbuf; 10033647Sbostic tio.i_cc = SECTSIZ; 10133647Sbostic tio.i_flgs |= F_RDDATA; 10233647Sbostic if (upstrategy(&tio, READ) != SECTSIZ) 10334520Skarels error = ERDLAB; 10433647Sbostic dlp = (struct disklabel *)(lbuf + LABELOFFSET); 10534520Skarels if (error == 0 && (dlp->d_magic != DISKMAGIC || 10634520Skarels dlp->d_magic2 != DISKMAGIC)) 10734520Skarels error = EUNLAB; 10834520Skarels if (error == 0) 10934520Skarels *lp = *dlp; 11034520Skarels else 11133647Sbostic #ifdef COMPAT_42 11234520Skarels if (upmaptype(unit, upaddr, lp) == 0) 11333647Sbostic #endif 11434520Skarels return (error); 11533647Sbostic 11632196Skarels #ifndef SMALL 11733647Sbostic /* Read in the bad sector table. */ 11833647Sbostic tio.i_bn = lp->d_secpercyl * lp->d_ncylinders - lp->d_nsectors; 11935049Skarels tio.i_ma = (char *)&upbad[uba][ctlr][unit]; 12033647Sbostic tio.i_cc = sizeof(struct dkbad); 12110023Ssam tio.i_flgs |= F_RDDATA; 12210023Ssam for (i = 0; i < 5; i++) { 12333647Sbostic if (upstrategy(&tio, READ) == sizeof(struct dkbad)) 12410023Ssam break; 1259974Ssam tio.i_bn += 2; 1269974Ssam } 1279974Ssam if (i == 5) { 12833647Sbostic printf("up: can't read bad sector table\n"); 12910352Shelge for (i = 0; i < MAXBADDESC; i++) { 13035049Skarels upbad[uba][ctlr][unit].bt_bad[i].bt_cyl = -1; 13135049Skarels upbad[uba][ctlr][unit].bt_bad[i].bt_trksec = -1; 1329974Ssam } 13333647Sbostic } 13432196Skarels #endif 13525443Skarels sc->gottype = 1; 1369974Ssam } 13733647Sbostic if (io->i_part >= lp->d_npartitions || 13833647Sbostic lp->d_partitions[io->i_part].p_size == 0) 13935049Skarels return (EPART); 14033647Sbostic io->i_boff = lp->d_partitions[io->i_part].p_offset; 14110023Ssam io->i_flgs &= ~F_TYPEMASK; 14233408Skarels return (0); 1439974Ssam } 1449974Ssam 1459974Ssam upstrategy(io, func) 1469974Ssam register struct iob *io; 14733647Sbostic int func; 1489974Ssam { 14911317Ssam int cn, tn, sn, o; 15010352Shelge register unit = io->i_unit; 15133408Skarels register daddr_t bn; 1529974Ssam int recal, info, waitdry; 15333533Sbostic register struct updevice *upaddr; 15433647Sbostic register struct disklabel *lp; 15533533Sbostic struct up_softc *sc; 15633408Skarels int error, rv = io->i_cc; 15733408Skarels #ifndef SMALL 15833408Skarels int doprintf = 0; 15933408Skarels #endif 1609974Ssam 16135522Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, upstd[io->i_ctlr]); 16233533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 16333647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 16410352Shelge sectsiz = SECTSIZ; 16535049Skarels #ifndef SMALL 16611085Ssam if (io->i_flgs & (F_HDR|F_HCHECK)) 16710352Shelge sectsiz += HDRSIZ; 16835049Skarels #endif 16935049Skarels upaddr->upcs2 = unit; 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) { 17635049Skarels printf("up%d not ready\n", 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: 18511317Ssam o = io->i_cc + (upaddr->upwc * sizeof (short)); 18611317Ssam upaddr->upba = info + o; 18711317Ssam bn = io->i_bn + o / sectsiz; 18833408Skarels #ifndef SMALL 18935049Skarels error = 0; 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 19435049Skarels upwaitdry(upaddr); 19533647Sbostic if (upstart(io, bn, lp) != 0) { 19625443Skarels rv = -1; 19725443Skarels goto done; 19810352Shelge } 19935049Skarels upwaitrdy(upaddr); 20011085Ssam /* 20111085Ssam * If transfer has completed, free UNIBUS 20211085Ssam * resources and return transfer size. 20311085Ssam */ 20415067Skarels if ((upaddr->upds&UPDS_ERR) == 0 && (upaddr->upcs1&UP_TRE) == 0) 20515067Skarels goto done; 20625443Skarels bn = io->i_bn + 20725443Skarels (io->i_cc + upaddr->upwc * sizeof (short)) / sectsiz; 20825443Skarels if (upaddr->uper1 & (UPER1_DCK|UPER1_ECH)) 20925443Skarels bn--; 21033647Sbostic cn = bn / lp->d_secpercyl; 21133647Sbostic sn = bn % lp->d_secpercyl; 21233647Sbostic tn = sn / lp->d_nsectors; 21333647Sbostic sn = sn % lp->d_nsectors; 21432196Skarels #ifndef SMALL 21525443Skarels if (sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) { 21625443Skarels printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ", 21725443Skarels bn, cn, tn, sn); 21811386Ssam printf("cs2=%b er1=%b er2=%b wc=%d\n", 21911365Ssam upaddr->upcs2, UPCS2_BITS, upaddr->uper1, 22011386Ssam UPER1_BITS, upaddr->uper2, UPER2_BITS, upaddr->upwc); 22111365Ssam } 22232196Skarels #endif 2239974Ssam waitdry = 0; 22411386Ssam while ((upaddr->upds&UPDS_DRY) == 0 && ++waitdry < sectsiz) 22510023Ssam DELAY(5); 22632196Skarels #ifndef SMALL 22711085Ssam if (upaddr->uper1&UPER1_WLE) { 22811085Ssam /* 22911085Ssam * Give up on write locked devices immediately. 23011085Ssam */ 23111085Ssam printf("up%d: write locked\n", unit); 23225443Skarels rv = -1; 23325443Skarels goto done; 23411085Ssam } 23525443Skarels if (upaddr->uper2 & UPER2_BSE) { 23625443Skarels if ((io->i_flgs&F_NBSF) == 0 && upecc(io, BSE) == 0) 23725443Skarels goto success; 23825443Skarels error = EBSE; 23925443Skarels goto hard; 24025443Skarels } 24125443Skarels /* 24225443Skarels * ECC error. If a soft error, correct it; 24325443Skarels * if correction is too large, no more retries. 24425443Skarels */ 24525443Skarels if ((upaddr->uper1 & (UPER1_DCK|UPER1_ECH|UPER1_HCRC)) == UPER1_DCK) { 24625443Skarels if (upecc(io, ECC) == 0) 24725443Skarels goto success; 24825443Skarels error = EECC; 24925443Skarels goto hard; 25025443Skarels } 25125443Skarels /* 25233647Sbostic * If the error is a header CRC, check if a replacement sector 25333647Sbostic * exists in the bad sector table. 25425443Skarels */ 25525443Skarels if ((upaddr->uper1&UPER1_HCRC) && (io->i_flgs&F_NBSF) == 0 && 25625443Skarels upecc(io, BSE) == 0) 25725443Skarels goto success; 25832196Skarels #endif 25925443Skarels if (++io->i_errcnt > sc->retries) { 2609974Ssam /* 2619974Ssam * After 28 retries (16 without offset, and 2629974Ssam * 12 with offset positioning) give up. 2639974Ssam */ 26410352Shelge hard: 26535049Skarels #ifndef SMALL 26625443Skarels if (error == 0) { 26725443Skarels error = EHER; 26825443Skarels if (upaddr->upcs2 & UPCS2_WCE) 26925443Skarels error = EWCK; 27025443Skarels } 27135049Skarels io->i_error = error; 27235049Skarels #endif 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; 28335049Skarels upwaitdry(upaddr); 28415067Skarels } 28525443Skarels rv = -1; 28625443Skarels goto done; 28711085Ssam } 28811085Ssam /* 28933647Sbostic * Clear drive error and, every eight attempts, (starting with the 29033647Sbostic * fourth) recalibrate to clear the slate. 2919974Ssam */ 2929974Ssam upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; 29310638Shelge if ((io->i_errcnt&07) == 4 ) { 2949974Ssam upaddr->upcs1 = UP_RECAL|UP_GO; 29535049Skarels upwaitdry(upaddr); 2969974Ssam upaddr->updc = cn; 2979974Ssam upaddr->upcs1 = UP_SEEK|UP_GO; 29835049Skarels upwaitdry(upaddr); 29915067Skarels } 30015067Skarels if (io->i_errcnt >= 16 && (func & READ)) { 3019974Ssam upaddr->upof = up_offset[io->i_errcnt & 017] | UPOF_FMT22; 3029974Ssam upaddr->upcs1 = UP_OFFSET|UP_GO; 30335049Skarels upwaitdry(upaddr); 3049974Ssam } 30510638Shelge goto restart; 30611085Ssam 3079974Ssam success: 30811386Ssam #define rounddown(x, y) (((x) / (y)) * (y)) 30911386Ssam upaddr->upwc = rounddown(upaddr->upwc, sectsiz / sizeof (short)); 31011386Ssam if (upaddr->upwc) { 31133408Skarels #ifndef SMALL 31211317Ssam doprintf++; 31333408Skarels #endif 31410638Shelge goto restart; 31511317Ssam } 31615067Skarels done: 3179974Ssam ubafree(io, info); 31815067Skarels /* 31915067Skarels * If we were offset positioning, 32015067Skarels * return to centerline. 32115067Skarels */ 32215067Skarels if (io->i_errcnt >= 16) { 32315067Skarels upaddr->upof = UPOF_FMT22; 32415067Skarels upaddr->upcs1 = UP_RTC|UP_GO; 32535049Skarels upwaitdry(upaddr); 32615067Skarels } 32725443Skarels return (rv); 3289974Ssam } 3299974Ssam 33035049Skarels upwaitrdy(upaddr) 33135049Skarels register struct updevice *upaddr; 33235049Skarels { 33335049Skarels do { 33435049Skarels DELAY(25); 33535049Skarels } while ((upaddr->upcs1 & UP_RDY) == 0); 33635049Skarels } 33735049Skarels 33835049Skarels upwaitdry(upaddr) 33935049Skarels register struct updevice *upaddr; 34035049Skarels { 34135049Skarels while ((upaddr->upds&UPDS_DRY) == 0) 34235049Skarels DELAY(25); 34335049Skarels } 34435049Skarels 34532196Skarels #ifndef SMALL 3469974Ssam /* 34733647Sbostic * Correct an ECC error, and restart the i/o to complete the transfer (if 34833647Sbostic * necessary). This is quite complicated because the transfer may be going 34933647Sbostic * to an odd memory address base and/or across a page boundary. 3509974Ssam */ 35110023Ssam upecc(io, flag) 3529974Ssam register struct iob *io; 3539974Ssam int flag; 3549974Ssam { 35533533Sbostic register i, unit; 35633533Sbostic register struct up_softc *sc; 35733533Sbostic register struct updevice *up; 35833647Sbostic register struct disklabel *lp; 3599974Ssam caddr_t addr; 36010410Shelge int bn, twc, npf, mask, cn, tn, sn; 36110352Shelge daddr_t bbn; 3629974Ssam 3639974Ssam /* 36411143Ssam * Npf is the number of sectors transferred 36511143Ssam * before the sector containing the ECC error; 36611143Ssam * bn is the current block number. 3679974Ssam */ 36833533Sbostic unit = io->i_unit; 36933533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 37033647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 37135522Sbostic up = (struct updevice *)ubamem(io->i_adapt, upstd[io->i_ctlr]); 37210352Shelge twc = up->upwc; 37311143Ssam npf = ((twc * sizeof(short)) + io->i_cc) / sectsiz; 37415067Skarels if (flag == ECC) 37515067Skarels npf--; 37625443Skarels if (sc->debug & UPF_ECCDEBUG) 37711386Ssam printf("npf=%d mask=0x%x ec1=%d wc=%d\n", 37811386Ssam npf, up->upec2, up->upec1, twc); 37911317Ssam bn = io->i_bn + npf; 38033647Sbostic cn = bn / lp->d_secpercyl; 38133647Sbostic sn = bn % lp->d_secpercyl; 38233647Sbostic tn = sn / lp->d_nsectors; 38333647Sbostic sn = sn % lp->d_nsectors; 38411143Ssam 3859974Ssam /* 38611143Ssam * ECC correction. 3879974Ssam */ 3889974Ssam if (flag == ECC) { 38925443Skarels int bit, o; 39011085Ssam 3919974Ssam mask = up->upec2; 39211365Ssam printf("up%d: soft ecc sn%d\n", unit, bn); 39325443Skarels for (i = mask, bit = 0; i; i >>= 1) 39425443Skarels if (i & 1) 39525443Skarels bit++; 39625443Skarels if (bit > sc->ecclim) { 39725443Skarels printf("%d-bit error\n", bit); 39825443Skarels return (1); 39925443Skarels } 4009974Ssam /* 40111317Ssam * Compute the byte and bit position of 40211317Ssam * the error. o is the byte offset in 40311317Ssam * the transfer at which the correction 40411317Ssam * applied. 4059974Ssam */ 4069974Ssam i = up->upec1 - 1; /* -1 makes 0 origin */ 40711386Ssam bit = i & 07; 40811386Ssam o = (i & ~07) >> 3; 4099974Ssam up->upcs1 = UP_TRE|UP_DCLR|UP_GO; 4109974Ssam /* 41111143Ssam * Correct while possible bits remain of mask. 41211143Ssam * Since mask contains 11 bits, we continue while 41311143Ssam * the bit offset is > -11. Also watch out for 41411143Ssam * end of this block and the end of the transfer. 4159974Ssam */ 41611317Ssam while (o < sectsiz && (npf*sectsiz)+o < io->i_cc && bit > -11) { 4179974Ssam /* 41811143Ssam * addr = 41911317Ssam * (base address of transfer) + 42011143Ssam * (# sectors transferred before the error) * 42111143Ssam * (sector size) + 42211317Ssam * (byte offset to incorrect data) 4239974Ssam */ 42411317Ssam addr = io->i_ma + (npf * sectsiz) + o; 42511317Ssam /* 42611317Ssam * No data transfer occurs with a write check, 42711317Ssam * so don't correct the resident copy of data. 42811317Ssam */ 42911365Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 43025443Skarels if (sc->debug & UPF_ECCDEBUG) 43111365Ssam printf("addr=0x%x old=0x%x ", addr, 43211365Ssam (*addr&0xff)); 43310352Shelge *addr ^= (mask << bit); 43425443Skarels if (sc->debug & UPF_ECCDEBUG) 43511365Ssam printf("new=0x%x\n", (*addr&0xff)); 43611365Ssam } 43711317Ssam o++, bit -= 8; 4389974Ssam } 43911085Ssam return (0); 44011085Ssam } 44111143Ssam 44211143Ssam /* 44311143Ssam * Bad sector forwarding. 44411143Ssam */ 44511085Ssam if (flag == BSE) { 4469974Ssam /* 44711143Ssam * If not in bad sector table, 44811143Ssam * indicate a hard error to caller. 4499974Ssam */ 45010352Shelge up->upcs1 = UP_TRE|UP_DCLR|UP_GO; 45133533Sbostic if ((bbn = isbad(&upbad[io->i_adapt][io->i_ctlr][unit], cn, tn, sn)) < 0) 45211085Ssam return (1); 45333647Sbostic bbn = (lp->d_ncylinders * lp->d_secpercyl) - 45433647Sbostic lp->d_nsectors - 1 - bbn; 45510352Shelge twc = up->upwc + sectsiz; 45611085Ssam up->upwc = - (sectsiz / sizeof (short)); 45725443Skarels if (sc->debug & UPF_BSEDEBUG) 45811365Ssam printf("revector sn %d to %d\n", sn, bbn); 4599974Ssam /* 46011143Ssam * Clear the drive & read the replacement 46111143Ssam * sector. If this is in the middle of a 46211143Ssam * transfer, then set up the controller 46311143Ssam * registers in a normal fashion. 46411143Ssam * The UNIBUS address need not be changed. 46511143Ssam */ 46635049Skarels upwaitrdy(up); 46733647Sbostic if (upstart(io, bbn, lp)) 46810352Shelge return (1); /* error */ 46910352Shelge io->i_errcnt = 0; /* success */ 47035049Skarels upwaitrdy(up); 47111386Ssam if ((up->upds & UPDS_ERR) || (up->upcs1 & UP_TRE)) { 47211386Ssam up->upwc = twc - sectsiz; 47310352Shelge return (1); 4749974Ssam } 4759974Ssam } 47610638Shelge if (twc) 4779974Ssam up->upwc = twc; 47810352Shelge return (0); 4799974Ssam } 48033533Sbostic #endif /* !SMALL */ 4819974Ssam 48233647Sbostic upstart(io, bn, lp) 48310023Ssam register struct iob *io; 48410023Ssam daddr_t bn; 48533647Sbostic register struct disklabel *lp; 4869974Ssam { 48733533Sbostic register struct updevice *upaddr; 48833533Sbostic register struct up_softc *sc; 4899974Ssam int sn, tn; 4909974Ssam 49135522Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, upstd[io->i_ctlr]); 49233533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][io->i_unit]; 49333647Sbostic sn = bn % lp->d_secpercyl; 49433647Sbostic tn = sn / lp->d_nsectors; 49533647Sbostic sn = sn % lp->d_nsectors; 49633647Sbostic upaddr->updc = bn / lp->d_secpercyl; 4979974Ssam upaddr->upda = (tn << 8) + sn; 49810352Shelge switch (io->i_flgs & F_TYPEMASK) { 49910023Ssam 50010023Ssam case F_RDDATA: 50110023Ssam upaddr->upcs1 = UP_RCOM|UP_GO; 5029974Ssam break; 50310023Ssam 50410023Ssam case F_WRDATA: 50510023Ssam upaddr->upcs1 = UP_WCOM|UP_GO; 5069974Ssam break; 50710023Ssam 50832196Skarels #ifndef SMALL 50933533Sbostic case F_HDR|F_RDDATA: 51010023Ssam upaddr->upcs1 = UP_RHDR|UP_GO; 51110023Ssam break; 51210023Ssam 51310023Ssam case F_HDR|F_WRDATA: 51410023Ssam upaddr->upcs1 = UP_WHDR|UP_GO; 51510023Ssam break; 51610023Ssam 51710023Ssam case F_CHECK|F_WRDATA: 51810023Ssam case F_CHECK|F_RDDATA: 5199974Ssam upaddr->upcs1 = UP_WCDATA|UP_GO; 5209974Ssam break; 52110023Ssam 52210023Ssam case F_HCHECK|F_WRDATA: 52310023Ssam case F_HCHECK|F_RDDATA: 5249974Ssam upaddr->upcs1 = UP_WCHDR|UP_GO; 5259974Ssam break; 52632196Skarels #endif 52710023Ssam 5289974Ssam default: 52910023Ssam io->i_error = ECMD; 53010023Ssam io->i_flgs &= ~F_TYPEMASK; 53110023Ssam return (1); 5329974Ssam } 53310023Ssam return (0); 5349974Ssam } 5359974Ssam 53633533Sbostic #ifndef SMALL 53710023Ssam /*ARGSUSED*/ 53810023Ssam upioctl(io, cmd, arg) 53910023Ssam struct iob *io; 54010023Ssam int cmd; 54110023Ssam caddr_t arg; 54210023Ssam { 54333533Sbostic register struct up_softc *sc; 54410352Shelge 54533647Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][io->i_unit]; 54610352Shelge switch(cmd) { 54711365Ssam case SAIODEBUG: 54825443Skarels sc->debug = (int)arg; 54925443Skarels break; 55010352Shelge case SAIODEVDATA: 55133647Sbostic *(struct disklabel *)arg = 55233647Sbostic uplabel[io->i_adapt][io->i_ctlr][io->i_unit]; 55325443Skarels break; 55425443Skarels case SAIOGBADINFO: 55533647Sbostic *(struct dkbad *)arg = 55633647Sbostic upbad[io->i_adapt][io->i_ctlr][io->i_unit]; 55725443Skarels break; 55825443Skarels case SAIOECCLIM: 55925443Skarels sc->ecclim = (int)arg; 56025443Skarels break; 56125443Skarels case SAIORETRIES: 56225443Skarels sc->retries = (int)arg; 56325443Skarels break; 56425443Skarels default: 56525443Skarels return (ECMD); 56610352Shelge } 56725443Skarels return (0); 56810023Ssam } 56933533Sbostic #endif /* !SMALL */ 570