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

📄 sd.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* *	System Crash Dump routine */#define	NDUMP_RETRIES	5intsddump(dev, addr, blkno, nblk)dev_t dev;caddr_t addr;daddr_t blkno;int nblk;{	struct dk_map *lp;	struct scsi_device *devp;	struct scsi_disk *un;	struct scsi_pkt *pkt;	register s, i, pflag;	int err;	if (SDUNIT(dev) >= SD_MAXUNIT) {		return (ENXIO);	} else if (!(devp = sdunits[SDUNIT(dev)]) || !devp->sd_present ||	    !(un = UPTR) || !un->un_gvalid) {		return (ENXIO);	}	lp = &un->un_map[SDPART(dev)];	if (blkno+nblk > lp->dkl_nblk) {		return (EINVAL);	}	/*	 * The first time through, reset the specific target device.	 * Do a REQUEST SENSE if required.	 */	pflag = FLAG_NOINTR|FLAG_NODISCON;	if (un->un_dp->options & SD_NOPARITY)		pflag |= FLAG_NOPARITY;	un->un_rqs->pkt_flags |= pflag;	s = splr(sdpri);	if (un->un_state != SD_STATE_DUMPING) {		New_state(un, SD_STATE_DUMPING);		/*		 * Abort any active commands for this target		 */		(void) scsi_abort(ROUTE, (struct scsi_pkt *) 0);		/*		 * Reset the bus. I'd like to not have to do this,		 * but this is the safest thing to do...		 */		if (scsi_reset(ROUTE, RESET_ALL) == 0) {			(void) splx(s);			return (EIO);		}		DELAY(2*1000000);		for (i = 0; i < NDUMP_RETRIES; i++) {			if (scsi_poll(un->un_rqs)) {				(void) splx(s);				return (EIO);			}			if (SCBP_C(un->un_rqs) == STATUS_GOOD)				break;			DELAY(10000);		}	}	(void) splx(s);	blkno += (lp->dkl_cylno * un->un_g.dkg_nhead * un->un_g.dkg_nsect);	/*	 * It should be safe to call the allocator here without	 * worrying about being locked for DVMA mapping because	 * the address we're passed is already a DVMA mapping	 */	bzero((caddr_t) un->un_sbufp, sizeof (struct buf));	un->un_sbufp->b_un.b_addr = addr;	un->un_sbufp->b_bcount = nblk << DEV_BSHIFT;	pkt = scsi_resalloc(ROUTE, CDB_GROUP1, 1,	    (opaque_t) un->un_sbufp, NULL_FUNC);	if (pkt == (struct scsi_pkt *) 0) {		sdlog(devp, LOG_CRIT, "no resources for dumping");		return (EIO);	}	if (blkno >= (1<<20)) {		makecom_g1(pkt, devp, pflag, SCMD_WRITE_G1, (int) blkno, nblk);	} else {		makecom_g0(pkt, devp, pflag, SCMD_WRITE, (int) blkno, nblk);	}	s = splr(sdpri);	for (err = EIO, i = 0; i < NDUMP_RETRIES && err == EIO; i++) {		if (scsi_poll(pkt)) {			if (scsi_reset(ROUTE, RESET_ALL) == 0) {				break;			}		}		switch (SCBP_C(pkt)) {		case STATUS_GOOD:			err = 0;			break;		case STATUS_BUSY:			DELAY(5*1000000);			break;		case STATUS_CHECK:			/*			 * Hope this clears it up...			 */			(void) scsi_poll(un->un_rqs);			break;		default:			break;		}	}	(void) splx(s);	scsi_resfree(pkt);	return (err);}/* * This routine implements the ioctl calls.  It is called * from the device switch at normal priority. *//*ARGSUSED3*/sdioctl(dev, cmd, data, flag)dev_t dev;int cmd;caddr_t data;int flag;{	extern char *strcpy();	register struct scsi_device *devp;	register struct scsi_disk *un;	struct dk_map *lp;	struct dk_info *info;	struct dk_conf *conf;	struct dk_diag *diag;	int unit, i, s, part;	if ((unit = SDUNIT(dev)) >= SD_MAXUNIT || !(devp = sdunits[unit]) ||	    !(devp->sd_present) || !(un = UPTR) ||	    (un->un_state == SD_STATE_DETACHING)) {		return (ENXIO);	}	part = SDPART(dev);	lp = &un->un_map[part];	switch (cmd) {	case DKIOCWCHK:	{		int pbit = (1<<part);		if (!suser()) {			return (u.u_error);		} else if (lp->dkl_nblk == 0) {			return (ENXIO);		}		if (un->un_dp->options & SD_NOVERIFY) {			return (ENOTTY);		}		i = (*((int *) data));		if (i) {			s = splr(sdpri);			(*((int *) data)) = ((un->un_wchkmap & pbit) != 0);			un->un_wchkmap |= pbit;			/* VM HACK!!! */#ifdef	VAC			{#ifdef	sun4#include <machine/cpu.h>				extern int cpu, vac, nopagereclaim;				/* VM HACK!!! */				if (cpu == CPU_SUN4_260 && vac) {					nopagereclaim = 1;				}#endif	sun4#ifdef	sun3#include <machine/cpu.h>				extern int cpu, vac, nopagereclaim;				if (cpu == CPU_SUN3_260 && vac) {					nopagereclaim = 1;				}#endif	sun4			}#endif	VAC			(void) splx(s);			printf("sd%d%c: write check enabled\n",			    unit, 'a' + part);		} else  {			s = splr(sdpri);			(*((int *) data)) = ((un->un_wchkmap & pbit) != 0);			un->un_wchkmap &= ~pbit;			(void) splx(s);			printf("sd%d%c: write check disabled\n",			    unit, 'a' + part);		}		return (0);	}	case DKIOCINFO:	/*	 * Return info concerning the controller.	 */		info = (struct dk_info *)data;#ifdef	OPENPROMS		info->dki_ctlr =			(int) devp->sd_dev->devi_parent->devi_reg->reg_addr;		info->dki_unit = (Tgt(devp)<<3)|Lun(devp);#else		info->dki_ctlr = getdevaddr(devp->sd_dev->md_mc->mc_addr);		info->dki_unit = devp->sd_dev->md_slave;#endif		switch (un->un_dp->ctype) {		case CTYPE_MD21:			info->dki_ctype = DKC_MD21;			break;#ifdef	ADAPTEC		case CTYPE_ACB4000:			info->dki_ctype = DKC_ACB4000;			break;#endif	/* ADAPTEC */		default:			info->dki_ctype = DKC_SCSI_CCS;			break;		}		info->dki_flags = DKI_FMTVOL;		return (0);	case DKIOCGGEOM:	/*	 * Return the geometry of the specified unit.	 */		*(struct dk_geom *)data = un->un_g;		return (0);	/*	 * Set the geometry of the specified unit.	 */	case DKIOCSGEOM:		un->un_g = *(struct dk_geom *)data;		return (0);	case DKIOCGPART:	/*	 * Return the map for the specified logical partition.	 * This has been made obsolete by the get all partitions	 * command.	 */		*(struct dk_map *)data = *lp;		return (0);	case DKIOCSPART:	/*	 * Set the map for the specified logical partition.	 * This has been made obsolete by the set all partitions	 * command.  We raise the priority just to make sure	 * an interrupt doesn't come in while the map is	 * half updated.	 */		*lp = *(struct dk_map *)data;		return (0);	/*	 * Return configuration info	 */	case DKIOCGCONF:		conf = (struct dk_conf *)data;		switch (un->un_dp->ctype) {		case CTYPE_MD21:			conf->dkc_ctype = DKC_MD21;			break;#ifdef	ADAPTEC		case CTYPE_ACB4000:			conf->dkc_ctype = DKC_ACB4000;			break;#endif	/* ADAPTEC */		default:			conf->dkc_ctype = DKC_MD21;			break;		}		conf->dkc_dname[0] = 's';		conf->dkc_dname[1] = 'd';		conf->dkc_dname[2] = 0;		conf->dkc_flags = DKI_FMTVOL;#ifndef	OPENPROMS		conf->dkc_cnum = devp->sd_dev->md_mc->mc_ctlr;		conf->dkc_addr = getdevaddr(devp->sd_dev->md_mc->mc_addr);		conf->dkc_space = devp->sd_dev->md_mc->mc_space;		conf->dkc_prio = devp->sd_dev->md_mc->mc_intpri;		if (devp->sd_dev->md_mc->mc_intr)			conf->dkc_vec = devp->sd_dev->md_mc->mc_intr->v_vec;		else			conf->dkc_vec = 0;		(void) strncpy(conf->dkc_cname,				devp->sd_dev->md_driver->mdr_cname, DK_DEVLEN);		conf->dkc_unit = devp->sd_dev->md_unit;		conf->dkc_slave = devp->sd_dev->md_slave;#else	OPENPROMS		conf->dkc_cnum = devp->sd_dev->devi_parent->devi_unit;		conf->dkc_addr = (int)			devp->sd_dev->devi_parent->devi_reg->reg_addr;		conf->dkc_space =			devp->sd_dev->devi_parent->devi_reg->reg_bustype;		conf->dkc_prio =			ipltospl(devp->sd_dev->devi_parent->devi_intr->int_pri);		(void) strcpy(conf->dkc_cname, CNAME);		conf->dkc_cname[3] = CUNIT;		conf->dkc_unit = unit;		conf->dkc_slave = (Tgt(devp)<<3)|Lun(devp);#endif	OPENPROMS		return (0);	/*	 * Return the map for all logical partitions.	 */	case DKIOCGAPART:		for (i = 0; i < NDKMAP; i++)			((struct dk_map *)data)[i] = un->un_map[i];		return (0);	/*	 * Set the map for all logical partitions.  We raise	 * the priority just to make sure an interrupt doesn't	 * come in while the map is half updated.	 */	case DKIOCSAPART:		s = splr(sdpri);		for (i = 0; i < NDKMAP; i++)			un->un_map[i] = ((struct dk_map *)data)[i];		(void) splx(s);		return (0);	/*	 * Get error status from last command.	 */	case DKIOCGDIAG:		diag = (struct dk_diag *) data;		diag->dkd_errcmd  = un->un_last_cmd;		diag->dkd_errsect = un->un_err_blkno;		diag->dkd_errno = un->un_status;		diag->dkd_severe = un->un_err_severe;		un->un_last_cmd   = 0;	/* Reset */		un->un_err_blkno  = 0;		un->un_err_code   = 0;		un->un_err_severe = 0;		return (0);	/*	 * Run a generic command.	 */	case DKIOCSCMD:		return (sd_maptouscsi(dev, data));	/*	 * Run a geneeric ucsi.h command.	 */	case USCSICMD:		return (sdioctl_cmd(dev, data, 0));	/*	 * Handle unknown ioctls here.	 */	default:		return (ENOTTY);	}}static intsd_maptouscsi(dev, data)dev_t dev;caddr_t data;{	register struct scsi_device *devp;	struct dk_cmd *dcom;	struct uscsi_cmd scmd, *ucom = &scmd;	char cmdblk[CDB_SIZE], *cdb = cmdblk;	u_short cmd;	auto daddr_t blkno = 0;	int count;	int g1 = 0;	bzero(cdb, CDB_SIZE);	devp = sdunits[SDUNIT(dev)];	dcom = (struct dk_cmd *)data;	count = dcom->dkc_buflen;	blkno = (daddr_t)dcom->dkc_blkno;	cmd = dcom->dkc_cmd;	switch (dcom->dkc_cmd) {	case SCMD_READ:	case SCMD_WRITE:	{		DPRINTF_IOCTL(devp, "special %s",		    (dcom->dkc_cmd == SCMD_READ) ? "read" : "write");		if (dcom->dkc_buflen & (SECSIZE-1))			return (EINVAL);		count = (count + (SECSIZE - 1)) >> SECDIV;		if (dcom->dkc_cmd == SCMD_READ)			ucom->uscsi_flags = USCSI_READ;		else			ucom->uscsi_flags = USCSI_WRITE;		if (blkno >= (2<<20) || count > 0xff) {			cmd |= SCMD_GROUP1;			g1 = 1;		}		break;	}	case SCMD_MODE_SELECT:	{		DPRINTF_IOCTL(devp, "mode select; sp=%d",		    (blkno & 0x80)? 1 : 0);		if (blkno & 0x80) {			/*			 * The 'save parameters' bit			 * is in the first bit of the 'tag',			 * or bit #16 of a nominal 21 bit			 * block address. Unfortunately, 4.0			 * format(8) sets bit #7 to indicate			 * that these are saveable parameters.			 */			blkno = 0x10000;		} else			blkno = 0;		ucom->uscsi_flags = USCSI_WRITE;		break;	}	case SCMD_MODE_SENSE:	{		DPRINTF_IOCTL(devp, "mode sense: pcf=0x%x, page 0x%x",		    blkno>>5, blkno&0x1f);		blkno <<= 8;		ucom->uscsi_flags = USCSI_READ;		break;	}	case SCMD_READ_DEFECT_LIST:	{		char descriptor;		/*		 * yet another compatibility deal with 4.0-		 * we have to pick up the defect list descriptor		 * from the user's buffer itself. Also, the		 * Defect List Format stuff will end up in what		 * is the most significant byte of a 32 byte		 * block address.		 */		struct scsi_defect_list *sd =		    (struct scsi_defect_list *) dcom->dkc_bufaddr;		g1 = 1;		u.u_error = copyin((caddr_t)&sd->descriptor, &descriptor, 1);		if (u.u_error)			return (u.u_error);		DPRINTF_IOCTL(devp, "read_defect_list: descrip %x",		    descriptor);		blkno = descriptor & 0xff;		blkno <<= 24;		ucom->uscsi_flags = USCSI_READ;		break;	}	case SCMD_REASSIGN_BLOCK:	{		/*		 * Compatibility with 4.0. The block to be		 * reassigned is in the block field. We		 * have had to make a little buffer for		 * it (in the correct format) and we will		 * then put the block into that little buffer		 */		DPRINTF_IOCTL(devp, "reassign block %d, count %d (== 8?)",		    blkno, count);		if (devp->sd_inq->inq_rdf < RDF_CCS) {			/* reassign block unlikely for non-CCS device */			/* XXX SHOULDN'T WE JUST LET IT BOUNCE THE COMMAND? */			return (EINVAL);		} else if (dcom->dkc_buflen) {			return (EINVAL);		}		ucom->uscsi_flags = USCSI_WRITE;		/*		 * Turn the cdb into a Group 1 command, so that the		 * block number does not get truncated to 20 bits.		 * This is a little wierd, since no such command		 * exists for reassign, but we perform the		 * inverse transformation later, so we're ok.		 */		cmd |= SCMD_GROUP1;		g1 = 1;		break;	}	case SCMD_FORMAT:	{		DPRINTF_IOCTL(devp, "format: blkno_bits 0x%x", blkno);		if (blkno & 0x80000000) {			unsigned int	tmp;			/*			 * interleave			 */			tmp = blkno;			count = tmp&0xff;			blkno = (tmp>>8)&0xff;			/*			 * data pattern			 */			blkno |= (((tmp>>16)&0xff)<<8);			/*			 * format parameter bits			 */			blkno |= (((tmp>>24)&0x1f)<<16);		} else {			blkno = (FPB_DATA|FPB_CMPLT|FPB_BFI)<<16;			count = 1; /* interleave */		}		ucom->uscsi_flags = USCSI_WRITE;		break;	}	case SCMD_TEST_UNIT_READY:	{		if (dcom->dkc_buflen)			return (EINVAL);		ucom->uscsi_flags = USCSI_WRITE;		break;	}	default:		return (EINVAL);	}	if (DEBUGGING_ALL) {		sdprintf(devp, "sd_maptouscsi cmd= %x  blk= %x buflen= 0x%x",		    dcom->dkc_cmd, dcom->dkc_blkno, dcom->dkc_buflen);		if (ucom->uscsi_flags == USCSI_WRITE && dcom->dkc_buflen) {			auto u_int i, amt = min(64, dcom->dkc_buflen);			char buf [64];			if (copyin(dcom->dkc_bufaddr, buf, amt)) {				return (EFAULT);			}			printf("\tuser's buf:");			for (i = 0; i < amt; i++) {				printf(" 0x%x", buf[i]&0xff);			}			printf("\n");		}	}	cmdblk[0] = (u_char)cmd;	ucom->uscsi_cdb = cdb;	if (g1) {		FORMG1ADDR((union scsi_cdb *)cmdblk, blkno);

⌨️ 快捷键说明

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