📄 scsi_tape.c
字号:
#ifndef lintstatic char *sccsid = "@(#)scsi_tape.c 4.6 (ULTRIX) 1/22/91";#endif lint/************************************************************************ * * * Copyright (c) 1984,86,87,88,89 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * * scsi_tape.c 23_Jun-89 * * VAX SCSI device driver (tape routines) * * Modification history: * * 08-Jan-91 Robin Miller * Modified DEVIOCGET ioctl() code to properly return tape density * codes. To resolve this problem, the density_table[] was defined * to decode the mode sense density code, and additional code was * added to return default density codes. * * 15-Nov-90 Robin Miller * Removed clearing of the DEV_TPMARK flag in tzstrategy() for nbuf * I/O requests (B_RAWASYNC). This caused a race condition with code * in the SCSI state machine with outstanding read requests. This * problem caused the queued reads to read past the tape file mark. * * 21-Sept-90 Bill Dallas * Fixed 2 problems with the devget ioctl. * Problem one caused a panic if someone made a minor * number by hand (aka mknod) which was out side the * controllers range. The second problem was minor, * we never gave back to the user the lower 4 bits * of the devget.category_stat field. * * 30-Jul-90 Bill Dallas * Added fixed block tape units tape mark handling. * This included a new falg in sc_category_flags called * TPMARK_PENDING * * 13-Nov-89 Janet Schank * Changed the refrence of nNSCSI to nNSCSIBUS. * * 08-Oct-89 Fred Canter * Bump TZ30 minium revision level to 11. It should be 12, but * we never received rev 12 drives to test. * Remove #ifdef OLDWAY. * * 01-Oct-89 Fred Canter * Bug fix. Tapes were not reporting write locked status via the * devioget ioctl. * * 24-Jul-89 Fred Canter * Bug fix for dump (MT CACHE ioctls not supported by SCSI). * * 16-Jul-89 Fred Canter * Changed meaning of count field for MODSNS tzcommand/rzcommand. * * 23-Jun-89 John A. Gallant * Added the tape command completion routine. * * 19-Jun-89 Fred Canter * Convert to scsi_devtab. * * 13-Jun-89 Fred Canter * Added MTFLUSH to tzioctl (always returns ENXIO). * * 06-Apr-89 Fred Canter * Added TZxx (EXABYTE) support. Cannot count on TZxx drives * supporting the receive diagnostic results command. * * Added b_comand to replace b_command for local command buffers. * Use b_gid instead of b_resid to store command. * * Added debug code to allow mode sense before tape open. * * 12-Feb-89 Fred Canter * Added function header comments to each routine. * * 5-Feb-89 Fred Canter * Added tz_tz30_minrev and tz_tzk50_minrev so minimum firmware * revision levels for tapes can be changed with adb. * * 14-Jan-89 Fred Canter * Clear sc_category_flags in tzopen() so left over DEV_TPMARK * does not casue drive to fail all commands after encountering * a tape mark. * Fixed a bug which caused a space command (via ioctl) to * space over a tape mark without failing (as it should). * In tzioctl(), fail the ioctl if DEV_TPMARK set. * Update minimum firmware revision for the TZK50 to 45. * * 28-Dec-88 Fred Canter * Changed stops to tzops in tzioctl, for consistency. * * 18-Dec-88 Fred Canter * Fixed (as best I could) info returned for MTIOCGET ioctl * (mt status). So MTX can handle EOT on SCSI tapes. * * 17-Dec-88 Fred Canter * Added pseudo commands to resolve the conflict between * SZ_UNLOAD and SZ_SSUNIT both being opcode 0x1b. * * 16-Oct-88 Fred Canter * Clean up comments. * * 28-Sep-88 Fred Canter * Clean up comments. * * 21-Aug-88 Fred Canter * Fixed a bug which caused the magtape exerciser MTIOCTOP ioctl * to fail. Check status and sense key after ioctl. * * 17-Aug-88 Fred Canter * Created this file by moving the SCSI tape specific files * from the old combined driver (scsi.c) to scsi_tape.c. * ***********************************************************************/#include "scsi.h"#include "sii.h"#if NSCSI > 0 || NSII > 0 || defined(BINARY)#include "../data/scsi_data.c"#include "scsi_debug.h"/* * Define the tape density table. */static int density_table[] = { 0, /* 0x00 - Default density. */ DEV_800BPI, /* 0x01 - 800 BPI (NRZI, R) */ DEV_1600BPI, /* 0x02 - 1600 BPI (PE, R) */ DEV_6250BPI, /* 0x03 - 6250 BPI (GCR, R) */ DEV_8000_BPI, /* 0x04 - 8000 BPI (GCR, C) */ DEV_8000_BPI, /* 0x05 - 8000 BPI (GCR, C) */ 0, /* 0x06 - 3200 BPI (PE, R) */ 0, /* 0x07 - 6400 BPI (IMFM, C) */ DEV_8000_BPI, /* 0x08 - 8000 BPI (GCR, CS) */ DEV_38000BPI, /* 0x09 - 37871 BPI (GCR, C) */ DEV_6666BPI, /* 0x0A - 6667 BPI (MFM, C) */ DEV_1600BPI, /* 0x0B - 1600 BPI (PE, C) */ 0, /* 0x0C - 12690 BPI (GCR, C) */ DEV_10000_BPI, /* 0x0D - QIC-120 with ECC. */ DEV_10000_BPI, /* 0x0E - QIC-150 with ECC. */ DEV_10000_BPI, /* 0x0F - QIC-120 (GCR, C) */ DEV_10000_BPI, /* 0x10 - QIC-150 (GCR, C) */ DEV_16000_BPI, /* 0x11 - QIC-320 (GCR, C) */ 0, /* 0x12 - QIC-1350 (RLL, C) */ DEV_61000_BPI, /* 0x13 - 4mm Tape (DDS, CS) */ DEV_54000_BPI /* 0x14 - 8mm Tape (???, CS) */};static int density_entrys = sizeof(density_table) / sizeof(int);/* * TODO: * Temporary(?) debug variable. * If nonzero, SZ_NODEVICE is returned from tz_rcvdiag() * if the tape fails self test or its firmware revision * level is too far out of date. * If zero, tz_rcvdiag() results are ignored. */int sz_open_fst = 1;int wakeup();extern int hz;extern int sz_unit_rcvdiag[]; /* If zero, need unit's selftest status *//* * Unit on line flag. Set to one if the * device is on-line. Set to zero on any unit * attention condition. */extern int sz_unit_online[];/* * * Name: tzopen -Tape open routine * * Abstract: This routine is called each time a tape device * is opened. This routine: makes sure the device * exists, checks for device on-line via test unit * ready, and does a mode select (sets buffered mode). * On the first call, a receive diagnostic results * command is done to make sure the tape drive is ok. * * Inputs: * * dev ULTRIX major/minor device number. * flag How to open flag (read, write, NDELAY). * * Outputs: * Possible error messages (eg, device off-line). * sz_unit_online flag set. * Exclusive use flag (sc_openf) flag set. * * Return Values: * * ENXIO No such device or address (non extistent device). * EIO I/O error (device off-line, etc). * 0 Open succeeded. * * Side Effects: * tzcommand() called. * sleep() called. * */tzopen(dev, flag) register dev_t dev; register int flag;{ register struct uba_device *ui; register struct sz_softc *sc; int unit = UNIT(dev); int cntlr; int targid; int retry = 0; int retval; int dev_ready; struct sz_modsns_dt *sdp; /* * Order of following checks is important. */ if (unit >= nNSZ) return(ENXIO); ui = szdinfo[unit]; if ((ui == 0) || (ui->ui_alive == 0)) return(ENXIO); cntlr = ui->ui_ctlr; if (cntlr >= nNSCSIBUS) return(ENXIO); targid = ui->ui_slave; sc = &sz_softc[cntlr]; if (sc->sc_alive[targid] == 0 || sc->sc_openf[targid]) return (ENXIO); if ((sc->sc_devtyp[targid] & SZ_TAPE) == 0) return(ENXIO); /* * This is a strange use of the FNDELAY flag. It * is here to allow the installation finder program * to open the device when the tape cartridge is not * inserted. The installation finder program needs * to do an ioctl, so open must succeed whether or * not a cartridge is present. */ /* * Clear sc_flags, device will lockup after any * hard error (DEV_HARDERR set) if we don't. * TODO: other drivers look at dis_eot_??[]! */ sc->sc_flags[targid] = 0; sc->sc_category_flags[targid] = 0; sc->sc_szflags[targid] &= ~SZ_NODEVICE; /* * Get selftest result, if we haven't already. * The tz_rcvdiag() routine will return * SZ_NODEVICE if anything is wrong. * * Fix for the nodiag flag in devtab..Some units * must have a senddiag cmd before a recvdiag cmd * or data is garbage for the recv diag cmd. We * will just look at the NO_DIAG flag in the devtab * struct for this type unit. */ if ((sz_unit_rcvdiag[unit] == 0) && ((sc->sc_devtab[targid]->flags & SCSI_NODIAG) == 0)) { sc->sc_szflags[targid] |= tz_rcvdiag(dev); } /* * Try to bring the drive on line. * The TZK50 takes about 25 seconds come ready after * a cartridge change. The TZ30 takes about 30 seconds. * So, we try for 40 seconds to bring the drive on-line. * This allows the user some think time to realize the * tape is off-line and load the cartridge. */ dev_ready = 0; for (retry = 0; retry < 20; retry++) { if (sc->sc_szflags[targid] & SZ_NODEVICE) { if (flag & FNDELAY) break; else return(ENXIO); } tzcommand(dev, SZ_TUR, 1, 0); if (sc->sc_c_status[targid] == SZ_GOOD) { dev_ready = 1; break; } else if (sc->sc_c_status[targid] == SZ_BAD) { continue; } else if (sc->sc_c_status[targid] == SZ_CHKCND) { retval = SZ_RETRY; switch(sc->sc_c_snskey[targid]) { case SZ_NOSENSE: case SZ_RECOVERR: retval = SZ_SUCCESS; dev_ready = 1; break; case SZ_NOTREADY: timeout(wakeup, (caddr_t)&sc->sc_alive[targid], (hz*2)); sleep((caddr_t)&sc->sc_alive[targid], PZERO + 1); if (!(sc->sc_flags[targid] & DEV_EOM)) { sc->sc_flags[targid] = 0; } break; case SZ_UNITATTEN: sz_unit_online[unit] = 0; /* just retry */ break; default: /* TODO: may want to retry? */ if (!(sc->sc_flags[targid] & DEV_EOM)) { sc->sc_flags[targid] = 0; } if(flag & FNDELAY) { sc->sc_szflags[targid] |= SZ_NODEVICE; retval = SZ_SUCCESS; } else { return(ENXIO); } break; } /* end of switch */ if (retval == SZ_SUCCESS) break; /* from for loop */ else continue; /* with for loop */ } else { /* TODO: debug */ printf("tzopen: impossible sc_c_status (val=%d)\n", sc->sc_c_status[targid]); continue; /* retry */ } } /* end for loop */ if (retry >= 20) { if (!(flag & FNDELAY)) { DEV_UGH(sc->sc_device[targid], unit, "offline"); return(EIO); } } /* * If SZ_NODEVICE is not set, the device exists, * and we want to do a SZ_MODSEL command */ if (!(sc->sc_szflags[targid] & SZ_NODEVICE)) { if (tz_exabyte_modsns) { tzcommand(dev, SZ_MODSNS, -1, 0); if (sc->sc_c_status[targid] != SZ_GOOD) printf("tzopen: %s unit %d: mode sense failed\n", sc->sc_device[targid], unit); sdp = (struct sz_modsns_dt *)&sc->sz_dat[targid]; printf("vu = 0x%x, mt = 0x%x, rt = 0x%x\n", sdp->vulen, sdp->pad[0], sdp->pad[1]); } for (retry = 0; retry < 5; retry++) { tzcommand(dev, SZ_MODSEL, 1, 0); if (sc->sc_c_status[targid] == SZ_GOOD) break; } if ((retry >= 5) && ((flag & FNDELAY) == 0)) { printf("tzopen: %s unit %d: mode select failed\n", sc->sc_device[targid], unit); return(EIO); } } /* So open nodelay doesn't falsely set on-line! */ if (dev_ready) sz_unit_online[unit] = 1; sc->sc_openf[targid] = 1; return (0);}int tz_tz30_minrev = 11; /* Minimum TZ30 firmware revision */int tz_tzk50_minrev = 45; /* Minimum TZK50 firmware revision *//* * * Name: tz_rcvdiag -Receive diagnostic results * * Abstract: This routine executes a receive diagnostic results * command for the specified tape drive, and uses * the results to determine if the tape exists, * is up to minimum firmware revision, and passed * self test. * * Inputs: * * dev ULTRIX major/minor device number. * * Outputs: * sz_unit_rcvdiag flag set. * Possible firmware revision level warning message. * Possible error message (receive diagnostics failed). * * Return Values: * * SZ_NODEVICE Tape drive does not exist or failed self test. * SZ_SUCCESS Tape exists and is operational. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -