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

📄 esp.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#endif	ESP_TEST_FAST_SYNC			} else {				ep->esp_conf2 = esp->e_espconf2;				esp->e_type = ESP236;				IPRINTF("found ESP236\n");			}			ep->esp_conf3 = espconf3;		} else {			ep->esp_conf2 = esp->e_espconf2;			esp->e_type = ESP100A;		}	} else {		esp->e_type = ESP100;	}	/*	 * check for differential scsi bus property	 */	if (getprop(dev->devi_nodeid, prop_diff, -1) != -1) {		IPRINTF("differential scsi bus\n");		esp->e_differential++;	}	esp_internal_reset(esp, ESP_RESET_ALL);	/*	 * Whew! Now make ourselves known to the rest of the SCSI world...	 */	scsi_config(&esp->e_tran, dev);#ifdef	GASP	if (dev->devi_unit == 0 && nesp > 1) {		for (i = 1; i < nesp; i++) {			dev = dev->devi_next;			(void) esp_attach(dev);		}	}#endif	/* GASP */	return (0);}#else	/* OPENPROMS */static int esp_probe(), esp_slave(), esp_attach();struct mb_driver espdriver = {	esp_probe, esp_slave, esp_attach, 0, 0, esp_poll,	ESP_SIZE, "scsibus", 0, "esp", 0, MDR_BIODMA};static intesp_probe(reg, ctlr)caddr_t reg;int ctlr;{	static char first_time = 1;	register struct dmaga *dmar;	register struct espreg *ep;	register struct esp *esp, *nsp;	u_long dma_base, ticks;	u_char clock_conv;	long lptr;	/*	 * These shorthand defines just for this routine	 */#define	DNAME	espdriver.mdr_cname#define	DUNIT	ctlr	switch (cpu) {#ifdef	sun4	case CPU_SUN4_330:		dma_base = (u_long) DVMA;		clock_conv = CLOCK_25MHZ;		dmar = (struct dmaga *) (((long) reg) + STINGRAY_DMA_OFFSET);		break;#endif	/* sun4 */#ifdef	sun3x	case CPU_SUN3X_80:		dma_base = (u_long) DVMA;		clock_conv = CLOCK_20MHZ;		dmar = (struct dmaga *) (((long) reg) + HYDRA_DMA_OFFSET);		break;#endif	/* sun3x */	default:		return (0);	}	if ((peekl((long *)&(dmar->dmaga_csr), (long *)&(lptr))) == -1) {		return (0);	}	ep = (struct espreg *) reg;	if ((peekc((char *)&(ep->esp_xcnt_lo))) == -1) {		return (0);	}	esp  = (struct esp *) kmem_zalloc((unsigned) (sizeof (struct esp)));	if (esp != (struct esp *) 0) {		esp->e_cmdarea = (u_char *) IOPBALLOC(FIFOSIZE);	}	if (esp == (struct esp *) 0 || esp->e_cmdarea == (u_char *) 0) {		printf("esp%d: no space for %s\n", DUNIT, (esp->e_cmdarea) ?		    "cmd areas" : "data structures");		if (esp) {			(void) kmem_free((caddr_t)esp, (sizeof (struct esp)));		}		return (0);	}	esp->e_next = (struct esp *)0;	esp->e_unit = DUNIT;	/*	 * Establish initial softc values	 */	if (esp_softc == (struct esp *) 0) {		esp_softc = esp;	} else {		for (nsp = esp_softc; nsp->e_next != (struct esp *) 0;							nsp = nsp->e_next);		nsp->e_next = esp;	}	esp->e_dev = &espdriver;	esp->e_espconf = DEFAULT_HOSTID;	if (scsi_options & SCSI_OPTIONS_PARITY)		esp->e_espconf |= ESP_CONF_PAREN;	esp->e_espconf |= (espconf & ~ESP_CONF_BUSID);	esp->e_burstsizes = 0;	esp->e_clock_conv = clock_conv;	esp->e_clock_cycle = FIVE_MEG * clock_conv;	ticks = ESP_CLOCK_TICK(esp);	esp->e_stval = ESP_CLOCK_TIMEOUT(ticks);	esp->e_backoff = 0;#ifdef	ESP_TEST_FAST_SYNC	IPRINTF5("%d mhz, clock_conv %d, clock_cycle %d, ticks %d, stval %d\n",		FIVE_MEG * clock_conv, esp->e_clock_conv, esp->e_clock_cycle,		ticks, esp->e_stval);#endif	ESP_TEST_FAST_SYNC	esp->e_reg = ep;	esp->e_dma = dmar;	/*	 * Initialize state of DMA gate array.	 */	dmar->dmaga_csr = dmar->dmaga_csr & ~DMAGA_WRITE;	esp->e_dma_base = dma_base;	esp->e_tran.tran_start		= esp_start;	esp->e_tran.tran_abort		= esp_abort;	esp->e_tran.tran_reset		= esp_reset;	esp->e_tran.tran_getcap		= esp_getcap;	esp->e_tran.tran_setcap		= esp_setcap;	esp->e_tran.tran_pktalloc	= scsi_std_pktalloc;	esp->e_tran.tran_dmaget		= scsi_std_dmaget;	esp->e_tran.tran_pktfree	= scsi_std_pktfree;	esp->e_tran.tran_dmafree	= scsi_std_dmafree;	esp->e_last_slot = esp->e_cur_slot = UNDEFINED;	if (first_time) {		first_time = 0;		timeout(esp_watch, (caddr_t) 0, hz);	}	esp_internal_reset(esp, ESP_RESET_ALL);#undef	DNAME#undef	DUNIT	return (ESP_SIZE);}/*ARGSUSED*/static intesp_slave(md, reg)struct mb_device *md;caddr_t reg;{	struct esp *esp;	register struct espreg *ep;	register int i;	for (esp = esp_softc, i = 0; esp->e_next != (struct esp *) 0,		i < md->md_ctlr; esp = esp->e_next, i++);	ep = esp->e_reg;	ep->esp_conf2 = 0;	ep->esp_conf2 = 0xa;	esp->e_type = ESP100;	if ((ep->esp_conf2&0xf) == 0xa) {		ep->esp_conf2 = esp->e_espconf2 = espconf2;		ep->esp_conf3 = 0;		ep->esp_conf3 = 5;		if (ep->esp_conf3 == 0x5) {			ep->esp_conf3 = espconf3;			for (i = 0; i < NTARGETS; i++) {				esp->e_espconf3[i] = espconf3;			}			esp->e_type = ESP236;		} else			esp->e_type = ESP100A;	}	md->md_slave = MY_ID(esp) << 3;	return (1);}static intesp_attach(md)struct mb_device *md;{	int i;	static int esp_spl = 0;	struct esp *esp, *nsp;	for (esp = esp_softc, i = 0; esp->e_next != (struct esp *) 0,		i < md->md_ctlr; esp = esp->e_next, i++);	/*	 * Calculate max locking spl so far seen..	 */	esp->e_spl = pritospl(md->md_intpri);	esp_spl = MAX(esp_spl, esp->e_spl);	/*	 * Make sure that everyone, including us, is locking at	 * the same priority.	 */	for (nsp = esp_softc; nsp != (struct esp *) 0; nsp = nsp->e_next) {		nsp->e_tran.tran_spl = esp_spl;	}#ifdef	ESPDEBUG	/*	 * Initialize last state log.	 */	for (i = 0; i < NPHASE; i++) {		esp->e_phase[i].e_save_state = STATE_FREE;		esp->e_phase[i].e_save_stat = -1;		esp->e_phase[i].e_val1 = -1;		esp->e_phase[i].e_val2 = -1;	}	esp->e_phase_index = 0;	esp->e_xfer = 0;#endif	/* ESPDEBUG */	/*	 * Whew! Now make ourselves known to the rest of the SCSI world...	 */	scsi_config(&esp->e_tran, md);}#endif	/* OPENPROMS *//* * Interface functions * * Visible to the external world via the transport structure. *//* * esp_start - Accept commands for transport */static intesp_start(sp)register struct scsi_cmd *sp;{	register s;	register short slot;	register struct esp *esp;	esp = (struct esp *) sp->cmd_pkt.pkt_address.a_cookie;	slot =	(sp->cmd_pkt.pkt_address.a_target * NLUNS_PER_TARGET) |	    (sp->cmd_pkt.pkt_address.a_lun);	if (sp->cmd_flags & CFLAG_DMAVALID) {		u_long maxdma;		switch (DMAGA_REV(esp->e_dma)) {		default:		case DMA_REV1:		case DMA_REV2:		case ESC1_REV1:			maxdma = 1<<24;			break;		case DMA_REV3:			maxdma = 1<<30; /* be reasonable - 2gb is enuff */			break;		}		if (sp->cmd_mapseg.d_count >= maxdma) {			return (TRAN_BADPKT);		}	}	s = splr(esp->e_tran.tran_spl);	if (esp->e_slots[slot] != (struct scsi_cmd *) 0) {		/*		 * This is where we would see if this is a SCSI-2		 * multiple command target.		 */		/*		 * Else queueing error...		 */		(void) splx(s);		return (TRAN_BUSY);	}	/*	 * Else, accept the command	 */	esp->e_slots[slot] = sp;	esp->e_ncmds++;	/*	 * Reinitialize some fields that need it	 */	esp_init_cmd(sp);	/*	 * Run the command (maybe).	 */	if ((sp->cmd_pkt.pkt_flags & FLAG_NOINTR) == 0) {		/*		 * Okay- if this is command is *not* a polling command,		 * and we're not pending any polling commands, *and*		 * the state is FREE, *then* we can start this command.		 */		if (esp->e_npolling == 0 && esp->e_state == STATE_FREE) {			(void) esp_ustart(esp, slot);		}	} else {		esp_runpoll(esp, slot);	}	(void) splx(s);	return (TRAN_ACCEPT);}static intesp_abort(ap, pkt)struct scsi_address *ap;struct scsi_pkt *pkt;{	register struct esp *esp = (struct esp *) ap->a_cookie;	register struct scsi_cmd *sp = (struct scsi_cmd *) pkt;	register int s, rval;	register short slot;	/*	 * find the slot for this specific address	 */	slot =	(ap->a_target * NLUNS_PER_TARGET) | ap->a_lun;	/*	 * Take care of the easy cases first:	 *	 *   A specific command was passed as an argument (to be aborted) and	 *	 *	The command is currently active; we cannot abort now	 *	The command does not exist here.	 *	The command exists here, but hasn't been started yet.	 *	 *   No specific command was passed as an argument (abort all	 *   commands at this nexus), and	 *	 *	No commands exist for this nexus.	 *	Commands that exist here haven't been started yet.	 *	 */	s = splr(esp->e_tran.tran_spl);	if (esp->e_state != STATE_FREE && esp->e_cur_slot == slot) {		/*		 * This isn't right, but it will have to do for now.		 * If the currently active command is the one to be		 * aborted, we don't know at this level whether it		 * is safe, nor how to, queue up the ABORT OPERATION		 * message. Instead, punt, and let the target driver		 * decide whether to pull the chain on the bus.		 */		(void) splx(s);		return (FALSE);	}	if (sp == (struct scsi_cmd *) 0) {		sp = esp->e_slots[slot];	}	if (esp->e_slots[slot] == (struct scsi_cmd *) 0) {		sp = (struct scsi_cmd *) 0;	}	if (sp && sp == esp->e_slots[slot] && sp->cmd_pkt.pkt_state == 0) {		esp->e_slots[slot] = (struct scsi_cmd *) 0;		sp->cmd_pkt.pkt_reason = CMD_ABORTED;		esp->e_ncmds -= 1;		(*sp->cmd_pkt.pkt_comp)(sp);		sp = (struct scsi_cmd *) 0;	}	if (sp == (struct scsi_cmd *) 0) {		(void) splx(s);		return (TRUE);	}	/*	 * Now deal with the hard cases. We have a valid sp for the	 * single active command at this nexus (XXX later we will have	 * a list of commands to abort XXX).	 */	{		/*		 * In this case, the command is active but disconnected		 */		auto struct scsi_cmd local;		register struct scsi_cmd *savesp = sp;		int wasdisc;		esp->e_slots[slot] = (struct scsi_cmd *) 0;		if (sp->cmd_flags & CFLAG_CMDDISC) {			wasdisc = 1;			esp->e_ndisc -= 1;		} else {			wasdisc = 0;		}		esp->e_ncmds -= 1;		sp = &local;		esp_makeproxy_cmd(sp, ap, MSG_ABORT);		IPRINTF2 ("Sending proxy abort message to %d.%d\n",		    ap->a_target, ap->a_lun);		if (esp_start(sp) == TRAN_ACCEPT &&		    sp->cmd_pkt.pkt_reason == CMD_CMPLT &&		    sp->cmd_cdb[ESP_PROXY_RESULT] == TRUE) {			IPRINTF2 ("Proxy abort succeeded for %d.%d\n",			    ap->a_target, ap->a_lun);			rval = TRUE;			savesp->cmd_pkt.pkt_reason = CMD_ABORTED;			(*savesp->cmd_pkt.pkt_comp)(savesp);			IPRINTF2 ("Completion called for %d.%d\n",			    ap->a_target, ap->a_lun);		} else {			IPRINTF2 ("Proxy abort failed for %d.%d\n",			    ap->a_target, ap->a_lun);			esp->e_ncmds++;			if (wasdisc) {				esp->e_ndisc++;				savesp->cmd_flags |= CFLAG_CMDDISC;			}			esp->e_slots[slot] = savesp;			rval = FALSE;		}		if (esp->e_state == STATE_FREE) {			(void) esp_ustart(esp, NEXTSLOT(slot));		}	}	(void) splx(s);	return (rval);}static intesp_reset(ap, level)struct scsi_address *ap;int level;{	register s, rval;	struct esp *esp = (struct esp *) ap->a_cookie;	rval = FALSE;	s = splr(esp->e_tran.tran_spl);	if (level == RESET_ALL) {		/*		 * We know that esp_reset_bus() returns ACTION_RETURN.		 */		(void) esp_reset_bus(esp);		/*		 * Now call esp_dopoll() to field the reset interrupt		 * which will than call esp_reset_recovery which will		 * call completion for all commands.		 *		 * XXX: mark that we are in 'polling' mode so that		 * XXX: esp_reset_recovery just returns up to esp_dopoll()		 * XXX: with state == STATE_FREE. Gross, but esp_reset_recovery		 * XXX: will clear the e_npolling flag, but remember that		 * XXX: we were in 'polling' mode and just return ACTION_RETURN		 *		 */		esp->e_npolling++;		if (esp_dopoll(esp, POLL_TIMEOUT)) {			esplog(esp, LOG_ERR, "reset scsi bus failed");		} else			rval = TRUE;	} else {		short slot = (ap->a_target * NLUNS_PER_TARGET) | ap->a_lun;		if (esp->e_state == STATE_FREE && esp->e_slots[slot] == 0 &&		    esp->e_npolling == 0) {			auto struct scsi_cmd local;			register struct scsi_cmd *sp = &local;			IPRINTF2 ("Sending proxy reset message to %d.%d\n",			    ap->a_target, ap->a_lun);			esp_makeproxy_cmd(sp, ap, MSG_DEVICE_RESET);			if (esp_start(sp) == TRAN_ACCEPT &&			    sp->cmd_pkt.pkt_reason == CMD_CMPLT &&			    sp->cmd_cdb[ESP_PROXY_RESULT] == TRUE) {				IPRINTF2 ("proxy reset of %d.%d ok\n",				    ap->a_target, ap->a_lun);				rval = TRUE;			} else {				/*				 * make sure the local packet is not left in				 * the active slot				 */				if (esp->e_slots[slot] == &local) {					esp->e_slots[slot] =					    (struct scsi_cmd *) NULL;				}			}		}	}	if (esp->e_state == STATE_FREE) {		(void) esp_ustart(esp, 0);	}	(void) splx(s);	return (rval);}static intesp_commoncap(ap, cap, val, tgtonly, doset)

⌨️ 快捷键说明

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