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

📄 scsi_resource.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 2 页
字号:
#ident	"@(#)scsi_resource.c 1.1 92/07/30 SMI"/* * Copyright (c) 1988, 1989, 1990 Sun Microsystems, Inc. */#define	DPRINTF	if (scsi_options & SCSI_DEBUG_LIB) printf/* *	Generic Resource Allocation Routines */#include <scsi/scsi.h>struct scsi_pkt *scsi_resalloc(ap, cmdlen, statuslen, dmatoken, callback)struct scsi_address *ap;int cmdlen, statuslen;opaque_t dmatoken;int (*callback)();{	register struct scsi_pkt *pktp;	register struct scsi_transport *tranp;	/*	 * The first part of the address points to	 * an array of transport function points	 */	tranp = (struct scsi_transport *) ap->a_cookie;	pktp = (*tranp->tran_pktalloc)(ap, cmdlen, statuslen, callback);	if (pktp == (struct scsi_pkt *) 0) {		if (callback == SLEEP_FUNC) {			panic("scsi_resalloc: No packet after sleep");			/*NOTREACHED*/		}	} else if (dmatoken != (opaque_t) 0) {		if ((*tranp->tran_dmaget)(pktp, dmatoken, callback) == NULL) {			if (callback == SLEEP_FUNC) {				panic("scsi_resalloc: No dma after sleep");				/*NOTREACHED*/			}			/*			 * if we didn't get dma resources in this function,			 * free up the packet resources.			 */			(*tranp->tran_pktfree)(pktp);			pktp = (struct scsi_pkt *) 0;		}	}	return (pktp);}struct scsi_pkt *scsi_pktalloc(ap, cmdlen, statuslen, callback)struct scsi_address *ap;int cmdlen, statuslen;int (*callback)();{	struct scsi_transport *tranp = (struct scsi_transport *) ap->a_cookie;	return ((*tranp->tran_pktalloc)(ap, cmdlen, statuslen, callback));}struct scsi_pkt *scsi_dmaget(pkt, dmatoken, callback)struct scsi_pkt *pkt;opaque_t dmatoken;int (*callback)();{	struct scsi_transport *tranp;	if (dmatoken == (opaque_t) NULL) {		return ((struct scsi_pkt *) NULL);	}	tranp = (struct scsi_transport *) pkt->pkt_address.a_cookie;	return ((*tranp->tran_dmaget)(pkt, dmatoken, callback));}/* *	Generic Resource Deallocation Routines */voidscsi_dmafree(pkt)struct scsi_pkt *pkt;{	struct scsi_transport *tranp =		(struct scsi_transport *) pkt->pkt_address.a_cookie;	(*tranp->tran_dmafree)(pkt);}voidscsi_resfree(pkt)struct scsi_pkt *pkt;{	struct scsi_transport *tranp =		(struct scsi_transport *) pkt->pkt_address.a_cookie;	/*	 * Free DMA resources if any need to be freed.	 */	(*tranp->tran_dmafree)(pkt);	/*	 * free packet.	 */	(*tranp->tran_pktfree)(pkt);}/* *	Standard Resource Allocation/Deallocation Routines *//* * When Host Adapters don't want to supply their own resource allocation * routines, and they can live with certain assumptions about DVMA, * these routines are stuffed into their scsi_transport structures * which they then export to the library. *//* * Local resource management data && defines */#if	defined(sun4c) || defined(sun4m)#define	DMA	dvmamap#else	defined(sun4c) || defined(sun4m)#define	DMA	mb_hd.mh_map#endif	defined(sun4c) || defined(sun4m)int scsi_ncmds, scsi_spl;static int sfield();static int scsi_cmdwake = 0;static struct scsi_cmd *scsibase;/* * This code shamelessly stolen from mb_machdep.c. * Full attribution and credit to John Pope. * * Drivers queue function pointers here when they have to wait * for resources. Subsequent calls from the same driver that are * forced to wait need not queue up again, as the function pointed * to will run the driver's internal queues until done or space runs * out again. * * The difficulty is that we may block on two different things here: * packet allocation itself, and DVMA mapping resources associated with * the packet. If we cannot get a packet, no problem. If we can get * or have already gotten a packet, but cannot get DVMA mapping resources, * things get a bit sticky. The DVMA mapping callback routine expects * us to return DVMA_RUNOUT if DVMA allocation fails again- but *our* * callback to the target driver may return failure not due to DVMA * allocation failure (again) but packet allocation failure instead. * In either case, we assume that *we* have appropriately re-queued * the caller, but we have to know what kind of allocation failure * it was in order to appropriately notify the sentinel in the DVMA * map allocation callback code. * * In other words, the SCSA specification screwed this up. Oh well. * * The magic number for SCQLEN was picked because: * *	a) That seems a reasonable limit for the number of separate and *	   distinct target drivers that can latch up waiting for resources. * *	b) it is a power of two, to make the cycle easier. * */#define	SCQLEN		0x8#define	SCQLENMASK	0x7struct scq {	u_int	qlen;	u_int	qstore;	u_int	qretrv;	u_int	ncalls;	u_int	incallback;	func_t funcp[SCQLEN];};static struct scq scpq, scdq;static void scq_store();		/* store element */static func_t scq_retrieve();		/* retrieve element *//* * resource initializer */voidscsi_rinit(){	if (scsibase != (struct scsi_cmd *) 0) {		return;	}	/*	 * start with a minimum of twice the per_dev requirement	 */	scsi_addcmds(scsi_ncmds_per_dev << 1);	if (scsibase == (struct scsi_cmd *) 0) {		panic("No space for scsi command structures");		/*NOTREACHED*/	}	scpq.qretrv = scdq.qretrv = SCQLEN-1;	scpq.incallback = scdq.incallback = 0;}voidscsi_addcmds(ncmds)int ncmds;{	register s, i;	register struct scsi_cmd *sp;	sp = (struct scsi_cmd *)	    kmem_zalloc((u_int) sizeof (struct scsi_cmd) * ncmds);	if (sp == (struct scsi_cmd *) 0) {		return;	}	scsi_ncmds += ncmds;	s = splr(scsi_spl);	for (i = 0; i < ncmds-1; i++)		sp[i].cmd_pkt.pkt_ha_private = (opaque_t) &sp[i+1];	sp[ncmds-1].cmd_pkt.pkt_ha_private = (opaque_t) scsibase;	scsibase = sp;	(void) splx(s);}/* * pktalloc */struct scsi_pkt *scsi_std_pktalloc(ap, cmdlen, statuslen, callback)struct scsi_address *ap;int cmdlen, statuslen;int (*callback)();{	register struct scsi_cmd *cmd;	register s;	register caddr_t cdbp, scbp;	cdbp = scbp = (caddr_t) 0;	s = splr(scsi_spl);	cmd = scsibase;	for (;;) {		if (cmd == (struct scsi_cmd *) 0) {			if (callback == SLEEP_FUNC) {				if (servicing_interrupt()) {					panic("scsi_std_pktalloc");					/*NOTREACHED*/				}				scsi_cmdwake++;				(void) sleep((caddr_t)&scsibase, PRIBIO);				cmd = scsibase;				/*				 * around the top again...				 */				continue;			} else if (callback != NULL_FUNC) {				scq_store(&scpq, callback);			}			break;		}		if (cmdlen > CDB_SIZE) {			cdbp = kmem_zalloc((unsigned) cmdlen);			if (cdbp == (caddr_t) 0) {				cmd = (struct scsi_cmd *) 0;				continue;			}		}		if (statuslen > STATUS_SIZE) {			scbp = kmem_zalloc((unsigned) statuslen);			if (scbp == (caddr_t) 0) {				if (cdbp != (caddr_t) 0) {					(void) kmem_free_intr (cdbp,						(unsigned) cmdlen);				}				cmd = (struct scsi_cmd *) 0;				continue;			}		}		scsibase = (struct scsi_cmd *) cmd->cmd_pkt.pkt_ha_private;		break;	}	/*	 * We can safely drop priority now	 */	(void) splx(s);	if (cmd != (struct scsi_cmd *) 0) {		bzero ((caddr_t)cmd, sizeof (struct scsi_cmd));		if (cdbp != (caddr_t) 0) {			cmd->cmd_pkt.pkt_cdbp = (opaque_t) cdbp;			cmd->cmd_flags |= CFLAG_CDBEXTERN;		} else {			cmd->cmd_pkt.pkt_cdbp = (opaque_t) &cmd->cmd_cdb[0];		}		if (scbp != (caddr_t) 0) {			cmd->cmd_pkt.pkt_scbp = (opaque_t) scbp;			cmd->cmd_flags |= CFLAG_SCBEXTERN;		} else {			cmd->cmd_pkt.pkt_scbp = (opaque_t) &cmd->cmd_scb[0];		}		cmd->cmd_cdblen = cmdlen;		cmd->cmd_scblen = statuslen;		cmd->cmd_pkt.pkt_address = *ap;	}	return ((struct scsi_pkt *) cmd);}

⌨️ 快捷键说明

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