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

📄 siop.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/*	$OpenBSD: siop.c,v 1.17 2001/11/05 17:25:58 art Exp $ *//*	$NetBSD: siop.c,v 1.39 2001/02/11 18:04:49 bouyer Exp $	*//* * Copyright (c) 2000 Manuel Bouyer. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by Manuel Bouyer * 4. The name of the author may not be used to endorse or promote products *    derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,      * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *//* SYM53c7/8xx PCI-SCSI I/O Processors driver */#include <sys/param.h>#include <sys/systm.h>#include <sys/device.h>#include <sys/malloc.h>#include <sys/buf.h>#include <sys/kernel.h>#include <machine/endian.h>#include <machine/bus.h>#include <dev/microcode/siop/siop.out>#include <scsi/scsi_all.h>#include <scsi/scsi_message.h>#include <scsi/scsiconf.h>#include <dev/ic/siopreg.h>#include <dev/ic/siopvar.h>#include <dev/ic/siopvar_common.h>#undef DEBUG#define DIAGNOSTIC#define SIOP_DEBUG#define SIOP_DEBUG_DR#define SIOP_DEBUG_INTR#define SIOP_DEBUG_SCHED#define SIOP_DEBUG_SINGLE_STEP#ifndef DEBUG#undef DEBUG#undef DIAGNOSTIC#undef SIOP_DEBUG#undef SIOP_DEBUG_DR#undef SIOP_DEBUG_INTR#undef SIOP_DEBUG_SCHED#undef SIOP_DEBUG_SINGLE_STEP#undef DUMP_SCRIPT#endif#define SIOP_STATS#ifndef SIOP_DEFAULT_TARGET#define SIOP_DEFAULT_TARGET 7#endif/* number of cmd descriptors per block */#define SIOP_NCMDPB (PAGE_SIZE / sizeof(struct siop_xfer))/* number of scheduler slots (needs to match script) */#define SIOP_NSLOTS 40void	siop_reset __P((struct siop_softc *));void	siop_handle_reset __P((struct siop_softc *));int	siop_handle_qtag_reject __P((struct siop_cmd *));void	siop_scsicmd_end __P((struct siop_cmd *));void	siop_start __P((struct siop_softc *));void 	siop_timeout __P((void *));int	siop_scsicmd __P((struct scsi_xfer *));void	siop_dump_script __P((struct siop_softc *));int	siop_morecbd __P((struct siop_softc *));struct siop_lunsw *siop_get_lunsw __P((struct siop_softc *));void	siop_add_reselsw __P((struct siop_softc *, int));void	siop_update_scntl3 __P((struct siop_softc *, struct siop_target *));struct cfdriver siop_cd = {	NULL, "siop", DV_DULL};struct scsi_adapter siop_adapter = {	siop_scsicmd,	siop_minphys,	NULL,	NULL,};struct scsi_device siop_dev = {	NULL,	NULL,	NULL,	NULL,};#ifdef SIOP_STATSstatic int siop_stat_intr = 0;static int siop_stat_intr_shortxfer = 0;static int siop_stat_intr_sdp = 0;static int siop_stat_intr_done = 0;static int siop_stat_intr_xferdisc = 0;static int siop_stat_intr_lunresel = 0;static int siop_stat_intr_qfull = 0;void siop_printstats __P((void));#define INCSTAT(x) x++#else#define INCSTAT(x) #endifstatic __inline__ void siop_script_sync __P((struct siop_softc *, int));static __inline__ voidsiop_script_sync(sc, ops)	struct siop_softc *sc;	int ops;{	if ((sc->features & SF_CHIP_RAM) == 0)		bus_dmamap_sync(sc->sc_dmat, sc->sc_scriptdma,		    0, PAGE_SIZE, ops);}static __inline__ u_int32_t siop_script_read __P((struct siop_softc *, u_int));static __inline__ u_int32_tsiop_script_read(sc, offset)	struct siop_softc *sc;	u_int offset;{	if (sc->features & SF_CHIP_RAM) {		return bus_space_read_4(sc->sc_ramt, sc->sc_ramh, offset * 4);	} else {		return letoh32(sc->sc_script[offset]);	}}static __inline__ void siop_script_write __P((struct siop_softc *, u_int,	u_int32_t));static __inline__ voidsiop_script_write(sc, offset, val)	struct siop_softc *sc;	u_int offset;	u_int32_t val;{	if (sc->features & SF_CHIP_RAM) {		bus_space_write_4(sc->sc_ramt, sc->sc_ramh, offset * 4, val);	} else {		sc->sc_script[offset] = htole32(val);	}}voidsiop_attach(sc)	struct siop_softc *sc;{	int error, i;	bus_dma_segment_t seg;	int rseg;	/*	 * Allocate DMA-safe memory for the script and map it.	 */	if ((sc->features & SF_CHIP_RAM) == 0) {		error = bus_dmamem_alloc(sc->sc_dmat, PAGE_SIZE, 		    PAGE_SIZE, 0, &seg, 1, &rseg, BUS_DMA_NOWAIT);		if (error) {			printf("%s: unable to allocate script DMA memory, "			    "error = %d\n", sc->sc_dev.dv_xname, error);			return;		}		error = bus_dmamem_map(sc->sc_dmat, &seg, rseg, PAGE_SIZE,		    (caddr_t *)&sc->sc_script, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);		if (error) {			printf("%s: unable to map script DMA memory, "			    "error = %d\n", sc->sc_dev.dv_xname, error);			return;		}		error = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1,		    PAGE_SIZE, 0, BUS_DMA_NOWAIT, &sc->sc_scriptdma);		if (error) {			printf("%s: unable to create script DMA map, "			    "error = %d\n", sc->sc_dev.dv_xname, error);			return;		}		error = bus_dmamap_load(sc->sc_dmat, sc->sc_scriptdma,		    sc->sc_script, PAGE_SIZE, NULL, BUS_DMA_NOWAIT);		if (error) {			printf("%s: unable to load script DMA map, "			    "error = %d\n", sc->sc_dev.dv_xname, error);			return;		}		sc->sc_scriptaddr = sc->sc_scriptdma->dm_segs[0].ds_addr;		sc->ram_size = PAGE_SIZE;	}	TAILQ_INIT(&sc->free_list);	TAILQ_INIT(&sc->ready_list);	TAILQ_INIT(&sc->urgent_list);	TAILQ_INIT(&sc->cmds);	TAILQ_INIT(&sc->lunsw_list);	sc->sc_currschedslot = 0;#ifdef SIOP_DEBUG	printf("%s: script size = %d, PHY addr=0x%x, VIRT=%p\n",	    sc->sc_dev.dv_xname, (int)sizeof(siop_script),	    (u_int32_t)sc->sc_scriptaddr, sc->sc_script);#endif	/* Start with one page worth of commands */	siop_morecbd(sc);	/*	 * sc->sc_link is the template for all device sc_link's	 * for devices attached to this adapter. It is passed to	 * the upper layers in config_found().	 */	sc->sc_link.adapter_softc = sc;	sc->sc_link.openings = SIOP_OPENINGS;	sc->sc_link.adapter_buswidth =	    (sc->features & SF_BUS_WIDE) ? 16 : 8;	sc->sc_link.adapter_target = bus_space_read_1(sc->sc_rt,	    sc->sc_rh, SIOP_SCID);	if (sc->sc_link.adapter_target == 0 ||	    sc->sc_link.adapter_target >=	    sc->sc_link.adapter_buswidth)		sc->sc_link.adapter_target = SIOP_DEFAULT_TARGET;	sc->sc_link.adapter = &siop_adapter;	sc->sc_link.device = &siop_dev;	sc->sc_link.flags  = 0;	sc->sc_link.quirks = 0;	if ((sc->features & SF_BUS_WIDE) == 0)	  sc->sc_link.quirks |= SDEV_NOWIDE;	for (i = 0; i < 16; i++)		sc->targets[i] = NULL;	/* find min_dt_sync and min_st_sync for this chip */	sc->min_dt_sync = 0;	for (i = 0; i < sizeof(period_factor) / sizeof(period_factor[0]); i++)		if (period_factor[i].scf[sc->scf_index].dt_scf != 0) {			sc->min_dt_sync = period_factor[i].factor;			break;		}	sc->min_st_sync = 0;	for (i = 0; i < sizeof(period_factor) / sizeof(period_factor[0]); i++)		if (period_factor[i].scf[sc->scf_index].st_scf != 0) {			sc->min_st_sync = period_factor[i].factor;			break;		}	if (sc->min_st_sync == 0)		panic("%s: can't find minimum allowed sync period factor\n", sc->sc_dev.dv_xname);	/* Do a bus reset, so that devices fall back to narrow/async */	siop_resetbus(sc);	/*	 * siop_reset() will reset the chip, thus clearing pending interrupts	 */	siop_reset(sc);#ifdef DUMP_SCRIPT	siop_dump_script(sc);#endif	config_found((struct device*)sc, &sc->sc_link, scsiprint);}voidsiop_reset(sc)	struct siop_softc *sc;{	int i, j;	struct siop_lunsw *lunsw;	siop_common_reset(sc);	/* copy and patch the script */#ifdef SIOP_DEBUG	printf("%s: downloading script...\n", sc->sc_dev.dv_xname);#endif	if (sc->features & SF_CHIP_RAM) {#ifdef SIOP_DEBUG		printf("%s: sc->sc_ramh is 0x%08x...\n",			sc->sc_dev.dv_xname, sc->sc_ramh);#endif		bus_space_write_region_4(sc->sc_ramt, sc->sc_ramh, 0,		    siop_script, sizeof(siop_script) / sizeof(siop_script[0]));		for (j = 0; j <		    (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));		    j++) {			bus_space_write_4(sc->sc_ramt, sc->sc_ramh,			    E_abs_msgin_Used[j] * 4,			    sc->sc_scriptaddr + Ent_msgin_space);		}#ifdef SIOP_DEBUG	printf("%s: script download done...\n", sc->sc_dev.dv_xname);#endif	} else {		for (j = 0;		    j < (sizeof(siop_script) / sizeof(siop_script[0])); j++) {			sc->sc_script[j] = htole32(siop_script[j]);		}		for (j = 0; j <		    (sizeof(E_abs_msgin_Used) / sizeof(E_abs_msgin_Used[0]));		    j++) {			sc->sc_script[E_abs_msgin_Used[j]] =			    htole32(sc->sc_scriptaddr + Ent_msgin_space);		}	}	sc->script_free_lo = sizeof(siop_script) / sizeof(siop_script[0]);	sc->script_free_hi = sc->ram_size / 4;	/* free used and unused lun switches */	while((lunsw = TAILQ_FIRST(&sc->lunsw_list)) != NULL) {#ifdef SIOP_DEBUG		printf("%s: free lunsw at offset %d\n",				sc->sc_dev.dv_xname, lunsw->lunsw_off);#endif		TAILQ_REMOVE(&sc->lunsw_list, lunsw, next);		free(lunsw, M_DEVBUF);	}	TAILQ_INIT(&sc->lunsw_list);	/* restore reselect switch */	for (i = 0; i < sc->sc_link.adapter_buswidth; i++) {		if (sc->targets[i] == NULL)			continue;#ifdef SIOP_DEBUG		printf("%s: restore sw for target %d\n",				sc->sc_dev.dv_xname, i);#endif		free(sc->targets[i]->lunsw, M_DEVBUF);		sc->targets[i]->lunsw = siop_get_lunsw(sc);		if (sc->targets[i]->lunsw == NULL) {			printf("%s: can't alloc lunsw for target %d\n",			    sc->sc_dev.dv_xname, i);			break;		}		siop_add_reselsw(sc, i);	}	/* start script */#ifdef SIOP_DEBUG	printf("%s: starting script @ 0x%08x...\n", 		sc->sc_dev.dv_xname, sc->sc_scriptaddr + Ent_reselect);#endif	siop_script_sync(sc, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);#ifdef SIOP_DEBUG_SINGLE_STEP	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL,		bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL) | DCNTL_SSM);#endif	bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP,	    sc->sc_scriptaddr + Ent_reselect);#ifdef SIOP_DEBUG_SINGLE_STEP	bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL,		bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL) | DCNTL_STD);#endif#ifdef SIOP_DEBUG	printf("%s: script started...\n", sc->sc_dev.dv_xname);#endif}#ifdef DEBUG#ifdef SIOP_DEBUG_SINGLE_STEP#define CALL_SCRIPT(ent) do {\	printf ("start script DSA 0x%lx DSP 0x%lx\n", \	    siop_cmd->dsa, \	    sc->sc_scriptaddr + ent); \bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, sc->sc_scriptaddr + ent); \bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL, bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_DCNTL) | DCNTL_STD); \} while (0)#else#define CALL_SCRIPT(ent) do {\	printf ("start script DSA 0x%lx DSP 0x%lx\n", \	    siop_cmd->dsa, \	    sc->sc_scriptaddr + ent); \bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, sc->sc_scriptaddr + ent); \} while (0)#endif#else#define CALL_SCRIPT(ent) do {\bus_space_write_4(sc->sc_rt, sc->sc_rh, SIOP_DSP, sc->sc_scriptaddr + ent); \} while (0)#endifintsiop_intr(v)	void *v;{	struct siop_softc *sc = v;	struct siop_target *siop_target;	struct siop_cmd *siop_cmd;	struct siop_lun *siop_lun;	struct scsi_xfer *xs;	int istat, sist = 0, sstat1 = 0, dstat = 0;	u_int32_t irqcode = 0;	int need_reset = 0;	int offset, target, lun, tag;	bus_addr_t dsa;	struct siop_cbd *cbdp;	int freetarget = 0;	int restart = 0;	istat = bus_space_read_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT);	if ((istat & (ISTAT_INTF | ISTAT_DIP | ISTAT_SIP)) == 0)		return 0;	INCSTAT(siop_stat_intr);	if (istat & ISTAT_INTF) {		printf("INTRF\n");		bus_space_write_1(sc->sc_rt, sc->sc_rh, SIOP_ISTAT, ISTAT_INTF);	}	/* use DSA to find the current siop_cmd */	dsa = bus_space_read_4(sc->sc_rt, sc->sc_rh, SIOP_DSA);

⌨️ 快捷键说明

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