📄 scsi_resource.c
字号:
#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 + -