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

📄 esp.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#ident	"@(#)esp.c 1.1 92/07/30 SMI"/* * Copyright (c) 1988-1991 by Sun Microsystems, Inc. */#include "esp.h"#if NESP > 0#include <scsi/scsi.h>#include <scsi/adapters/espvar.h>#ifdef	OPENPROMS#include <sun/autoconf.h>#endif	/* OPENPROMS */#ifdef	sun4m#include <sun4m/iommu.h>#endif	/* sun4m *//* * Update Grok- to allow compilation on systems without newer dmaga.h header(s) */#ifndef BURSTSIZE#define	BURSTSIZE#define	BURST1		0x01#define	BURST2		0x02#define	BURST4		0x04#define	BURST8		0x08#define	BURST16		0x10#define	BURST32		0x20#define	BURST64		0x40#define	BURSTSIZE_MASK	0x7f#define	DEFAULT_BURSTSIZE	BURST16|BURST8|BURST4|BURST2|BURST1#endif	/* BURSTSIZE */#ifndef DMAGA_TURBO#define	DMAGA_TURBO	0x00400000#endif	/* !DMAGA_TURBO */#ifndef ESC1_REV1#define	ESC1_REV1	0x4#define	SET_DMAESC_COUNT(dmar, val) (dmar)->dmaga_count = val#define	DMAESC_BSIZE	0x0800#define	DMAESC_TCZERO	0x1000#define	DMAESC_EN_TCI	0x2000#define	DMAESC_INTPEND	0x4000#define	DMAESC_PEN	0x8000#define	DMAESC_PERR	0x00010000#define	DMAESC_DRAIN	0x00020000#define	DMAESC_EN_ADD	0x00040000#define	DMAESC_SETBURST16(d)	(d)->dmaga_csr |= DMAESC_BSIZE#define	DMAESC_SETBURST32(d)	(d)->dmaga_csr &= ~DMAESC_BSIZE#endif	/* ESC1_REV1 */#ifndef DMA_REV3#define	DMA_REV3	0xA	/* DMA2 gate array */#define	DMAGA_BURSTMASK 0x000C0000#define	DMAGA_BURST16	0x00000000#define	DMAGA_NOBURST	0x00080000#define	DMAGA_BURST32	0x00040000#define	DMA2_SETNOBURST(d)	\	(d)->dmaga_csr &= ~DMAGA_BURSTMASK, (d)->dmaga_csr |= DMAGA_NOBURST#define	DMA2_SETBURST16(d)	(d)->dmaga_csr &= ~DMAGA_BURSTMASK#define	DMA2_SETBURST32(d)	\	(d)->dmaga_csr &= ~DMAGA_BURSTMASK, (d)->dmaga_csr |= DMAGA_BURST32#define	DMAGA_TWO_CYCLE 0x00200000#endif	/* !DMA_REV3 *//* * Local function declarations */static int esp_start(), esp_abort(), esp_reset(), esp_getcap(), esp_setcap();static int esp_poll(), esp_watch(), esp_phasemanage();static int esp_finish_select(), esp_reconnect(), esp_finish();static int esp_ustart(), esp_startcmd(), esp_reset_recovery(), esp_istart();static int esp_abort_curcmd(), esp_abort_allcmds(), esp_reset_bus();static int esp_handle_selection();static int esp_dopoll();#ifdef	VECTORED_INTERRUPTSstatic int esp_intr();#endif	/* VECTORED_INTERRUPTS */static void esp_internal_reset(), esp_sync_backoff();static void esp_hw_reset(), esp_curcmd_timeout(), esp_disccmd_timeout();static void esplog(), eprintf(), esp_stat_int_print();static void esp_watchsubr();static void espsvc();static void esp_dump_datasegs(), esp_dump_cmd();static void esp_chip_disconnect();static void esp_makeproxy_cmd(), esp_make_sdtr();static void esp_init_cmd(), esp_runpoll();/* * Phase handlers */static int esp_handle_unknown(), esp_handle_cmd_start(), esp_handle_cmd_done();static int esp_handle_msg_out(), esp_handle_msg_out_done();static int esp_handle_clearing();static int esp_handle_msg_in(), esp_handle_more_msgin();static int esp_handle_msg_in_done();static int esp_handle_c_cmplt(), esp_handle_data(), esp_handle_data_done();/* * Debug routines- ultimately to be hidden within ESPDEBUG */#ifdef	ESPDEBUGstatic	void esp_dump_state();#endif	/* ESPDEBUG */static	void esp_printstate();static	char *esp_state_name();/* * Local static data */static int espconf = 0;static int espconf2 = 0;static int espconf3 = 0;#define	POLL_TIMEOUT	(3 * 60000000)	/* in usec, about 3 mins */static struct esp *esp_softc = (struct esp *) 0;#ifdef	OPENPROMSstatic int nesp;#else	/* OPENPROMS */static int nesp = NESP;#endif	/* OPENPROMS */static char *esp_stat_bits = ESP_STAT_BITS;static char *esp_int_bits = ESP_INT_BITS;static char *dmaga_bits = DMAGA_BITS;static char *msginperr = "SCSI bus MESSAGE IN phase parity error\n";#ifdef	sun4cstatic int esp_ss1_esp0sync = 0;#endif	/* sun4c */static int esp_nhardints;static int esp_nmultsvc;#ifdef	ESPDEBUGstatic int espdebug = 0;#endif	/* ESPDEBUG */#ifdef	ESP_TEST_PARITYstatic int esp_ptest_msgin;static int esp_ptest_msg = -1;static int esp_ptest_msgcmplt;static int esp_ptest_status;static int esp_ptest_data_in;#endif	/* ESP_TEST_PARITY */#ifdef ESP_TEST_TIMEOUTstatic int esp_ttest;static int esp_stest;#endif /* ESP_TEST_TIMEOUT *//* * autoconfiguration routines. */#ifdef	OPENPROMSstatic int esp_identify(), esp_attach();struct dev_ops esp_ops = {	1,	esp_identify,	esp_attach};#ifdef	GASPextern int gasp_cards;extern u_long gasp_addrs[];#define	ESP_OFFSET	0x800000#define	Esp_addr(card)	(gasp_addrs[(card)] + ESP_OFFSET)static voidnew_esp(prev, gaddr)struct dev_info *prev;u_long gaddr;{	struct dev_info *dev;	dev = (struct dev_info *) kmem_zalloc (sizeof (*dev));	dev->devi_parent =  prev->devi_parent;	dev->devi_next = prev->devi_next;	prev->devi_next = dev;	dev->devi_name = prev->devi_name;	dev->devi_nreg = 1;	dev->devi_reg = (struct dev_reg *)		kmem_zalloc(sizeof (struct dev_reg));	dev->devi_reg->reg_bustype = OBIO;	dev->devi_reg->reg_addr = (addr_t) gaddr;	dev->devi_reg->reg_size = sizeof (struct espreg);	dev->devi_nintr = 1;	dev->devi_intr = prev->devi_intr;	dev->devi_driver = &esp_ops;	dev->devi_nodeid = prev->devi_nodeid; /* lies. all lies */	nesp += 1;}#endif	/* GASP */static intesp_identify(name)	char *name;{	/*	 * Note the octal literal for a comma.	 * Avoids Shannon's C-style awk script's complaints	 */	if (strcmp(name, "esp") == 0 || strcmp(name, "SUNW\054esp") == 0) {		nesp++;		return (1);	} else {		return (0);	}}static intesp_attach(dev)register struct dev_info *dev;{#ifdef	ESP_NEW_HW_DEBUG	static char *cdebug = "esp%d: %s %s returned as %d\n";#endif	/* ESP_NEW_HW_DEBUG */	static char *prop_ini_id = "initiator-id";	static char *prop_scsi_ini_id = "scsi-initiator-id";	static char *prop_cfreq = "clock-frequency";	static char *prop_bur_size = "burst-sizes";	static char *prop_diff = "differential";	static int next_unit = 0;	static int esp_spl = 0;	register struct dmaga *dmar;	register struct espreg *ep;	register struct esp *esp, *nsp;	register struct dev_info *ndev;	int i, cur_unit;	u_long ticks;	u_char clock_conv;#ifdef	GASP	if (next_unit == 0) {		register card;		struct dev_info *tmp = dev;		for (card = 0; card < 4; card++) {			if (gasp_cards & (1<<card)) {				new_esp(tmp, Esp_addr(card));				tmp = tmp->devi_next;			}		}	}#endif	/* GASP */	cur_unit = dev->devi_unit = next_unit++;	if (cur_unit >= nesp || dev->devi_nreg > 1 || dev->devi_nintr == 0) {		return (-1);	}#ifdef	sun4c	/*	 * Check to see whether this is a useful	 * slot for an sbus scsi interface	 */	if ((i = slaveslot(dev->devi_reg->reg_addr)) >= 0) {		printf("esp%d: not used - SBus slot %d is slave-only\n",		    cur_unit, i);		return (-1);	}#endif	/* sun4c */	/*	 * map in device registers	 */	ep = (struct espreg *) map_regs(dev->devi_reg->reg_addr,	    dev->devi_reg->reg_size, dev->devi_reg->reg_bustype);	if (ep == (struct espreg *) 0) {		printf("esp%d: unable to map registers\n", cur_unit);		return (-1);	}	dmar = dma_alloc(dev->devi_reg->reg_bustype, dev->devi_reg->reg_addr);	if (!dmar) {		printf("esp%d: cannot find dma controller\n", cur_unit);		unmap_regs((addr_t) ep, dev->devi_reg->reg_size);		return (-1);	}	/*	 * Initialize state of DMA gate array.	 * Must clear DMAGA_RESET on the ESC before accessing the esp.	 */	if (DMAGA_REV(dmar) == ESC1_REV1) {		dmar->dmaga_csr &= ~DMAGA_RESET;	}	dmar->dmaga_csr &= ~DMAGA_WRITE;	/*	 * If we haven't allocated the softc structure, do so now.	 */	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", cur_unit, (esp->e_cmdarea) ?		    "cmd areas" : "data structures");		if (esp) {			(void) kmem_free((caddr_t)esp, (sizeof (struct esp)));		}		unmap_regs((addr_t) ep, dev->devi_reg->reg_size);		dma_free(dmar);		return (-1);	}	esp->e_next = (struct esp *) 0;	esp->e_unit = cur_unit;	/*	 * Establish initial softc values	 */	if (esp_softc == (struct esp *) 0) {		esp_softc = esp;		timeout (esp_watch, (caddr_t) 0, hz);	} else {		for (nsp = esp_softc; nsp->e_next != (struct esp *) 0;							nsp = nsp->e_next);		nsp->e_next = esp;	}	/*	 * Determine clock frequency of attached ESP chip.	 */	for (ndev = dev; ndev; ndev = ndev->devi_parent) {		i = getprop(ndev->devi_nodeid, prop_cfreq, -1);		if ((i > 0) || ndev == top_devinfo) {#ifdef	ESP_NEW_HW_DEBUG			printf (cdebug, cur_unit, ndev->devi_name,					prop_cfreq, i);#endif	/* ESP_NEW_HW_DEBUG */			break;		}	}#ifdef	ESP_NEW_HW_DEBUG	if (i != 40000000) {		printf("WARNING: found clock frequency of %d\n", i);		printf("	 Assuming clock frequency of 40 MHZ\n");		i = 40000000;	}#endif	/* ESP_NEW_HW_DEBUG */	/*	 * Valid clock freqs. are between 10 and 40 MHz.  Otherwise	 * presume 20 MHz. and complain.  (Notice, that we wrap to	 * zero at 40 MHz.  Ick!)  This test should NEVER fail!	 *	 *	freq (MHz)	clock conversion factor	 *	10		2	 *	10.01-15	3	 *	15.01-20	4	 *	20.01-25	5	 *	25.01-30	6	 *	30.01-35	7	 *	35.01-40	8 (0)	 */	if (i > FIVE_MEG) {		clock_conv = (i + FIVE_MEG - 1)/ FIVE_MEG;	} else {		clock_conv = 0;	}	if (clock_conv < CLOCK_10MHZ || clock_conv > CLOCK_40MHZ) {		esplog(esp, LOG_ERR,		    "Bad clock frequency- setting 20mhz, asynchronous mode");		esp->e_weak = 0xff;		clock_conv = CLOCK_20MHZ;		i = TWENTY_MEG;	}	esp->e_clock_conv = clock_conv;	esp->e_clock_cycle = CLOCK_PERIOD(i);	ticks = ESP_CLOCK_TICK(esp);	esp->e_stval = ESP_CLOCK_TIMEOUT(ticks);#ifdef	ESP_TEST_FAST_SYNC	IPRINTF5("%d mhz, clock_conv %d, clock_cycle %d, ticks %d, stval %d\n",		i, esp->e_clock_conv, esp->e_clock_cycle,		ticks, esp->e_stval);#endif	ESP_TEST_FAST_SYNC	/*	 * The theory is that the layout of all cpu boards post SparcStation-1	 * is clean enough to allow SYNC mode to be on all the time.	 */#ifdef	sun4c	if (cpu == CPU_SUN4C_60 && dev->devi_unit == 0 &&	    esp_ss1_esp0sync == 0) {		esp->e_weak = 0xff;	}#endif	/* sun4c */	/*	 * Calculate max locking spl so far seen..	 */	esp->e_spl = ipltospl(dev->devi_intr->int_pri);	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 */	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_dev = dev;	esp->e_espconf = DEFAULT_HOSTID;	for (ndev = dev; ndev; ndev = ndev->devi_parent) {		i = getprop(ndev->devi_nodeid, prop_ini_id, -1);#ifdef	ESP_NEW_HW_DEBUG		printf (cdebug, cur_unit, ndev->devi_name, prop_ini_id, i);#endif	/* ESP_NEW_HW_DEBUG */		if (i == -1) {			i = getprop(ndev->devi_nodeid, prop_scsi_ini_id, -1);#ifdef	ESP_NEW_HW_DEBUG			printf (cdebug, cur_unit, ndev->devi_name,				prop_scsi_ini_id, i);#endif	/* ESP_NEW_HW_DEBUG */		}		if (i != DEFAULT_HOSTID && i >= 0 && i <= 7) {			esplog(esp, LOG_INFO, "initiator SCSI Id now %d", i);			esp->e_espconf = (u_char) i;		}		if (i > -1 || ndev == top_devinfo)			break;	}	if (scsi_options & SCSI_OPTIONS_PARITY)		esp->e_espconf |= ESP_CONF_PAREN;	esp->e_espconf |= (espconf & ~ESP_CONF_BUSID);	esp->e_reg = ep;	esp->e_dma = dmar;	/*	 * Determine sbus burst size.	 * top_devinfo is declared in <sun/openprom.h>.	 */	esp->e_burstsizes = 0xff;	ndev = esp->e_dev;	do {		i = getprop(ndev->devi_nodeid, prop_bur_size, -1);		if (i != -1) {			/*			 * oops- we have somebody who constrains us.			 */			esp->e_burstsizes = esp->e_burstsizes & i;#ifdef	ESP_NEW_HW_DEBUG			printf (cdebug, cur_unit, ndev->devi_name,				prop_bur_size, i);#endif	/* ESP_NEW_HW_DEBUG */		}		ndev = ndev->devi_parent;	} while (ndev != top_devinfo);	/*	 * No burstsize properties found- select a reasonable default	 */	i = esp->e_burstsizes;	if ((i == 0xff) || (!((i & BURST16) || (i & BURST32)))) {#ifdef	ESPDEBUG	if (DEBUGGING) {		eprintf(esp, "Bad burst size %d- setting to %d",			i, DEFAULT_BURSTSIZE);		}#endif	/* ESPDEBUG */		esp->e_burstsizes = DEFAULT_BURSTSIZE;	}	/*	 * XXX: This needs to be based upon architecture. Right now,	 * XXX: all OPENPROM machines are sun4c and have a dma base	 * XXX: of -1mb.	 */	esp->e_dma_base = (u_long) DVMA;	esp->e_last_slot = esp->e_cur_slot = UNDEFINED;	addintr(dev->devi_intr->int_pri, esp_poll,	    dev->devi_name, dev->devi_unit);	adddma(dev->devi_intr->int_pri);	report_dev(dev);	ep->esp_conf2 = 0;	ep->esp_conf2 = 0xa;	esp->e_default_period = CONVERT_PERIOD(DEFAULT_SYNC_PERIOD);	if ((ep->esp_conf2&0xf) == 0xa) {		esp->e_espconf2 = espconf2;		ep->esp_conf3 = 0;		ep->esp_conf3 = 5;		if (ep->esp_conf3 == 0x5) {			for (i = 0; i < NTARGETS; i++) {				esp->e_espconf3[i] = espconf3;			}			if (clock_conv > CLOCK_25MHZ) {				esp->e_espconf2 |= ESP_CONF2_FENABLE;				ep->esp_conf2 = esp->e_espconf2;				esp->e_default_period =					CONVERT_PERIOD(DEFAULT_FASTSYNC_PERIOD);				esp->e_type = FAST;#ifdef	ESP_TEST_FAST_SYNC				IPRINTF1("conf3=%x\n", espconf3);				IPRINTF("found FAST\n");

⌨️ 快捷键说明

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