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*34520Skarels * @(#)up.c 7.6 (Berkeley) 05/27/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 */ 3633533Sbostic u_short ubastd[MAXCTLR] = { 0776700 }; 3733647Sbostic struct disklabel uplabel[MAXNUBA][MAXCTLR][MAXUNIT]; 3833647Sbostic 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; 7033647Sbostic register int unit; 7133647Sbostic struct disklabel *dlp, *lp; 72*34520Skarels int error = 0; 739974Ssam 7433533Sbostic if ((u_int)io->i_ctlr >= MAXCTLR) 7533533Sbostic return (ECTLR); 7633647Sbostic if ((u_int)io->i_part >= MAXUNIT) 7733533Sbostic return (EPART); 7833533Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, ubastd[io->i_ctlr]); 7933647Sbostic unit = io->i_unit; 8015067Skarels upaddr->upcs2 = unit % 8; 8133533Sbostic while ((upaddr->upcs1 & UP_DVA) == 0); 8233533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 8333647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 8425443Skarels if (sc->gottype == 0) { 8510023Ssam register int i; 8610023Ssam struct iob tio; 8710023Ssam 8833647Sbostic #ifndef SMALL 8925443Skarels sc->retries = RETRIES; 9025443Skarels sc->ecclim = 11; 9125443Skarels sc->debug = 0; 9233647Sbostic #endif 9333647Sbostic /* Read in the pack label. */ 9433647Sbostic lp->d_nsectors = 32; 9533647Sbostic lp->d_secpercyl = 19*32; 9633647Sbostic tio = *io; 9733647Sbostic tio.i_bn = LABELSECTOR; 9833647Sbostic tio.i_ma = lbuf; 9933647Sbostic tio.i_cc = SECTSIZ; 10033647Sbostic tio.i_flgs |= F_RDDATA; 10133647Sbostic if (upstrategy(&tio, READ) != SECTSIZ) 102*34520Skarels error = ERDLAB; 10333647Sbostic dlp = (struct disklabel *)(lbuf + LABELOFFSET); 104*34520Skarels if (error == 0 && (dlp->d_magic != DISKMAGIC || 105*34520Skarels dlp->d_magic2 != DISKMAGIC)) 106*34520Skarels error = EUNLAB; 107*34520Skarels if (error == 0) 108*34520Skarels *lp = *dlp; 109*34520Skarels else 11033647Sbostic #ifdef COMPAT_42 111*34520Skarels if (upmaptype(unit, upaddr, lp) == 0) 11233647Sbostic #endif 113*34520Skarels return (error); 11433647Sbostic 11532196Skarels #ifndef SMALL 11633647Sbostic /* Read in the bad sector table. */ 11733647Sbostic tio.i_bn = lp->d_secpercyl * lp->d_ncylinders - lp->d_nsectors; 11833647Sbostic tio.i_ma = (char *)&upbad[io->i_adapt][io->i_ctlr][io->i_unit]; 11933647Sbostic tio.i_cc = sizeof(struct dkbad); 12010023Ssam tio.i_flgs |= F_RDDATA; 12110023Ssam for (i = 0; i < 5; i++) { 12233647Sbostic if (upstrategy(&tio, READ) == sizeof(struct dkbad)) 12310023Ssam break; 1249974Ssam tio.i_bn += 2; 1259974Ssam } 1269974Ssam if (i == 5) { 12733647Sbostic printf("up: can't read bad sector table\n"); 12810352Shelge for (i = 0; i < MAXBADDESC; i++) { 12933533Sbostic upbad[tio.i_adapt][tio.i_ctlr][unit].bt_bad[i].bt_cyl = -1; 13033533Sbostic upbad[tio.i_adapt][tio.i_ctlr][unit].bt_bad[i].bt_trksec = -1; 1319974Ssam } 13233647Sbostic } 13332196Skarels #endif 13425443Skarels sc->gottype = 1; 1359974Ssam } 13633647Sbostic if (io->i_part >= lp->d_npartitions || 13733647Sbostic lp->d_partitions[io->i_part].p_size == 0) 13833647Sbostic return (EPART); 13933647Sbostic io->i_boff = lp->d_partitions[io->i_part].p_offset; 14010023Ssam io->i_flgs &= ~F_TYPEMASK; 14133408Skarels return (0); 1429974Ssam } 1439974Ssam 1449974Ssam upstrategy(io, func) 1459974Ssam register struct iob *io; 14633647Sbostic int func; 1479974Ssam { 14811317Ssam int cn, tn, sn, o; 14910352Shelge register unit = io->i_unit; 15033408Skarels register daddr_t bn; 1519974Ssam int recal, info, waitdry; 15233533Sbostic register struct updevice *upaddr; 15333647Sbostic register struct disklabel *lp; 15433533Sbostic struct up_softc *sc; 15533408Skarels int error, rv = io->i_cc; 15633408Skarels #ifndef SMALL 15733408Skarels int doprintf = 0; 15833408Skarels #endif 1599974Ssam 16033533Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, ubastd[io->i_ctlr]); 16133533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 16233647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 16310352Shelge sectsiz = SECTSIZ; 16411085Ssam if (io->i_flgs & (F_HDR|F_HCHECK)) 16510352Shelge sectsiz += HDRSIZ; 16611365Ssam upaddr->upcs2 = unit % 8; 1679974Ssam if ((upaddr->upds & UPDS_VV) == 0) { 1689974Ssam upaddr->upcs1 = UP_DCLR|UP_GO; 1699974Ssam upaddr->upcs1 = UP_PRESET|UP_GO; 1709974Ssam upaddr->upof = UPOF_FMT22; 1719974Ssam } 17225443Skarels if ((upaddr->upds & UPDS_DREADY) == 0) { 17325443Skarels printf("up%d not ready", unit); 17425443Skarels return (-1); 17525443Skarels } 1769974Ssam info = ubasetup(io, 1); 1779974Ssam upaddr->upwc = -io->i_cc / sizeof (short); 17811085Ssam recal = 0; 17911085Ssam io->i_errcnt = 0; 18011085Ssam 18110638Shelge restart: 18225443Skarels error = 0; 18311317Ssam o = io->i_cc + (upaddr->upwc * sizeof (short)); 18411317Ssam upaddr->upba = info + o; 18511317Ssam bn = io->i_bn + o / sectsiz; 18633408Skarels #ifndef SMALL 18725443Skarels if (doprintf && sc->debug & (UPF_ECCDEBUG|UPF_BSEDEBUG)) 18811386Ssam printf("wc=%d o=%d i_bn=%d bn=%d\n", 18911365Ssam upaddr->upwc, o, io->i_bn, bn); 19033408Skarels #endif 19110023Ssam while((upaddr->upds & UPDS_DRY) == 0) 19210023Ssam ; 19333647Sbostic if (upstart(io, bn, lp) != 0) { 19425443Skarels rv = -1; 19525443Skarels goto done; 19610352Shelge } 1979974Ssam do { 1989974Ssam DELAY(25); 1999974Ssam } while ((upaddr->upcs1 & UP_RDY) == 0); 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: 26525443Skarels if (error == 0) { 26625443Skarels error = EHER; 26725443Skarels if (upaddr->upcs2 & UPCS2_WCE) 26825443Skarels error = EWCK; 26925443Skarels } 27025443Skarels printf("up error: sn%d (cyl,trk,sec)=(%d,%d,%d) ", 27125443Skarels bn, cn, tn, sn); 27225443Skarels printf("cs2=%b er1=%b er2=%b\n", 27311085Ssam upaddr->upcs2, UPCS2_BITS, upaddr->uper1, 27411085Ssam UPER1_BITS, upaddr->uper2, UPER2_BITS); 2759974Ssam upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; 27610352Shelge io->i_errblk = bn; 27715067Skarels if (io->i_errcnt >= 16) { 27815067Skarels upaddr->upof = UPOF_FMT22; 27915067Skarels upaddr->upcs1 = UP_RTC|UP_GO; 28015067Skarels while ((upaddr->upds&UPDS_DRY) == 0) 28115067Skarels DELAY(25); 28215067Skarels } 28325443Skarels rv = -1; 28425443Skarels goto done; 28511085Ssam } 28611085Ssam /* 28733647Sbostic * Clear drive error and, every eight attempts, (starting with the 28833647Sbostic * fourth) recalibrate to clear the slate. 2899974Ssam */ 2909974Ssam upaddr->upcs1 = UP_TRE|UP_DCLR|UP_GO; 29110638Shelge if ((io->i_errcnt&07) == 4 ) { 2929974Ssam upaddr->upcs1 = UP_RECAL|UP_GO; 29315067Skarels while ((upaddr->upds&UPDS_DRY) == 0) 29415067Skarels DELAY(25); 2959974Ssam upaddr->updc = cn; 2969974Ssam upaddr->upcs1 = UP_SEEK|UP_GO; 29715067Skarels while ((upaddr->upds&UPDS_DRY) == 0) 29815067Skarels DELAY(25); 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; 30310638Shelge while ((upaddr->upds&UPDS_DRY) == 0) 30410638Shelge DELAY(25); 3059974Ssam } 30610638Shelge goto restart; 30711085Ssam 3089974Ssam success: 30911386Ssam #define rounddown(x, y) (((x) / (y)) * (y)) 31011386Ssam upaddr->upwc = rounddown(upaddr->upwc, sectsiz / sizeof (short)); 31111386Ssam if (upaddr->upwc) { 31233408Skarels #ifndef SMALL 31311317Ssam doprintf++; 31433408Skarels #endif 31510638Shelge goto restart; 31611317Ssam } 31715067Skarels done: 3189974Ssam ubafree(io, info); 31915067Skarels /* 32015067Skarels * If we were offset positioning, 32115067Skarels * return to centerline. 32215067Skarels */ 32315067Skarels if (io->i_errcnt >= 16) { 32415067Skarels upaddr->upof = UPOF_FMT22; 32515067Skarels upaddr->upcs1 = UP_RTC|UP_GO; 32615067Skarels while ((upaddr->upds&UPDS_DRY) == 0) 32715067Skarels DELAY(25); 32815067Skarels } 32925443Skarels return (rv); 3309974Ssam } 3319974Ssam 33232196Skarels #ifndef SMALL 3339974Ssam /* 33433647Sbostic * Correct an ECC error, and restart the i/o to complete the transfer (if 33533647Sbostic * necessary). This is quite complicated because the transfer may be going 33633647Sbostic * to an odd memory address base and/or across a page boundary. 3379974Ssam */ 33810023Ssam upecc(io, flag) 3399974Ssam register struct iob *io; 3409974Ssam int flag; 3419974Ssam { 34233533Sbostic register i, unit; 34333533Sbostic register struct up_softc *sc; 34433533Sbostic register struct updevice *up; 34533647Sbostic register struct disklabel *lp; 3469974Ssam caddr_t addr; 34710410Shelge int bn, twc, npf, mask, cn, tn, sn; 34810352Shelge daddr_t bbn; 3499974Ssam 3509974Ssam /* 35111143Ssam * Npf is the number of sectors transferred 35211143Ssam * before the sector containing the ECC error; 35311143Ssam * bn is the current block number. 3549974Ssam */ 35533533Sbostic unit = io->i_unit; 35633533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][unit]; 35733647Sbostic lp = &uplabel[io->i_adapt][io->i_ctlr][unit]; 35833533Sbostic up = (struct updevice *)ubamem(io->i_adapt, ubastd[io->i_ctlr]); 35910352Shelge twc = up->upwc; 36011143Ssam npf = ((twc * sizeof(short)) + io->i_cc) / sectsiz; 36115067Skarels if (flag == ECC) 36215067Skarels npf--; 36325443Skarels if (sc->debug & UPF_ECCDEBUG) 36411386Ssam printf("npf=%d mask=0x%x ec1=%d wc=%d\n", 36511386Ssam npf, up->upec2, up->upec1, twc); 36611317Ssam bn = io->i_bn + npf; 36733647Sbostic cn = bn / lp->d_secpercyl; 36833647Sbostic sn = bn % lp->d_secpercyl; 36933647Sbostic tn = sn / lp->d_nsectors; 37033647Sbostic sn = sn % lp->d_nsectors; 37111143Ssam 3729974Ssam /* 37311143Ssam * ECC correction. 3749974Ssam */ 3759974Ssam if (flag == ECC) { 37625443Skarels int bit, o; 37711085Ssam 3789974Ssam mask = up->upec2; 37911365Ssam printf("up%d: soft ecc sn%d\n", unit, bn); 38025443Skarels for (i = mask, bit = 0; i; i >>= 1) 38125443Skarels if (i & 1) 38225443Skarels bit++; 38325443Skarels if (bit > sc->ecclim) { 38425443Skarels printf("%d-bit error\n", bit); 38525443Skarels return (1); 38625443Skarels } 3879974Ssam /* 38811317Ssam * Compute the byte and bit position of 38911317Ssam * the error. o is the byte offset in 39011317Ssam * the transfer at which the correction 39111317Ssam * applied. 3929974Ssam */ 3939974Ssam i = up->upec1 - 1; /* -1 makes 0 origin */ 39411386Ssam bit = i & 07; 39511386Ssam o = (i & ~07) >> 3; 3969974Ssam up->upcs1 = UP_TRE|UP_DCLR|UP_GO; 3979974Ssam /* 39811143Ssam * Correct while possible bits remain of mask. 39911143Ssam * Since mask contains 11 bits, we continue while 40011143Ssam * the bit offset is > -11. Also watch out for 40111143Ssam * end of this block and the end of the transfer. 4029974Ssam */ 40311317Ssam while (o < sectsiz && (npf*sectsiz)+o < io->i_cc && bit > -11) { 4049974Ssam /* 40511143Ssam * addr = 40611317Ssam * (base address of transfer) + 40711143Ssam * (# sectors transferred before the error) * 40811143Ssam * (sector size) + 40911317Ssam * (byte offset to incorrect data) 4109974Ssam */ 41111317Ssam addr = io->i_ma + (npf * sectsiz) + o; 41211317Ssam /* 41311317Ssam * No data transfer occurs with a write check, 41411317Ssam * so don't correct the resident copy of data. 41511317Ssam */ 41611365Ssam if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) { 41725443Skarels if (sc->debug & UPF_ECCDEBUG) 41811365Ssam printf("addr=0x%x old=0x%x ", addr, 41911365Ssam (*addr&0xff)); 42010352Shelge *addr ^= (mask << bit); 42125443Skarels if (sc->debug & UPF_ECCDEBUG) 42211365Ssam printf("new=0x%x\n", (*addr&0xff)); 42311365Ssam } 42411317Ssam o++, bit -= 8; 4259974Ssam } 42611085Ssam return (0); 42711085Ssam } 42811143Ssam 42911143Ssam /* 43011143Ssam * Bad sector forwarding. 43111143Ssam */ 43211085Ssam if (flag == BSE) { 4339974Ssam /* 43411143Ssam * If not in bad sector table, 43511143Ssam * indicate a hard error to caller. 4369974Ssam */ 43710352Shelge up->upcs1 = UP_TRE|UP_DCLR|UP_GO; 43833533Sbostic if ((bbn = isbad(&upbad[io->i_adapt][io->i_ctlr][unit], cn, tn, sn)) < 0) 43911085Ssam return (1); 44033647Sbostic bbn = (lp->d_ncylinders * lp->d_secpercyl) - 44133647Sbostic lp->d_nsectors - 1 - bbn; 44210352Shelge twc = up->upwc + sectsiz; 44311085Ssam up->upwc = - (sectsiz / sizeof (short)); 44425443Skarels if (sc->debug & UPF_BSEDEBUG) 44511365Ssam printf("revector sn %d to %d\n", sn, bbn); 4469974Ssam /* 44711143Ssam * Clear the drive & read the replacement 44811143Ssam * sector. If this is in the middle of a 44911143Ssam * transfer, then set up the controller 45011143Ssam * registers in a normal fashion. 45111143Ssam * The UNIBUS address need not be changed. 45211143Ssam */ 45311386Ssam while ((up->upcs1 & UP_RDY) == 0) 4549974Ssam ; 45533647Sbostic if (upstart(io, bbn, lp)) 45610352Shelge return (1); /* error */ 45710352Shelge io->i_errcnt = 0; /* success */ 4589974Ssam do { 4599974Ssam DELAY(25); 46011386Ssam } while ((up->upcs1 & UP_RDY) == 0) ; 46111386Ssam if ((up->upds & UPDS_ERR) || (up->upcs1 & UP_TRE)) { 46211386Ssam up->upwc = twc - sectsiz; 46310352Shelge return (1); 4649974Ssam } 4659974Ssam } 46610638Shelge if (twc) 4679974Ssam up->upwc = twc; 46810352Shelge return (0); 4699974Ssam } 47033533Sbostic #endif /* !SMALL */ 4719974Ssam 47233647Sbostic upstart(io, bn, lp) 47310023Ssam register struct iob *io; 47410023Ssam daddr_t bn; 47533647Sbostic register struct disklabel *lp; 4769974Ssam { 47733533Sbostic register struct updevice *upaddr; 47833533Sbostic register struct up_softc *sc; 4799974Ssam int sn, tn; 4809974Ssam 48133533Sbostic upaddr = (struct updevice *)ubamem(io->i_adapt, ubastd[io->i_ctlr]); 48233533Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][io->i_unit]; 48333647Sbostic sn = bn % lp->d_secpercyl; 48433647Sbostic tn = sn / lp->d_nsectors; 48533647Sbostic sn = sn % lp->d_nsectors; 48633647Sbostic upaddr->updc = bn / lp->d_secpercyl; 4879974Ssam upaddr->upda = (tn << 8) + sn; 48810352Shelge switch (io->i_flgs & F_TYPEMASK) { 48910023Ssam 49010023Ssam case F_RDDATA: 49110023Ssam upaddr->upcs1 = UP_RCOM|UP_GO; 4929974Ssam break; 49310023Ssam 49410023Ssam case F_WRDATA: 49510023Ssam upaddr->upcs1 = UP_WCOM|UP_GO; 4969974Ssam break; 49710023Ssam 49832196Skarels #ifndef SMALL 49933533Sbostic case F_HDR|F_RDDATA: 50010023Ssam upaddr->upcs1 = UP_RHDR|UP_GO; 50110023Ssam break; 50210023Ssam 50310023Ssam case F_HDR|F_WRDATA: 50410023Ssam upaddr->upcs1 = UP_WHDR|UP_GO; 50510023Ssam break; 50610023Ssam 50710023Ssam case F_CHECK|F_WRDATA: 50810023Ssam case F_CHECK|F_RDDATA: 5099974Ssam upaddr->upcs1 = UP_WCDATA|UP_GO; 5109974Ssam break; 51110023Ssam 51210023Ssam case F_HCHECK|F_WRDATA: 51310023Ssam case F_HCHECK|F_RDDATA: 5149974Ssam upaddr->upcs1 = UP_WCHDR|UP_GO; 5159974Ssam break; 51632196Skarels #endif 51710023Ssam 5189974Ssam default: 51910023Ssam io->i_error = ECMD; 52010023Ssam io->i_flgs &= ~F_TYPEMASK; 52110023Ssam return (1); 5229974Ssam } 52310023Ssam return (0); 5249974Ssam } 5259974Ssam 52633533Sbostic #ifndef SMALL 52710023Ssam /*ARGSUSED*/ 52810023Ssam upioctl(io, cmd, arg) 52910023Ssam struct iob *io; 53010023Ssam int cmd; 53110023Ssam caddr_t arg; 53210023Ssam { 53333533Sbostic register struct up_softc *sc; 53410352Shelge 53533647Sbostic sc = &up_softc[io->i_adapt][io->i_ctlr][io->i_unit]; 53610352Shelge switch(cmd) { 53711365Ssam case SAIODEBUG: 53825443Skarels sc->debug = (int)arg; 53925443Skarels break; 54010352Shelge case SAIODEVDATA: 54133647Sbostic *(struct disklabel *)arg = 54233647Sbostic uplabel[io->i_adapt][io->i_ctlr][io->i_unit]; 54325443Skarels break; 54425443Skarels case SAIOGBADINFO: 54533647Sbostic *(struct dkbad *)arg = 54633647Sbostic upbad[io->i_adapt][io->i_ctlr][io->i_unit]; 54725443Skarels break; 54825443Skarels case SAIOECCLIM: 54925443Skarels sc->ecclim = (int)arg; 55025443Skarels break; 55125443Skarels case SAIORETRIES: 55225443Skarels sc->retries = (int)arg; 55325443Skarels break; 55425443Skarels default: 55525443Skarels return (ECMD); 55610352Shelge } 55725443Skarels return (0); 55810023Ssam } 55933533Sbostic #endif /* !SMALL */ 560