📄 st.c
字号:
/* * @(#)st.c 1.1 92/07/30 Copyright (c) 1988 by Sun Microsystems, Inc. * * Driver for SCSI tape drives. *//*#define STDEBUG /* Allow compiling of debug code */#define REL4 /* Enable release 4 mods */#ifdef REL4#include <stand/saio.h>#include <stand/param.h>#include <sys/buf.h>#include <sun/dklabel.h>#include <sun/dkio.h>#include <mon/cpu.addrs.h>#include <mon/idprom.h>#include <stand/scsi.h>#include <stand/streg.h>#else REL4#include "saio.h"#include "param.h"#include "../h/buf.h"#include "../sun/dklabel.h"#include "../sun/dkio.h"#include "../mon/idprom.h"#include "../mon/cpu.addrs.h"#include "scsi.h"#include "streg.h"#endif REL4#ifdef STDEBUGint st_debug = 1; /* 0 = normal operation * 1 = extended error info only * 2 = debug and error info * 3 = all status info *//* Handy debugging 0, 1, and 2 argument printfs */#define DPRINTF(str) \ if (st_debug > 1) printf(str)#define DPRINTF1(str, arg1) \ if (st_debug > 1) printf(str,arg1)#define DPRINTF2(str, arg1, arg2) \ if (st_debug > 1) printf(str,arg1,arg2)/* Handy extended error reporting 0, 1, and 2 argument printfs */#define EPRINTF(str) \ if (st_debug) printf(str)#define EPRINTF1(str, arg1) \ if (st_debug) printf(str,arg1)#define EPRINTF2(str, arg1, arg2) \ if (st_debug) printf(str,arg1,arg2)static char *st_key_error_str[] = SENSE_KEY_INFO;#define MAX_KEY_ERROR_STR \ (sizeof(st_key_error_str)/sizeof(st_key_error_str[0]))#else STDEBUG#define DPRINTF(str)#define DPRINTF1(str, arg2)#define DPRINTF2(str, arg1, arg2)#define EPRINTF(str)#define EPRINTF1(str, arg2)#define EPRINTF2(str, arg1, arg2)#endif STDEBUG#ifdef BOOTBLOCK#define SC_ERROR(str)#define SC_ERROR1(str, arg1)#else BOOTBLOCK#define SC_ERROR printf#define SC_ERROR1 printf#endif BOOTBLOCKextern int sc_reset;extern int xxprobe(), xxboot();int stopen(), stclose(), ststrategy();/* * This table defines the auto-probe disk list. Currently only st0 and st1 * are probed automatically. Others can be added by simply adding them * to the following table. */u_char st_index[] = { 0x20, 0x28, 0x18, 0x10 };struct stparam { int st_target; int st_unit; int st_ctype; int st_dev_bsize; int st_eof; int st_lastcmd; struct host_saioreq h_sip; /* sip for host adapter */};/* * DMA-able buffers *//* Max tape record length allowed for various devices */#define ST_MAXXTREC (10*1024) /* 1/2-inch reel *//* Define virtual addresses space. Note, sun-2 is limited. */#ifdef sun2#define ST_MAXSIZE (30 * 1024)/*#define ST_MAXSIZE (20 * 1024) */#else sun2#define ST_MAXSIZE (126 * 512) #endif sun2struct stdma { char databuffer[ST_MAXSIZE]; char sbuffer[SC_SENSE_LENGTH];};#define BUF (((struct stdma *)sip->si_dmaaddr)->databuffer)#define STSBUF (((struct stdma *)sip->si_dmaaddr)->sbuffer)/* * What resources we need to run */struct devinfo stinfo = { 0, /* No device to map in */ sizeof (struct stdma), sizeof (struct stparam), 0, /* Dummy devices */ 0, /* Dummy devices */ MAP_MAINMEM, ST_MAXSIZE, /* transfer size */};struct boottab stdriver = { "st", xxprobe, xxboot, stopen, stclose, ststrategy, "st: SCSI tape", &stinfo};#define TAPE_TARGET 4 /* default SCSI target # for tape */#define SENSELOC 4 /* sysgen returns sense at this offset */#define ROUNDUP(x) ((x + DEV_BSIZE - 1) & ~(DEV_BSIZE - 1))#define min(a,b) ((a)<(b)? (a): (b))#define ISASYSGEN(stp) (stp->st_ctype == ST_TYPE_SYSGEN ? 1 : 0)#ifdef SDDEBUGsd_print_buffer(y, count) register u_char *y; register int count;{ register int x; for (x = 0; x < count; x++) printf("%x ", *y++); printf("\n");}#endif SDDEBUG/* * Open the SCSI Tape controller */stopen(sip) register struct saioreq *sip;{ register struct stparam *stp; register struct host_saioreq *h_sip; /* Host adapter block */ register struct st_ms_mspl *ms; register short r; register int skip; int i, index, ctlr; int do_reset = 1; DPRINTF("stopen:\n"); stp = (struct stparam *) sip->si_devdata; bzero( (char *)stp, (sizeof (struct stparam))); ctlr = sip->si_ctlr; /* Ctlr. number */ stp->st_ctype = ST_TYPE_SYSGEN; /* Always start with Sysgen! */ /* Set up host adapter and target info. */ST_OPEN_PROBE: if (sip->si_unit == 0) { index = 0; stp->st_unit = st_index[index] & 0x07; /* Logical unit */ stp->st_target = st_index[index++] >> 3; /* Target number */ } else { stp->st_unit = sip->si_unit & 0x07; /* Logical unit */ stp->st_target = sip->si_unit >> 3; /* Target number */ }ST_RETRY_OPEN: EPRINTF2("stopen: ctlr= 0x%x unit= 0x%x ", ctlr, stp->st_unit); EPRINTF1("target= 0x%x\n", stp->st_target); h_sip = &stp->h_sip; h_sip->ctlr = ctlr; /* Ctlr. number */ h_sip->unit = stp->st_target; /* Target number */ /* Probe for host adapter. */ if (scsi_probe(h_sip) == 0) { /* If an error occurred previously, reset the SCSI bus. */ if (sc_reset && do_reset) { EPRINTF("stopen: reset\n"); (void) (*h_sip->reset)(h_sip, 1); } /* * Test for the controller being ready. First test will fail * if the SCSI bus is permanently busy or if a previous op * was interrupted in mid-transfer. Second one should work. */ for (i = 0; i < 4; i++) { if ((r=stcmd(SC_TEST_UNIT_READY, sip, 0)) > 0) goto ST_OPEN; else if (r < -1) break; /*DELAY(2200); /* XXX: Extra timing margin for HP */ } /* If current tape device not ready, try the next one. */ if (sip->si_unit == 0 && index < sizeof(st_index)) { stp->st_unit = st_index[index] & 0x07; stp->st_target = st_index[index++] >> 3; do_reset = 0; goto ST_RETRY_OPEN; } } /* If current host adapter not ready, try the next one. */ if (sip->si_ctlr == 0 && ctlr < SC_NSC) { EPRINTF("stopen: trying next ha\n"); do_reset++; ctlr++; h_sip->devaddr = 0; goto ST_OPEN_PROBE; } EPRINTF("stopen: device offline\n"); return (-1); /* * Check for tape drive (that is..it's not a disk). Note, if * inquiry fails, we will presume the user knows what he's doing. */ST_OPEN: sc_reset = 1; sip->si_ctlr = ctlr; sip->si_unit = (stp->st_target <<3) + stp->st_unit; sip->si_ma = BUF; if (stcmd(SC_INQUIRY, sip, 0) > 0 && ((struct scsi_inquiry_data *)sip->si_ma)->dtype != 1) { EPRINTF("stopen: not a tape\n"); return (-1); } /* * To figure out what type of tape controller is out there we send * a REQUEST_SENSE command and see how much sense data comes back. */ stp->st_ctype = ST_TYPE_EMULEX; sip->si_cc = ST_EMULEX_SENSE_LEN; /*sip->si_ma = BUF;*/ r = stcmd(SC_REQUEST_SENSE, sip, 0); DPRINTF1("stopen: sense bytes= %x\n", r); if (r == ST_SYSGEN_SENSE_BYTES) { EPRINTF("stopen: Sysgen found\n"); stp->st_ctype = ST_TYPE_SYSGEN; stp->st_dev_bsize = DEV_BSIZE; sip->si_cc = ST_SYSGEN_SENSE_LEN; if (stcmd(SC_REQUEST_SENSE, sip, 0) <= 0) { SC_ERROR("st: cannot get sense\n"); return (-1); } } else { /* sip->si_ma = BUF; */ ms = (struct st_ms_mspl *) sip->si_ma; r = stcmd(SC_MODE_SENSE, sip, 0); stp->st_dev_bsize = (ms->high_bl <<16) + (ms->mid_bl <<8) + (ms->low_bl); EPRINTF1("stopen: density= 0x%x\n", ms->density); EPRINTF1("stopen: block size= %d\n", stp->st_dev_bsize); } /* Check for 1/2" tape */ (void) stcmd(SC_REWIND, sip, 0); if (stp->st_dev_bsize == 0) { if (stcmd(SC_QIC24, sip, 0) <= 0) { EPRINTF("stopen: Fixed CCS found\n"); stp->st_dev_bsize = DEV_BSIZE; goto STOPEN_TAPE; } sip->si_cc = 0; /* sip->si_ma = BUF; */ if (stcmd(SC_READ, sip, 0) <= 0) { EPRINTF("stopen: Emulex found\n"); stp->st_dev_bsize = DEV_BSIZE; (void) stcmd(SC_REWIND, sip, 0); goto STOPEN_TAPE; } else { EPRINTF("stopen: Variable CCS found\n"); stinfo.d_maxiobytes = ST_MAXXTREC; (void) stcmd(SC_REWIND, sip, 0); goto STOPEN_SKIP; } } /* * Default format mode for emulex is Qic24 for Sun-3 * or later. For Sun-2 use Qic-11. */STOPEN_TAPE:#ifdef sun2 (void) stcmd(SC_QIC11, sip, 1);#else sun2 (void) stcmd(SC_QIC24, sip, 1);#endif sun2 /* * If read fails, try the other format. For Sun-3 or later * this means Qic-11. For Sun-2, try Qic-24. */ sip->si_cc = 512; sip->si_ma = BUF; if (stcmd(SC_READ, sip, 0) > 0) { (void) stcmd(SC_REWIND, sip, 0); } else { (void) stcmd(SC_REWIND, sip, 0);#ifdef sun2 if (stcmd(SC_QIC24, sip, 1) <= 0) SC_ERROR("st: mode select failed\n");#else sun2 if (stcmd(SC_QIC11, sip, 1) <= 0) SC_ERROR("st: mode select failed\n");#endif sun2 }STOPEN_SKIP: skip = sip->si_boff; while (skip--) { sip->si_cc = 0; if (stcmd(SC_SPACE_FILE, sip, 1) <= 0) { SC_ERROR("st: space file failed\n"); return (-1); } } sc_reset = 0; stp->st_eof = 0; stp->st_lastcmd = 0; return (0);}/* * Close the tape drive and don't rewind it. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -