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

📄 sd.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
字号:
/* * @(#)sd.c 1.1 92/07/30 Copyright (c) 1985 by Sun Microsystems, Inc. * * Driver for SCSI disk drives. *//*#define SDDEBUG 		/* Allow compiling of debug code */#define REL4			/* Enable release 4 mods */#ifdef REL4#include <stand/saio.h>#include <stand/param.h>#include <sun/dklabel.h>#include <sun/dkio.h>#include <sys/buf.h>#include <mon/sunromvec.h>#include <mon/idprom.h>#include <mon/cpu.addrs.h>#include <stand/scsi.h>#else REL4#include "saio.h"#include "param.h"#include "../sun/dklabel.h"#include "../sun/dkio.h"#include "../h/buf.h"#include "../mon/sunromvec.h"#include "../mon/idprom.h"#include "../mon/cpu.addrs.h"#include "scsi.h"#endif REL4extern int sc_reset;extern int xxprobe(), xxboot(), nullsys();int sdopen(), sdclose(), sdstrategy();#ifdef SDDEBUGint sd_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 (sd_debug > 1) printf(str)#define DPRINTF1(str, arg1) \	if (sd_debug > 1) printf(str,arg1)#define DPRINTF2(str, arg1, arg2) \	if (sd_debug > 1) printf(str,arg1,arg2)/* Handy extended error reporting 0, 1, and 2 argument printfs */#define EPRINTF(str) \	if (sd_debug) printf(str)#define EPRINTF1(str, arg1) \	if (sd_debug) printf(str,arg1)#define EPRINTF2(str, arg1, arg2) \	if (sd_debug) printf(str,arg1,arg2)#else SDDEBUG#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 SDDEBUG#ifdef BOOTBLOCK#define SD_MAXSIZE	MAXBSIZE#define SC_ERROR(str)#define SC_ERROR1(str, arg1)#else BOOTBLOCK#define SD_MAXSIZE	(4 * MAXBSIZE)#define SC_ERROR	printf#define SC_ERROR1	printf#endif BOOTBLOCK/* * 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 sd_index[] = { 0x00, 0x18 };struct sdparam {	int	sd_target;	int	sd_unit;	unsigned	sd_boff;		/* real boff... */	struct host_saioreq h_sip;	/* sip for host adapter */};/* * Our DMA space */struct sddma {	char	buffer[SD_MAXSIZE];	char	sbuffer[SC_SENSE_LENGTH];};#define BUF		(((struct sddma *)sip->si_dmaaddr)->buffer)#define STSBUF		(((struct sddma *)sip->si_dmaaddr)->sbuffer)#define ROUNDUP(x)	((x + SECSIZE - 1) & ~(SECSIZE - 1))#define MSGS_OFF	1#define MSGS_ON		0/* * What resources we need to run */struct devinfo sdinfo = {	0,				/* No device to map in */	sizeof (struct sddma),	sizeof (struct sdparam),	0,				/* Dummy devices */	0,				/* Dummy devices */	MAP_MAINMEM,	SD_MAXSIZE,			/* transfer size */};/* * The interfaces we export */struct boottab sddriver = {	"sd",	xxprobe, xxboot, sdopen, sdclose, sdstrategy,	"sd: SCSI disk", &sdinfo};#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#ifndef	BOOTBLOCK/* * Test routine for isspinning() to see if SCSI disk is running. *//*ARGSUSED*/intsdspin(sip, dummy)	struct saioreq *sip;	int dummy;{	DPRINTF("sdspin:\n");	return (sdcmd(SC_TEST_UNIT_READY, sip, MSGS_OFF));}#endif	BOOTBLOCK/* * Open the SCSI Disk controller */sdopen(sip)	register struct saioreq *sip;{	register struct sdparam *sdp;	register struct host_saioreq *h_sip;	/* Sip for host adapter */	register struct dk_label *label;	int index, ctlr;	int do_reset = 1;	DPRINTF("sdopen:\n");	sdp = (struct sdparam *)sip->si_devdata;	label = (struct dk_label *)BUF;	bzero( (char *)sdp, (sizeof (struct sdparam)));	ctlr = sip->si_ctlr;		/* Ctlr. number */	/* Set up host adapter and target info. */SD_OPEN_PROBE:	if (sip->si_unit == 0) {		index = 0;		sdp->sd_unit = sd_index[index] & 0x07; /* Logical unit */		sdp->sd_target = sd_index[index++] >> 3; /* Target number */	} else {		sdp->sd_unit = sip->si_unit & 0x07;	/* Logical unit */		sdp->sd_target = sip->si_unit >> 3;  	/* Target number */	}SD_RETRY_OPEN:	DPRINTF2("sdopen: ctlr= 0x%x  unit= 0x%x", ctlr, sdp->sd_unit);	DPRINTF1("  target= 0x%x\n", sdp->sd_target);	h_sip = &sdp->h_sip;	h_sip->ctlr = ctlr;		/* Ctlr. number */	h_sip->unit = sdp->sd_target;		/* Host adapter LU 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("sdopen: 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.		 */		if (sdcmd(SC_TEST_UNIT_READY, sip, MSGS_OFF) > 0)				goto SD_OPEN;#ifndef	BOOTBLOCK		/* If current disk device not ready, try the next one. */		if (sip->si_unit == 0  &&  index < sizeof(sd_index)) {			sdp->sd_unit = sd_index[index] & 0x07;			sdp->sd_target = sd_index[index++] >> 3;			do_reset = 0;			goto SD_RETRY_OPEN;		}		/* If current host adapter not ready, try the next one. */		if (sip->si_ctlr == 0  &&  ctlr < SC_NSC) {			EPRINTF("sdopen: trying next ha\n");			do_reset++;			ctlr++;			h_sip->devaddr = 0;			goto SD_OPEN_PROBE;		}#endif	BOOTBLOCK	}	EPRINTF("sdopen: device offline\n");	return (-1);SD_OPEN:	sc_reset = 1;	sip->si_unit = (sdp->sd_target <<3) + sdp->sd_unit;	(void) sdcmd(SC_START, sip, MSGS_OFF);	/* Spin-up disk */#ifndef	BOOTBLOCK	switch (isspinning(sdspin, (char *)sip, 0)) {	default:				/* Error from sdspin */	case 0:					/* Disk still not ready */		EPRINTF("sdopen: device not ready\n");		return (-1);	case 1:					/* Spinning */		DPRINTF("sdopen: device ready\n");		break;	case 2:  				/* Just started spinup */		EPRINTF("sdopen: spinning up\n");		DELAY(2000000);  		/* Wait 2 Sec. */		break;	}#endif	BOOTBLOCK	/*	 * Check if it's a disk.  Note, if inquiry fails, we presume	 * the user knows what he's doing.	 */	sip->si_ma = BUF;	if (sdcmd(SC_INQUIRY, sip, MSGS_OFF) > 0  &&	   ((struct scsi_inquiry_data *)sip->si_ma)->dtype == 1) {		EPRINTF("sdopen: not a disk\n");		return (-1);	}	/*	 * Read the label	 */	label->dkl_magic = 0;	sip->si_bn = 0;				/* Read block #0 */	sip->si_cc = SECSIZE;	/*sip->si_ma = BUF;*/	if (sdcmd(SC_READ, sip, MSGS_ON) <= 0) {		EPRINTF("sdopen: label read failed\n");		return (-1);	}	EPRINTF1("sd: <%s>\n", (char *)sip->si_ma);	if (chklabel(label)) {		EPRINTF("sdopen: no label\n");		return (-1);	}	/*	 * Compute starting (abs.) starting block number and partition	 * size (in bytes).  Note:	 *	si_cyloff = starting block number of partition	 *	si_boff = size of partition in bytes	 * FIXME:  sd_boff really should be in sip structure.  Note	 * being there mans that ONLY one connection to sd can be 	 * used at a time (which is all we really do at the present).	 */	sip->si_cyloff = (u_short)(label->dkl_map[sip->si_boff].dkl_cylno)	    * (u_short)(label->dkl_nhead * label->dkl_nsect);	sdp->sd_boff =		(u_short) label->dkl_map[sip->si_boff].dkl_nblk * SECSIZE;	if (sdp->sd_boff == 0) {		EPRINTF("sdopen: zero size partition\n");		return (-1);	}	sc_reset = 0;	return (0);}/* * Close the SCSI Disk controller. */sdclose(sip)	register struct saioreq *sip;{	EPRINTF("sdclose:\n");#ifdef	lint	sip = sip;#endif	lint	sc_reset = 0;}/* * Execute reads or writes for the outside world. */sdstrategy(sip, rw)	struct saioreq *sip;	register int rw;{	register struct sdparam *sdp;	DPRINTF2("sdstrategy:  addr= 0x%x  size= 0x%x\n",		 (int)(sip->si_ma), sip->si_cc);	sc_reset = 1;	sdp = (struct sdparam *)sip->si_devdata;	if (sdp) {		if (sip->si_cc > sdp->sd_boff) {			EPRINTF("sdstrategy: request too big\n");			sip->si_cc = sdp->sd_boff;		}	}	if (sip->si_cc <= 0) {		EPRINTF("sdstrategy: request too small\n");		return(0);	}	rw = sdcmd((rw == WRITE ? SC_WRITE : SC_READ), sip, MSGS_ON);	return (rw < 0 ? 0 : rw);}/* * Internal interface to the disk command set * * Returns the character count read (or 1 if count==0) for success, * returns 0 for failure, or -1 for severe unretryable failure. */static intsdcmd(cmd, sip, errprint)	short cmd;	register struct saioreq *sip;	int errprint;{	register struct sdparam *sdp;	register struct host_saioreq *h_sip;	/* Sip for host adapter */	register char *buf;	struct scsi_cdb cdb, scdb;	struct scsi_scb scb, sscb;	int retry = 0;	int trycount = 16;	int r, i, cc, dir;	int sense_key;	DPRINTF("sdcmd:\n");	sdp = (struct sdparam *)sip->si_devdata;	h_sip = &sdp->h_sip;			/* Host adapter block */	h_sip->unit = sdp->sd_target;	cc = ROUNDUP(sip->si_cc);	buf = BUF;	/* Set up cdb */	bzero((char *) &cdb, CDB_GROUP1);	bzero((char *) &scb, sizeof scb);	cdb.cmd = cmd;	cdb.lun = sdp->sd_unit;	sip->si_bn += sip->si_cyloff;	/* Some fields in the cdb are command specific */	switch (cmd) {	case SC_READ:		DPRINTF("sdcmd: read\n");		h_sip->dma_dir = SC_RECV_DATA;		goto SDCMD_RD;	case SC_WRITE:		DPRINTF("sdcmd: write\n");		h_sip->dma_dir = SC_SEND_DATA;		if (sip->si_ma < DVMA_BASE) {			DPRINTF("sdcmd: write bcopy\n");			bcopy(sip->si_ma, BUF, sip->si_cc);		}SDCMD_RD:		if (sip->si_ma >= DVMA_BASE) {			DPRINTF("sdcmd: DVMA write\n");			buf = sip->si_ma;		}		FORMG0ADDR(&cdb, sip->si_bn);		FORMG0COUNT(&cdb, (cc / SECSIZE));		break;	case SC_INQUIRY:		EPRINTF("sdcmd: inquiry\n");		h_sip->dma_dir = SC_RECV_DATA;		sip->si_cc = cc = sizeof(struct scsi_inquiry_data);		FORMG0COUNT(&cdb, cc);		bzero((char *)h_sip->ma, cc);		break;	case SC_TEST_UNIT_READY:		DPRINTF("sdcmd: test unit ready\n");		trycount = 4;		h_sip->dma_dir = SC_NO_DATA;		cc = 0;		break;	case SC_START:		DPRINTF("sdcmd: start\n");		trycount = 2;		h_sip->dma_dir = SC_NO_DATA;		FORMG0COUNT(&cdb, 1);		break;	default:		if (!errprint)			SC_ERROR1("sd: unknown command (0x%x)\n", cdb.cmd);		return (0);	}	/* Run command and process errors. */	while (retry++ < trycount) {		h_sip->cc = cc;		h_sip->ma = buf;		r = (*h_sip->doit)(&cdb, &scb, h_sip);		DPRINTF2("sdcmd: r= 0x%x (0x%x)\n", cc, r);		/* Major SCSI bus error */		if (r < 0) {			EPRINTF("sdcmd: SCSI bus error\n");			return (r);		}		/* Disk busy - delay 2 Sec. */		if (scb.busy) {			EPRINTF("sdcmd: busy\n");			DELAY(2000000);			continue;		}		/* Error, get sense data. */		if (scb.chk) {			EPRINTF("sdcmd: check condition\n");			bzero((char *) &scdb, CDB_GROUP0);			bzero((char *) &sscb, sizeof scb);			scdb.cmd = SC_REQUEST_SENSE;			scdb.lun = sdp->sd_unit;			h_sip->cc = sizeof(struct scsi_sense);			FORMG0COUNT(&scdb, h_sip->cc);			h_sip->ma = STSBUF;			dir = h_sip->dma_dir;			h_sip->dma_dir = SC_RECV_DATA;			i = (*h_sip->doit)(&scdb, &sscb, h_sip);			h_sip->dma_dir = dir;			sense_key = sd_pr_sense((u_char *)h_sip->ma, i, errprint);			if (sense_key == SC_RECOVERABLE_ERROR) {				goto SDCMD_EXIT;			}			continue;		}		/* Return count should match */		if (r < cc) {			EPRINTF("sd: short transfer");			if (!errprint)				SC_ERROR1("sd: short transfer (0x%x)\n", r);			continue;		}		/* Copy from buffer */SDCMD_EXIT:		if (cmd == SC_READ  &&  sip->si_ma < DVMA_BASE) {			DPRINTF("sdcmd: read bcopy\n");			bcopy(BUF, sip->si_ma, sip->si_cc);		}		return (r ? r : 1);	/* Returns count */	}	if (!errprint)		SC_ERROR1("sd: %d retries\n", trycount); /* Unlikely */	return (0);}#ifndef BOOTBLOCKstatic u_char sd_adaptec_keys[] = {	0, 4, 4, 4,  2, 4, 4, 4,	/* 0x00-0x07 */	4, 4, 4, 4,  4, 4, 4, 4,	/* 0x08-0x0f */	3, 3, 3, 3,  3, 3, 3, 1,	/* 0x10-0x17 */	1, 1, 5, 5,  1, 1, 1, 1,	/* 0x18-0x1f */	5, 5, 5, 5,  5, 5, 5, 5,	/* 0x20-0x27 */	6, 6, 6, 6,  6, 6, 6, 6,	/* 0x28-0x30 */};#define MAX_ADAPTEC_KEYS \	(sizeof(sd_adaptec_keys))#endif		BOOTBLOCK#ifdef	SDDEBUGstatic char *sd_key_error_str[] = SENSE_KEY_INFO;#define MAX_KEY_ERROR_STR \	(sizeof(sd_key_error_str)/sizeof(sd_key_error_str[0]))#endif	SDDEBUG/* * Print out sense info. */static intsd_pr_sense(cp, len, errprint)	u_char *cp;	int len;	int errprint;{	register struct scsi_sense *ss;	register struct scsi_ext_sense *ses;	int sense_key;	DPRINTF("sd_pr_sense:\n");	ses = (struct scsi_ext_sense *) cp;	ss = (struct scsi_sense *) cp;#ifdef	lint	len = len;#endif	lint#ifdef SDDEBUG	if (sd_debug > 2) {		printf("sd: error:");		while (--len >= 0) {			printf(" %x", *cp++);		}		printf("\n");	}#endif	SDDEBUG	if (ss->code <= 6) {		/*		 * Synthesize sense key for extended sense. Note,		 * Without the decode table, we don't know what's		 * so we'll say we don't know.		 */#ifdef		BOOTBLOCK		sense_key = SC_NO_SENSE;#else		BOOTBLOCK		if (ss->code < MAX_ADAPTEC_KEYS) {			sense_key = sd_adaptec_keys[ss->code];		}#endif		BOOTBLOCK		if (errprint)			return (sense_key);		SC_ERROR1("sd: sense key = %x", sense_key);#ifdef	 	SDDEBUG		SC_ERROR1(" (%s)", sd_key_error_str[ses->key]);#endif	 	SDDEBUG		SC_ERROR1("  error = %x  ", ss->code);		if (ss->adr_val) {			SC_ERROR1("- block %d", (ss->high_addr << 16) |			    (ss->mid_addr << 8) | ss->low_addr);		}	/* Sense class 7: the standardized one */	} else {		/*		 * For CCS disks, it tells us the problem.		 */		sense_key = ses->key;		if (errprint)			return (sense_key);		SC_ERROR1("sd: sense key = %x", ses->key);#ifdef	 	SDDEBUG		SC_ERROR1(" (%s)", sd_key_error_str[ses->key]);#endif		SDDEBUG		SC_ERROR1("  error = %x  ", ses->error_code);		if (ses->adr_val) {			SC_ERROR1("- block %d", (ses->info_1 << 24) |			    (ses->info_2 << 16) | (ses->info_3 << 8) |			    ses->info_4);		}	}	SC_ERROR("\n");	return (sense_key);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -