1*52130Smckusick /* 2*52130Smckusick * Copyright (c) 1992 Regents of the University of California. 3*52130Smckusick * All rights reserved. 4*52130Smckusick * 5*52130Smckusick * This code is derived from software contributed to Berkeley by 6*52130Smckusick * Ralph Campbell. 7*52130Smckusick * 8*52130Smckusick * %sccs.include.redist.c% 9*52130Smckusick * 10*52130Smckusick * @(#)tz.c 7.1 (Berkeley) 01/07/92 11*52130Smckusick * 12*52130Smckusick * from: $Header: /sprite/src/kernel/dev/RCS/devSCSITape.c, 13*52130Smckusick * v 8.14 89/07/31 17:26:13 mendel Exp $ SPRITE (Berkeley) 14*52130Smckusick */ 15*52130Smckusick 16*52130Smckusick /* 17*52130Smckusick * SCSI CCS (Command Command Set) tape driver. 18*52130Smckusick */ 19*52130Smckusick #include "tz.h" 20*52130Smckusick #if NTZ > 0 21*52130Smckusick 22*52130Smckusick #include "param.h" 23*52130Smckusick #include "systm.h" 24*52130Smckusick #include "buf.h" 25*52130Smckusick #include "errno.h" 26*52130Smckusick #include "file.h" 27*52130Smckusick #include "ioctl.h" 28*52130Smckusick #include "mtio.h" 29*52130Smckusick #include "syslog.h" 30*52130Smckusick 31*52130Smckusick #include "device.h" 32*52130Smckusick #include "scsi.h" 33*52130Smckusick 34*52130Smckusick int tzprobe(); 35*52130Smckusick void tzstart(), tzdone(); 36*52130Smckusick 37*52130Smckusick struct driver tzdriver = { 38*52130Smckusick "tz", tzprobe, tzstart, tzdone, 39*52130Smckusick }; 40*52130Smckusick 41*52130Smckusick struct tz_softc { 42*52130Smckusick struct scsi_device *sc_sd; /* physical unit info */ 43*52130Smckusick int sc_flags; /* see below */ 44*52130Smckusick struct buf sc_tab; /* queue of pending operations */ 45*52130Smckusick struct buf sc_buf; /* buf for doing I/O */ 46*52130Smckusick struct buf sc_errbuf; /* buf for doing REQUEST_SENSE */ 47*52130Smckusick struct ScsiCmd sc_cmd; /* command for controller */ 48*52130Smckusick ScsiGroup0Cmd sc_rwcmd; /* SCSI cmd for read/write */ 49*52130Smckusick struct scsi_fmt_cdb sc_cdb; /* SCSI cmd if not read/write */ 50*52130Smckusick struct scsi_fmt_sense sc_sense; /* sense data from last cmd */ 51*52130Smckusick } tz_softc[NTZ]; 52*52130Smckusick 53*52130Smckusick /* sc_flags values */ 54*52130Smckusick #define TZF_ALIVE 0x01 /* drive found and ready */ 55*52130Smckusick #define TZF_SENSEINPROGRESS 0x02 /* REQUEST_SENSE command in progress */ 56*52130Smckusick #define TZF_ALTCMD 0x04 /* alternate command in progress */ 57*52130Smckusick #define TZF_WRITTEN 0x08 /* tape has been written to */ 58*52130Smckusick #define TZF_OPEN 0x10 /* device is open */ 59*52130Smckusick #define TZF_WAIT 0x20 /* waiting for sc_tab to drain */ 60*52130Smckusick 61*52130Smckusick /* bits in minor device */ 62*52130Smckusick #define tzunit(x) (minor(x) >> 1) /* tz%d unit number */ 63*52130Smckusick #define TZ_NOREWIND 0x1 /* don't rewind on close */ 64*52130Smckusick 65*52130Smckusick #define INF (daddr_t)1000000L /* a block number that won't exist */ 66*52130Smckusick 67*52130Smckusick #ifdef DEBUG 68*52130Smckusick int tzdebug = 1; 69*52130Smckusick #endif 70*52130Smckusick 71*52130Smckusick /* 72*52130Smckusick * Test to see if device is present. 73*52130Smckusick * Return true if found and initialized ok. 74*52130Smckusick */ 75*52130Smckusick tzprobe(sd) 76*52130Smckusick struct scsi_device *sd; 77*52130Smckusick { 78*52130Smckusick register struct tz_softc *sc = &tz_softc[sd->sd_unit]; 79*52130Smckusick register int i; 80*52130Smckusick ScsiInquiryData inqbuf; 81*52130Smckusick ScsiClass7Sense *sp; 82*52130Smckusick 83*52130Smckusick printf("tzprobe()\n"); /* XXX */ 84*52130Smckusick /* init some parameters that don't change */ 85*52130Smckusick sc->sc_sd = sd; 86*52130Smckusick sc->sc_cmd.sd = sd; 87*52130Smckusick sc->sc_cmd.unit = sd->sd_unit; 88*52130Smckusick sc->sc_rwcmd.unitNumber = sd->sd_slave; 89*52130Smckusick /* sc->sc_rwcmd.highAddr = 1; /* count in blocks */ 90*52130Smckusick 91*52130Smckusick /* try to find out what type of device this is */ 92*52130Smckusick sc->sc_flags = TZF_ALTCMD; /* force use of sc_cdb */ 93*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 94*52130Smckusick scsiGroup0Cmd(SCSI_INQUIRY, sd->sd_slave, 0, sizeof(inqbuf), 95*52130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 96*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_READ; 97*52130Smckusick sc->sc_buf.b_bcount = sizeof(inqbuf); 98*52130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)&inqbuf; 99*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 100*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 101*52130Smckusick tzstart(sd->sd_unit); 102*52130Smckusick if (biowait(&sc->sc_buf) || 103*52130Smckusick (i = sizeof(inqbuf) - sc->sc_buf.b_resid) < 5) 104*52130Smckusick goto bad; 105*52130Smckusick if (inqbuf.type != SCSI_TAPE_TYPE) 106*52130Smckusick goto bad; 107*52130Smckusick 108*52130Smckusick /* check for device ready to clear UNIT_ATTN */ 109*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 110*52130Smckusick scsiGroup0Cmd(SCSI_TEST_UNIT_READY, sd->sd_slave, 0, 0, 111*52130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 112*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_READ; 113*52130Smckusick sc->sc_buf.b_bcount = 0; 114*52130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)0; 115*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 116*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 117*52130Smckusick tzstart(sd->sd_unit); 118*52130Smckusick (void) biowait(&sc->sc_buf); 119*52130Smckusick 120*52130Smckusick sc->sc_flags = TZF_ALIVE; 121*52130Smckusick sc->sc_buf.b_flags = 0; 122*52130Smckusick printf("tz%d at %s%d drive %d slave %d\n", sd->sd_unit, 123*52130Smckusick sd->sd_cdriver->d_name, sd->sd_ctlr, sd->sd_drive, 124*52130Smckusick sd->sd_slave); 125*52130Smckusick return (1); 126*52130Smckusick 127*52130Smckusick bad: 128*52130Smckusick /* doesn't exist or not a CCS device */ 129*52130Smckusick sc->sc_flags = 0; 130*52130Smckusick sc->sc_buf.b_flags = 0; 131*52130Smckusick return (0); 132*52130Smckusick } 133*52130Smckusick 134*52130Smckusick /* 135*52130Smckusick * Perform a special tape command on a SCSI Tape drive. 136*52130Smckusick */ 137*52130Smckusick tzcommand(dev, command, code, count) 138*52130Smckusick dev_t dev; 139*52130Smckusick int command; 140*52130Smckusick int code; 141*52130Smckusick int count; 142*52130Smckusick { 143*52130Smckusick register struct tz_softc *sc = &tz_softc[tzunit(dev)]; 144*52130Smckusick int s, error; 145*52130Smckusick 146*52130Smckusick s = splbio(); 147*52130Smckusick while (sc->sc_tab.b_actf) { 148*52130Smckusick sc->sc_flags |= TZF_WAIT; 149*52130Smckusick sleep(&sc->sc_flags, PZERO); 150*52130Smckusick } 151*52130Smckusick sc->sc_flags |= TZF_ALTCMD; /* force use of sc_cdb */ 152*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 153*52130Smckusick scsiGroup0Cmd(command, sc->sc_sd->sd_slave, 154*52130Smckusick (code << 16) | ((count >> 8) & 0xFFFF), count & 0xFF, 155*52130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 156*52130Smckusick sc->sc_buf.b_flags = B_BUSY | B_READ; 157*52130Smckusick sc->sc_buf.b_bcount = 0; 158*52130Smckusick sc->sc_buf.b_un.b_addr = (caddr_t)0; 159*52130Smckusick sc->sc_buf.av_forw = (struct buf *)0; 160*52130Smckusick sc->sc_tab.b_actf = sc->sc_tab.b_actl = &sc->sc_buf; 161*52130Smckusick tzstart(sc->sc_sd->sd_unit); 162*52130Smckusick error = biowait(&sc->sc_buf); 163*52130Smckusick sc->sc_flags &= ~TZF_ALTCMD; /* force use of sc_cdb */ 164*52130Smckusick sc->sc_buf.b_flags = 0; 165*52130Smckusick splx(s); 166*52130Smckusick return (error); 167*52130Smckusick } 168*52130Smckusick 169*52130Smckusick void 170*52130Smckusick tzstart(unit) 171*52130Smckusick int unit; 172*52130Smckusick { 173*52130Smckusick register struct tz_softc *sc = &tz_softc[unit]; 174*52130Smckusick register struct buf *bp = sc->sc_tab.b_actf; 175*52130Smckusick register int n; 176*52130Smckusick extern int sii_debug; /* XXX */ 177*52130Smckusick 178*52130Smckusick sc->sc_cmd.buf = bp->b_un.b_addr; 179*52130Smckusick sc->sc_cmd.buflen = bp->b_bcount; 180*52130Smckusick 181*52130Smckusick if (sc->sc_flags & (TZF_SENSEINPROGRESS | TZF_ALTCMD)) { 182*52130Smckusick sc->sc_cmd.dataToDevice = !(bp->b_flags & B_READ); 183*52130Smckusick sc->sc_cmd.cmd = sc->sc_cdb.cdb; 184*52130Smckusick sc->sc_cmd.cmdlen = sc->sc_cdb.len; 185*52130Smckusick } else { 186*52130Smckusick if (bp->b_flags & B_READ) { 187*52130Smckusick sc->sc_cmd.dataToDevice = 0; 188*52130Smckusick sc->sc_rwcmd.command = SCSI_READ; 189*52130Smckusick } else { 190*52130Smckusick sc->sc_cmd.dataToDevice = 1; 191*52130Smckusick sc->sc_rwcmd.command = SCSI_WRITE; 192*52130Smckusick } 193*52130Smckusick sc->sc_cmd.cmd = (u_char *)&sc->sc_rwcmd; 194*52130Smckusick sc->sc_cmd.cmdlen = sizeof(sc->sc_rwcmd); 195*52130Smckusick n = howmany(bp->b_bcount, 512); 196*52130Smckusick sc->sc_rwcmd.midAddr = n >> 16; 197*52130Smckusick sc->sc_rwcmd.lowAddr = n >> 8; 198*52130Smckusick sc->sc_rwcmd.blockCount = n; 199*52130Smckusick if ((bp->b_bcount & (512 - 1)) != 0) 200*52130Smckusick printf("tz%d: partial block xfer -- %x bytes\n", 201*52130Smckusick unit, bp->b_bcount); 202*52130Smckusick } 203*52130Smckusick 204*52130Smckusick printf("tzstart(%d) flags %x, addr %x sz %d\n", unit, 205*52130Smckusick sc->sc_flags, sc->sc_cmd.buf, sc->sc_cmd.buflen); /* XXX */ 206*52130Smckusick /* tell controller to start this command */ 207*52130Smckusick if (sc->sc_cmd.cmd[0] == SCSI_READ) 208*52130Smckusick sii_debug = 5; /* XXX */ 209*52130Smckusick (*sc->sc_sd->sd_cdriver->d_start)(&sc->sc_cmd); 210*52130Smckusick } 211*52130Smckusick 212*52130Smckusick /* 213*52130Smckusick * This is called by the controller driver when the command is done. 214*52130Smckusick */ 215*52130Smckusick void 216*52130Smckusick tzdone(unit, error, resid, status) 217*52130Smckusick int unit; 218*52130Smckusick int error; /* error number from errno.h */ 219*52130Smckusick int resid; /* amount not transfered */ 220*52130Smckusick int status; /* SCSI status byte */ 221*52130Smckusick { 222*52130Smckusick register struct tz_softc *sc = &tz_softc[unit]; 223*52130Smckusick register struct buf *bp = sc->sc_tab.b_actf; 224*52130Smckusick extern int cold; 225*52130Smckusick extern int sii_debug; /* XXX */ 226*52130Smckusick 227*52130Smckusick printf("tzdone(%d, %d, %d, %x) %x flags %x\n", unit, error, resid, 228*52130Smckusick status, sc, sc->sc_flags); /* XXX */ 229*52130Smckusick if (bp == NULL) { 230*52130Smckusick printf("tz%d: bp == NULL\n", unit); 231*52130Smckusick return; 232*52130Smckusick } 233*52130Smckusick if (sc->sc_flags & TZF_SENSEINPROGRESS) { 234*52130Smckusick sc->sc_flags &= ~TZF_SENSEINPROGRESS; 235*52130Smckusick sc->sc_tab.b_actf = bp = bp->b_actf; /* remove sc_errbuf */ 236*52130Smckusick if (bp == 0) { 237*52130Smckusick sii_DumpLog(); 238*52130Smckusick panic("tzdone"); /* XXX */ 239*52130Smckusick } 240*52130Smckusick 241*52130Smckusick if (error || (status & SCSI_STATUS_CHECKCOND)) { 242*52130Smckusick #ifdef DEBUG 243*52130Smckusick if (tzdebug) 244*52130Smckusick printf("tz%d: error reading sense data: error %d scsi status 0x%x\n", 245*52130Smckusick unit, error, status); 246*52130Smckusick #endif 247*52130Smckusick /* 248*52130Smckusick * We got an error during the REQUEST_SENSE, 249*52130Smckusick * fill in no sense for data. 250*52130Smckusick */ 251*52130Smckusick sc->sc_sense.sense[0] = 0x70; 252*52130Smckusick sc->sc_sense.sense[2] = SCSI_CLASS7_NO_SENSE; 253*52130Smckusick } else if (!cold 254*52130Smckusick #ifdef DEBUG 255*52130Smckusick || tzdebug 256*52130Smckusick #endif 257*52130Smckusick ) { 258*52130Smckusick printf("tz%d: ", unit); 259*52130Smckusick scsiPrintSense((ScsiClass7Sense *)sc->sc_sense.sense, 260*52130Smckusick sizeof(sc->sc_sense.sense) - resid); 261*52130Smckusick } 262*52130Smckusick } else if (error || (status & SCSI_STATUS_CHECKCOND)) { 263*52130Smckusick #ifdef DEBUG 264*52130Smckusick if (tzdebug) 265*52130Smckusick printf("tz%d: error %d scsi status 0x%x\n", 266*52130Smckusick unit, error, status); 267*52130Smckusick #endif 268*52130Smckusick /* save error info */ 269*52130Smckusick sc->sc_sense.status = status; 270*52130Smckusick bp->b_flags |= B_ERROR; 271*52130Smckusick bp->b_error = error; 272*52130Smckusick bp->b_resid = resid; 273*52130Smckusick 274*52130Smckusick if (status & SCSI_STATUS_CHECKCOND) { 275*52130Smckusick /* 276*52130Smckusick * Start a REQUEST_SENSE command. 277*52130Smckusick * Since we are called at interrupt time, we can't 278*52130Smckusick * wait for the command to finish; that's why we use 279*52130Smckusick * the sc_flags field. 280*52130Smckusick */ 281*52130Smckusick sc->sc_flags |= TZF_SENSEINPROGRESS; 282*52130Smckusick sc->sc_cdb.len = sizeof(ScsiGroup0Cmd); 283*52130Smckusick scsiGroup0Cmd(SCSI_REQUEST_SENSE, sc->sc_sd->sd_slave, 284*52130Smckusick 0, sizeof(sc->sc_sense.sense), 285*52130Smckusick (ScsiGroup0Cmd *)sc->sc_cdb.cdb); 286*52130Smckusick sc->sc_errbuf.b_flags = B_BUSY | B_READ; 287*52130Smckusick sc->sc_errbuf.b_bcount = sizeof(sc->sc_sense.sense); 288*52130Smckusick sc->sc_errbuf.b_un.b_addr = (caddr_t)sc->sc_sense.sense; 289*52130Smckusick sc->sc_errbuf.av_forw = bp; 290*52130Smckusick sc->sc_tab.b_actf = &sc->sc_errbuf; 291*52130Smckusick tzstart(unit); 292*52130Smckusick return; 293*52130Smckusick } 294*52130Smckusick } else { 295*52130Smckusick sc->sc_sense.status = status; 296*52130Smckusick bp->b_resid = resid; 297*52130Smckusick } 298*52130Smckusick 299*52130Smckusick sc->sc_tab.b_actf = bp->b_actf; 300*52130Smckusick biodone(bp); 301*52130Smckusick if (sc->sc_tab.b_actf) 302*52130Smckusick tzstart(unit); 303*52130Smckusick else { 304*52130Smckusick sii_debug = 1; /* XXX */ 305*52130Smckusick sc->sc_tab.b_active = 0; 306*52130Smckusick if (sc->sc_flags & TZF_WAIT) { 307*52130Smckusick sc->sc_flags &= ~TZF_WAIT; 308*52130Smckusick wakeup(&sc->sc_flags); 309*52130Smckusick } 310*52130Smckusick } 311*52130Smckusick } 312*52130Smckusick 313*52130Smckusick tzopen(dev, flags) 314*52130Smckusick dev_t dev; 315*52130Smckusick int flags; 316*52130Smckusick { 317*52130Smckusick register int unit = tzunit(dev); 318*52130Smckusick register struct tz_softc *sc = &tz_softc[unit]; 319*52130Smckusick int error; 320*52130Smckusick 321*52130Smckusick if (unit >= NTZ) 322*52130Smckusick return (ENXIO); 323*52130Smckusick if (!(sc->sc_flags & TZF_ALIVE)) { 324*52130Smckusick /* check again, tape may have been turned off at boot time */ 325*52130Smckusick if (!tzprobe(sc->sc_sd)) 326*52130Smckusick return (ENXIO); 327*52130Smckusick } 328*52130Smckusick if (sc->sc_flags & TZF_OPEN) 329*52130Smckusick return (EBUSY); 330*52130Smckusick 331*52130Smckusick /* clear UNIT_ATTENTION */ 332*52130Smckusick error = tzcommand(dev, SCSI_TEST_UNIT_READY, 0, 0); 333*52130Smckusick if (error) { 334*52130Smckusick ScsiClass7Sense *sp = (ScsiClass7Sense *)sc->sc_sense.sense; 335*52130Smckusick 336*52130Smckusick /* return error if last error was not UNIT_ATTENTION */ 337*52130Smckusick if (!(sc->sc_sense.status & SCSI_STATUS_CHECKCOND) || 338*52130Smckusick sp->error7 != 0x70 || sp->key != SCSI_CLASS7_UNIT_ATTN) 339*52130Smckusick return (error); 340*52130Smckusick } 341*52130Smckusick 342*52130Smckusick #ifdef notdef 343*52130Smckusick if ((flag&FWRITE) && (sc->sc_dsreg&HTDS_WRL)) { 344*52130Smckusick sc->sc_openf = 0; 345*52130Smckusick uprintf("tu%d: no write ring\n", tuunit); 346*52130Smckusick return (EIO); 347*52130Smckusick } 348*52130Smckusick sc->sc_ctty = (caddr_t)(u.u_procp->p_flag & SCTTY ? 349*52130Smckusick u.u_procp->p_session->s_ttyp : 0); 350*52130Smckusick #endif 351*52130Smckusick sc->sc_flags = TZF_ALIVE | TZF_OPEN; 352*52130Smckusick return (0); 353*52130Smckusick } 354*52130Smckusick 355*52130Smckusick tzclose(dev, flag) 356*52130Smckusick dev_t dev; 357*52130Smckusick int flag; 358*52130Smckusick { 359*52130Smckusick register struct tz_softc *sc = &tz_softc[tzunit(dev)]; 360*52130Smckusick 361*52130Smckusick if (!(sc->sc_flags & TZF_OPEN)) 362*52130Smckusick return (0); 363*52130Smckusick if (flag == FWRITE || 364*52130Smckusick ((flag & FWRITE) && (sc->sc_flags & TZF_WRITTEN))) { 365*52130Smckusick (void) tzcommand(dev, SCSI_WRITE_EOF, 0, 1); 366*52130Smckusick } 367*52130Smckusick if ((minor(dev) & TZ_NOREWIND) == 0) 368*52130Smckusick (void) tzcommand(dev, SCSI_REWIND, 0, 0); 369*52130Smckusick sc->sc_flags &= ~(TZF_OPEN | TZF_WRITTEN); 370*52130Smckusick return (0); 371*52130Smckusick } 372*52130Smckusick 373*52130Smckusick tzioctl(dev, cmd, data, flag) 374*52130Smckusick dev_t dev; 375*52130Smckusick int cmd; 376*52130Smckusick caddr_t data; 377*52130Smckusick int flag; 378*52130Smckusick { 379*52130Smckusick register struct tz_softc *sc = &tz_softc[tzunit(dev)]; 380*52130Smckusick register struct buf *bp = &sc->sc_buf; 381*52130Smckusick struct mtop *mtop; 382*52130Smckusick struct mtget *mtget; 383*52130Smckusick int code, count; 384*52130Smckusick static tzops[] = { 385*52130Smckusick SCSI_WRITE_EOF, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE, SCSI_SPACE, 386*52130Smckusick SCSI_REWIND, SCSI_REWIND, SCSI_TEST_UNIT_READY 387*52130Smckusick }; 388*52130Smckusick 389*52130Smckusick switch (cmd) { 390*52130Smckusick 391*52130Smckusick case MTIOCTOP: /* tape operation */ 392*52130Smckusick mtop = (struct mtop *)data; 393*52130Smckusick if ((unsigned)mtop->mt_op < MTREW && mtop->mt_count <= 0) 394*52130Smckusick return (EINVAL); 395*52130Smckusick switch (mtop->mt_op) { 396*52130Smckusick 397*52130Smckusick case MTWEOF: 398*52130Smckusick code = 0; 399*52130Smckusick count = mtop->mt_count; 400*52130Smckusick break; 401*52130Smckusick 402*52130Smckusick case MTFSF: 403*52130Smckusick code = 1; 404*52130Smckusick count = mtop->mt_count; 405*52130Smckusick break; 406*52130Smckusick 407*52130Smckusick case MTBSF: 408*52130Smckusick code = 1; 409*52130Smckusick count = -mtop->mt_count; 410*52130Smckusick break; 411*52130Smckusick 412*52130Smckusick case MTFSR: 413*52130Smckusick code = 0; 414*52130Smckusick break; 415*52130Smckusick 416*52130Smckusick case MTBSR: 417*52130Smckusick code = 0; 418*52130Smckusick count = -mtop->mt_count; 419*52130Smckusick break; 420*52130Smckusick 421*52130Smckusick case MTREW: 422*52130Smckusick case MTOFFL: 423*52130Smckusick case MTNOP: 424*52130Smckusick code = 0; 425*52130Smckusick count = 0; 426*52130Smckusick break; 427*52130Smckusick 428*52130Smckusick default: 429*52130Smckusick return (EINVAL); 430*52130Smckusick } 431*52130Smckusick return (tzcommand(dev, tzops[mtop->mt_op], code, count)); 432*52130Smckusick 433*52130Smckusick case MTIOCGET: 434*52130Smckusick mtget = (struct mtget *)data; 435*52130Smckusick mtget->mt_dsreg = 0; 436*52130Smckusick mtget->mt_erreg = sc->sc_sense.status; 437*52130Smckusick mtget->mt_resid = 0; 438*52130Smckusick mtget->mt_type = 0; 439*52130Smckusick break; 440*52130Smckusick 441*52130Smckusick default: 442*52130Smckusick return (EINVAL); 443*52130Smckusick } 444*52130Smckusick return (0); 445*52130Smckusick } 446*52130Smckusick 447*52130Smckusick void 448*52130Smckusick tzstrategy(bp) 449*52130Smckusick register struct buf *bp; 450*52130Smckusick { 451*52130Smckusick register int unit = tzunit(bp->b_dev); 452*52130Smckusick register struct tz_softc *sc = &tz_softc[unit]; 453*52130Smckusick register struct buf *dp; 454*52130Smckusick register int s; 455*52130Smckusick 456*52130Smckusick bp->av_forw = NULL; 457*52130Smckusick dp = &sc->sc_tab; 458*52130Smckusick s = splbio(); 459*52130Smckusick if (dp->b_actf == NULL) 460*52130Smckusick dp->b_actf = bp; 461*52130Smckusick else 462*52130Smckusick dp->b_actl->av_forw = bp; 463*52130Smckusick dp->b_actl = bp; 464*52130Smckusick if (dp->b_active == 0) { 465*52130Smckusick dp->b_active = 1; 466*52130Smckusick tzstart(unit); 467*52130Smckusick } 468*52130Smckusick splx(s); 469*52130Smckusick } 470*52130Smckusick #endif 471