📄 stc.c
字号:
#ifndef lintstatic char *sccsid = "@(#)stc.c 4.1 ULTRIX 7/2/90";#endif lint/************************************************************************ * * * Copyright (c) 1984, 1986, 1987, 1988, 1989 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. * * * ************************************************************************//************************************************************************ * stc.c 02-Mar-89 * * Modification history * * TZK50 Tape Driver * * 02-Dec-89 Fred Canter * Bug fix; mprintf to error log printed address of sense data * bytes instead of the data in the sense data bytes. * Bug fix; restore issues a MTNOCACHE ioctl which causes a hardware * error on the TZK50. This prevented TK50 installtaions to MV2000 * and VS2000 systems. * * 17-May-89 Fred Canter * Yet another bug fix. Back/forward space thru a file mark should * fail but wasn't. * * 13-May-89 Fred Canter * Fixed yet another bug uncovered by the V3.1 installation. There * were many errors in the DEV_TPMARK flag handling. Code changes * identified with "#ifdef TM_NO_FIX". To include the fix, don't * define TM_NO_FIX. * * 10-May-89 Fred Canter * Fix to last bug fix. Caused driver to return error on filemark * read instead of returning the users' byte count. * * 25-Apr-89 Fred Canter * Cleared all flags in the open routine. This fixed a bug which * caused the driver to fail all reads after any fatal error, until * the system was rebooted. * * Changed printf to printd1 for the "Didn't space back over second * filemark" debug message. * * 24-Apr-89 Fred Canter * Rev 45 of the TZK50 firmware caused this driver to fail, because * it did not expect a save data pointer message with no data * remaining to be transferred (i.e., DMA count register = 0). * * 02-Mar-89 John A. Gallant * In st_start(), correctly initialized the um pointer. * * 28-Sep-88 Fred Canter * Clean up comments. * * 01-Sep-88 darrell * ST_W_DMA: now saves a copy of sc_stflags which it restore, as * the call to st_scsistart() clears sc_stflags. Also corrected * the check in ST_SP_CONT: that determines if the REQUEST SENSE * succeeded. This fixes a P1 bug that was elevated to a CLD * (SPR 4st-00571) * * 06-Jun-88 Fred Canter * Changes to allow this driver to use PVAX extended data buffer * I/O mode. * * 15-Feb-88 Fred Canter * Changes for VAX420 (CVAXstar/PVAX) support. * * 12-Jan-88 darrell * Rewrote st_timer(). I had forgotten about the fact that a * space command could take up to approximately 40 minutes to * complete. The timer was set to go off every 3 minutes and * if a command had not completed as of the second time timeout * the drive was assumed to be dead. Each command is now looked * up in a table and timed separately. * * 15-Sep-87 darrell * Copied most if stintr() into another routine st_scsistart() which * is used to start the scsi transfer. stintr used to be called by * st_start() to start the scsi transfer which was clearly not how * an interrupt routine is supposed to work, and it also made * returning from stintr() and st_start() quite complex. As a result * of these latest changes, st_start calls st_scsistart() to start * the transfer, and stintr() is only called from interrupt -- which * is much cleaner, and the "right" thing to do. At the same time * the sc_stflags field in the ST_R_DMA: case is restored after the * Request Sense Command -- which fixes a panic which was happening * in vs_bufctl. * * 20-Aug-87 darrell * Added a timeout routine (st_timer) to timeout commands and reset * the controller. A request diagnostic results command is now send * to read the controller firmware and refuse to be opened if the * firmware rev is below REV 34. The first command sent to the drive * now is a Receive Diagnostic Results command. This should always * return success if the drive is there and working, so we no longer * need to wait for three minutes with a Test Unit Ready of "not ready" * in order to tell if the tape is there. * * 23-Apr-87 darrell * Changed the calls to vs_bufctl to pass a pointer to a structure * that contains a pointer to the function that vs_bufctl is to call. * This is the first step of cleaning up some of this code, and making * it more maintainable. * * 15-Mar-87 darrell * Removed the code that does a bus reset. The bus reset was being * done on all error conditions. Now a bus reset is never done. * * 03-Mar-87 darrell * Added multi-volume support. Fixed various small bugs. Increased * the default number of fills to seven (7). If the drive exists, but * the tape is not loaded, and the open routine is called with FNDELAY, * the driver now waits to make sure that there is not an outstanding * rewind. * * 27-Jan-87 darrell * Added support for the change in V32 of the TZK50 microcode that * allows the reselect timeout (TZK50 timing out the host) to be * disabled. A change was also made to catch and return an iodone * on buffers that were queued as a result of nbuffio, after a * hard error was detected. Also OR'ed the density bits into the * category_stat field in the DEVIOGET case of stioctl -- so now * dump can calculate the correct length of tape needed. * * 15-Jan-87 darrell * Rewrote about half of this driver to support * disconnects/reselects, make the tape stream, and * reduce the adverse performance impact this driver * had on the system. Seems to work well. EOT is * still not tested. * * 23-Oct-86 darrell * Fixed a FNDELAY problem so finder now works. * * 26-Sep-86 darrell * Cleaned up error message printouts, and fixed a problem where * opening the device FNDELAY allowed the first command after * changing a tape to fail. * * 26-Sep-86 darrell * Removed a debug printf I had left in my last delta. * * 26-Sep-86 darrell * Fixed a problem queueing multiple requests so that nbuf * I/O will work. Also enabled buffered writing. * * 12-Sep-86 darrell * Fixed remaining ioctl's, put in the devioctl code to * to work with the utilities using nbufio. bp->b_resid * is now returned correctly. Fixed many other little bugs. * * 04-Sep-86 darrell * Made ioctls work - all except MTIOCGET:, put in code to * handle EOM, EOT, and other tape end contition, and did a * lot of cleanup in removing old unused code, and comments, * and changed ST_SP_COMPL: DATAI: to only read as many * characters as are expected in program I/O -- as the STATUS * byte was getting sucked in. * * 4-Sep-86 darrell (Darrell Dunnuck) * First semi-working driver. * * 26-Aug-86 rsp (Ricky Palmer) * Cleaned up devioctl code to (1) zero out devget structure * upon entry and (2) use strlen instead of fixed storage * for bcopy's. * * 5-Aug-86 darrell * First pass of real driver (compiles but not debugged). * * 12-Jun-86 darrell * started with ht.c, and made it into this file. * *//*********************************************************************** * TODO: * * 1. This driver needs to support record sizes greater that 16k. * The maximum size supported by the TZK50 is 64k. This driver * should be changed to support record sizes up to 64k. *********************************************************************** */ /* */#if NST > 0 || defined(BINARY)#include "../data/stc_data.c"extern int cvs_exmode_on;u_char inicmd_tmp; /* keep this around since we can't |= the scs_inicmd reg */int st_from_open; /* used to tell when the command was initiated from stopen*/int st_retries = 0; /* retry counter */int st_max_numof_fills = ST_DEFAULT_FILLS; /* Maximum number of fills to write*/ /* in order to try to keep the tape*/ /* drive streaming. */extern struct vsbuf vsbuf;struct vsdev vstapedev = { VS_ST, 0, 0 };int stprobe(), stslave(), stattach(), stintr(), st_start(), sterror(), st_timer(), st_scsistart();u_short ststd[] = { 0 };struct uba_driver stcdriver = { stprobe, stslave, stattach, st_start, ststd, "st", stdinfo, "stc", stminfo, 0 };int wakeup();extern int hz;extern struct nexus nexus[];struct stspace ST_bufmap[];extern int cpu;extern int cpu_subtype;#define ST_TIMERRATE 30 /* how often the timer goes off */int unit_attn = 1; /* An indication that the tape was removed *//* * The following table is the timeout value for each command assuming that * the timer is set to go off every 30 seconds. */char st_timetable[48] = { 2, /* ST_TUR 0x00 */ 6, /* ST_REWIND 0x01 */ 0, /* unused 0x02 */ 2, /* ST_RQSNS 0x03 */ 0, /* unused 0x04 */ 0, /* ST_RBL 0x05 */ 0, /* unused 0x06 */ 0, /* unused 0x07 */ 8, /* ST_READ 0x08 */ 0, /* unused 0x09 */ 8, /* ST_WRITE 0x0a */ 2, /* ST_TRKSEL 0x0b */ 0, /* unused 0x0c */ 0, /* unused 0x0d */ 0, /* unused 0x0e */ 0, /* unused 0x0f */ 2, /* ST_WFM 0x10 */ 90, /* ST_SPACE 0x11 */ 2, /* ST_INQ 0x12 */ 0, /* ST_VFY 0x13 */ 0, /* ST_RBD 0x14 */ 2, /* ST_MODSEL 0x15 */ 0, /* ST_RESUNIT 0x16 */ 0, /* ST_RELUNIT 0x17 */ 0, /* unused 0x18 */ 0, /* ST_ERASE 0x19 */ 2, /* ST_MODSNS 0x1a */ 6, /* ST_LOAD/ST_UNLOAD 0x1b */ 6, /* ST_RCVDIAG 0x1c */ 0, /* ST_SNDDIAG 0x1d */ 90, /* ST_FSPACER 0x1e */ 90, /* ST_FSPACEF 0x1f */ 0, /* unused 0x20 */ 0, /* unused 0x21 */ 0, /* unused 0x22 */ 0, /* unused 0x23 */ 0, /* unused 0x24 */ 0, /* unused 0x25 */ 0, /* unused 0x26 */ 0, /* unused 0x27 */ 0, /* unused 0x28 */ 0, /* unused 0x29 */ 0, /* unused 0x2a */ 0, /* unused 0x2b */ 2, /* ST_P_CACHE 0x2c */ 2, /* ST_P_NOCACHE 0x2d */ 90, /* ST_BSPACER 0x2e */ 90 /* ST_BSPACEF 0x2f */};/* STDEBUG intentionally left defined */#define STDEBUG#ifdef STDEBUG#define ST_TRACK_SIZE 100 /* size of the tracking buffer */#define ST_CMDTRACK_SIZE 600 /* size of the command tracking buffer */char sttrack[ST_TRACK_SIZE];char stcmdtrack[ST_CMDTRACK_SIZE];int st_cmdindex = ((ST_CMDTRACK_SIZE) - 1);int st_index = ST_TRACK_SIZE - 1;/* * ST_TRACK - a macro that writes into the ST_TRACK_SIZE * array that is used as a trail of what this driver has * done. The data is written into the array starting from * the highest address down to the lowest address to make * it easier to trace backwards using adb. * */#define ST_TRACK(a) if(st_index < 0 ) \ st_index = (ST_TRACK_SIZE - 1); \ sttrack[st_index--] = a/* * ST_CMDTRACK - a macro that writes into an array the command * that was sent to the drive -- to be used as a trail of * what this driver has done. The data is written into the array * starting from the highest address down to the lowest address * to make it easier to trace backwards using adb. */#define ST_CMDTRACK(a) if(st_cmdindex < 0 ) \ st_cmdindex = ((ST_CMDTRACK_SIZE) - 1); \ stcmdtrack[st_cmdindex--] = aint stdebug = 0;#define printd if(stdebug)printf#define printd1 if (stdebug > 1) printf#define printd2 if (stdebug > 2) printf#define printd3 if (stdebug > 3) printf#define printd4 if (stdebug > 4) printf#define printd5 if (stdebug > 5) printf#define printd6 if (stdebug > 6) printfint st_direct_track_mode = 0; /* for testing multivolume dump */u_char st_prev_cmd; /* keeps track of the previous command sent to drive *//* * Trace Tables */char *trace_xstate [] = { "ST_NEXT", "ST_SP_START", "ST_SP_CONT", "ST_RW_START", "ST_R_STDMA", "ST_W_STDMA", "ST_R_DMA", "ST_W_DMA", "ST_R_COPY", "ST_R_DMACONT", "ST_W_DMACONT", "ST_ERR"};char *trace_fstate [] = { "ST_SP_ARB", "ST_SP_SEL", "ST_CMD_PHA", "ST_DATAO_PHA", "ST_DATAI_PHA", "ST_STATUS_PHA", "ST_MESSI_PHA", "ST_MESSO_PHA", "ST_RELBUS", "ST_ABORT"};char *trace_event [] = { "ST_CONT", "ST_BEGIN", "ST_DMA_DONE", "ST_PAR_ERR", "ST_PHA_MIS", "ST_RESET", "ST_CMD", "ST_DMA", "ST_ABRT", "ST_ERROR", "ST_TIMEOUT", "ST_FREEB"};#endif STDEBUG/* */stprobe(reg, cntlr) int cntlr; caddr_t reg;{ register struct nb1_regs *staddr = (struct nb1_regs *)qmem; register struct nb_regs *stiaddr = (struct nb_regs *)nexus;#ifdef STDEBUG printd6("stprobe: probing TZK50\n");#endif STDEBUG /* * This driver only runs on VAXstar/Teammate. * It cannot be used with CVAXstar/PVAX. */ if (cpu != VAXSTAR) return(0); stiaddr->nb_int_reqclr = SCS_INT_TAPE; /* clear SCSI in INT_REQ reg */ stiaddr->nb_int_msk |= SCS_INT_TAPE; /* enable SCSI interrupts */ /* the reset of the SCSI bus may cause an interrupt */ staddr->scs_inicmd = SCS_INI_RST; /* reset the SCSI bus */ DELAY(100000); /* clear RST */ staddr->scs_inicmd = 0; /* make the controller interrupt */ /* may not need this stuff, the reset may cause an interrupt */ if((stiaddr->nb_int_reqclr&SCS_INT_TAPE) == 0) { /* didn't cause intr */ staddr->scs_selena = SCS_ID0; staddr->scs_outdata = (SCS_ID0 | SCS_ID1); staddr->scs_inicmd = (SCS_INI_SEL | SCS_INI_ENOUT); DELAY(100000); /* may not need this */ staddr->scs_inicmd = 0; staddr->scs_selena = 0; } stiaddr->nb_int_reqclr = SCS_INT_TAPE; /* clear SCSI in INT_REQ reg */#ifdef STDEBUG if (cvec && cvec == 0x200) /* check for interrupt */ printd6("stprobe: controller didn't interrupt\n"); else printd6("stprobe: controller found at vector %o\n", cvec);#endif STDEBUG return(1); /* * Determine if the drive exists, and is a TK50. * We can get away with using a dev of zero in the * stcommand because it is not checked anywhere in * this driver. */}/* */stattach(ui) register struct uba_device *ui;{ register struct uba_ctlr *um; ui->ui_flags = 0; /* * Link the drive buffer to the controller queue and * leave it there since there is only one drive. We'll * check for outstanding requests queued for the drive. */ um = ui->ui_mi; um->um_tab.b_actf = &stutab[0]; um->um_tab.b_actl = &stutab[0]; um->um_tab.b_actf->b_actf = NULL;}/* */stslave(ui) register struct uba_device *ui;{ register struct st_softc *sc; register int s = spl5(); sc = &st_softc[0]; bcopy(DEV_TK50, sc->sc_device, strlen(DEV_TK50)); splx(s); if (ui->ui_slave) return(0); return(1);}/* */stopen(dev, flag) register dev_t dev; register int flag;{ register struct uba_device *ui; register struct st_softc *sc; int unit = UNIT(dev); int retry = 0; int retval;#ifdef STDEBUG ST_TRACK('o');#endif STDEBUG if (unit >= nNST || (sc = &st_softc[unit])->sc_openf || (ui = stdinfo[unit]) == 0 || ui->ui_alive == 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -