⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 st.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * @(#)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 + -