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

📄 bshw.c

📁 freebsd v4.4内核源码
💻 C
字号:
/*	$NecBSD: bshw.c,v 1.1 1997/07/18 09:19:03 kmatsuda Exp $	*//*	$NetBSD$	*//* * [NetBSD for NEC PC98 series] *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff. *  All rights reserved. *  *  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. 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. *//* * Copyright (c) 1994, 1995, 1996 Naofumi HONDA.  All rights reserved. */#ifdef	__NetBSD__#include <dev/isa/isadmareg.h>#include <i386/Cbus/dev/bs/bsif.h>#include <i386/Cbus/dev/bs/bshw.lst>#endif#ifdef	__FreeBSD__#include <i386/isa/ic/i8237.h>#include <i386/isa/bs/bsif.h>#include <i386/isa/bs/bshw.lst>#include <machine/clock.h>#include <i386/i386/cons.h>#endifstatic struct bs_softc *gbsc;/************************************************** * DECLARATION **************************************************/static void bshw_force_bsmode __P((struct bs_softc *));/************************************************** * STATIC VAL **************************************************/static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };/************************************************** * SCSI CMD BRANCH **************************************************/#define	RS	(BSSAT | BSSMIT | BSLINK | BSREAD)#define	WS	(BSSAT | BSSMIT | BSLINK)#define	EOK	(BSERROROK)u_int8_t bshw_cmd[256] = {/*   0  1   2   3   4   5   6   7   8   9   A   B   C   E   D   F *//*0*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,RS ,0  ,WS ,0  ,0  ,0  ,0  ,0  ,/*1*/0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,/*2*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,RS ,0  ,WS ,0  ,0  ,0  ,0  ,0  ,/*3*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*4*/0  ,0  ,EOK,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*5*/0  ,0  ,0  ,0  ,EOK,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*6*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*7*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*8*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*9*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*A*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*B*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*C*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*D*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*E*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,/*F*/0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,0  ,};#undef	RS#undef	WS#undef	EOK/********************************************** * init **********************************************/static voidbshw_force_bsmode(bsc)	struct bs_softc *bsc;{	if (bsc->sc_flags & BSBSMODE)		return;	bsc->sc_flags |= BSBSMODE;	/*	 * If you have memory over 16M, some stupid boards always force to	 * use the io polling mode. Check such a case and change mode into	 * bus master DMA. However this depends heavily on the board's	 * specifications!	 */	if (bsc->sc_hw->dma_init && ((*bsc->sc_hw->dma_init)(bsc)))		printf("%s change mode using external DMA (%x)\n",		    bsc->sc_dvname, (u_int)read_wd33c93(bsc, 0x37));}#define	RESET_DEFAULT	2000intbshw_chip_reset(bsc)	struct bs_softc *bsc;{	int ct;	u_int8_t aux;	bshw_lock(bsc);	bshw_abort_cmd(bsc);	delay(10000);	bshw_get_auxstat(bsc);	bshw_get_busstat(bsc);	write_wd33c93(bsc, wd3s_oid, IDR_EHP | bsc->sc_cspeed | bsc->sc_hostid);	write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);	for (ct = RESET_DEFAULT; ct > 0; ct--)	{		aux = bshw_get_auxstat(bsc);		if (aux != 0xff && (aux & STR_INT))		{			if (bshw_get_busstat(bsc) == 0)				break;			write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);		}		delay(1);	}	if (ct == 0)	{		bshw_unlock(bsc);		return ENXIO;	}	bshw_force_bsmode(bsc);	write_wd33c93(bsc, wd3s_tout, BSHW_SEL_TIMEOUT);	write_wd33c93(bsc, wd3s_sid, SIDR_RESEL);	bsc->sc_flags |= BSDMATRANSFER;	write_wd33c93(bsc, wd3s_ctrl, CR_DEFAULT);	write_wd33c93(bsc, wd3s_synch, 0);	bshw_get_auxstat(bsc);	bsc->sc_busstat = bshw_get_busstat(bsc);	bshw_unlock(bsc);	return 0;}/* scsi bus hard reset */#define	TWIDDLEWAIT	10000static int tw_pos;static char tw_chars[] = "|/-\\";/* this is some jokes */static voidtwiddle_wait(void){	cnputc('\b');	cnputc(tw_chars[tw_pos++]);	tw_pos %= (sizeof(tw_chars) - 1);	delay(TWIDDLEWAIT);}static void bshw_set_vsp __P((struct bs_softc *, u_int, u_int8_t));static voidbshw_set_vsp(bsc, chan, spva)	struct bs_softc *bsc;	u_int chan;	u_int8_t spva;{	struct bshw *hw = bsc->sc_hw;	if (hw->sregaddr == 0)		return;	write_wd33c93(bsc, hw->sregaddr + chan, spva);	if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)		write_wd33c93(bsc, hw->sregaddr + chan + 8, spva);}voidbshw_bus_reset(bsc)	struct bs_softc *bsc;{	struct targ_info *ti;	int i, lpc;	if (bsc->sc_RSTdelay == 0)		bsc->sc_RSTdelay = 6 * 1000 * 1000;	else	{		/* XXX:		 * second time reset will be requested by hardware failuer.		 */		bsc->sc_RSTdelay = 12 * 1000 * 1000;	}	bshw_lock(bsc);	write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank | MBR_RST) & ~MBR_IEN);	delay(500000);	write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank) & ~MBR_IEN);	bshw_unlock(bsc);	for (lpc = 0; lpc < 2; lpc ++)	{		cnputc(' ');		for (i = 0; i <= bsc->sc_RSTdelay / TWIDDLEWAIT; i++)			twiddle_wait();		cnputc('\b');		(void) read_wd33c93(bsc, wd3s_auxc);		delay(10000);		if ((read_wd33c93(bsc, wd3s_auxc) & AUXCR_RRST) == 0)			break;		printf("\nreset state still continue, wait ...");	}	for (i = 0; i < NTARGETS; i++)	{		if ((ti = bsc->sc_ti[i]) != NULL)		{			ti->ti_sync = 0;			bshw_set_vsp(bsc, i, 0);		}	}}/* probe */intbshw_board_probe(bsc, drq, irq)	struct bs_softc *bsc;	u_int *drq;	u_int *irq;{	gbsc = bsc;#ifdef	SHOW_PORT	bshw_print_port(bsc);#endif	/* SHOW_PORT */	bsc->sc_hostid = (read_wd33c93(bsc, wd3s_auxc) & AUXCR_HIDM);	if ((*irq) == IRQUNK)		*irq = irq_tbl[(read_wd33c93(bsc, wd3s_auxc) >> 3) & 7];	if ((*drq) == DRQUNK)		*drq = BUS_IOR(cmd_port) & 3;	bsc->sc_dmachan = *drq;	bsc->sc_irq = (*irq);	bsc->sc_membank = read_wd33c93(bsc, wd3s_mbank);	bsc->sc_membank &= ~MBR_RST;	bsc->sc_membank |= MBR_IEN;	bsc->sc_cspeed = (read_wd33c93(bsc, wd3s_oid) & (~IDR_IDM));	switch (BSC_CHIP_CLOCK(bsc->sc_cfgflags))	{	case 0:		break;	case 1:		bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);		break;	case 2:		bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);		bsc->sc_cspeed |= IDR_FS_12_15;		break;	case 3:		bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);		bsc->sc_cspeed |= IDR_FS_15_20;		break;	}	/* XXX: host id fixed(7) */	bsc->sc_hostid = 7;	if (bshw_chip_reset(bsc))		return ENXIO;	return 0;}/* * XXX: * Assume the board clock rate must be 20Mhz (always satisfied, maybe)! * Only 10M/s 6.6M/s 5.0M/s 3.3M/s for synchronus transfer speed set. */#define	ILLEGAL_SYNCH#ifdef	ILLEGAL_SYNCH/*  A  10    6.6   5.0   4.0   3.3   2.8   2.5   2.0  M/s *//*  X  100   150   200   250   300   350   400   500  ns  */static u_int bshw_scsi_period[] =   {0, 25,   37,   50,   62,   75,   87,   100,  125};static u_int8_t bshw_chip_pval[] =   {0, 0xa0, 0xb0, 0x20, 0xd0, 0x30, 0xf0, 0x40, 0x50};#else	/* !ILLEGAL_SYNCH *//*  A  10    6.6   5.0   3.3   2.5 M/s *//*  X  100   150   200   300   400 ns  */static u_int bshw_scsi_period[] =   {0, 25,   37,   50,   75,   100};static u_int8_t bshw_chip_pval[] =   {0, 0xa0, 0xb0, 0x20, 0x30, 0x40};#endif	/* !ILLEGAL_SYNCH */voidbshw_adj_syncdata(sdp)	struct syncdata *sdp;{	int i;	if (sdp->offset == 0 || sdp->period < 25 || sdp->period > 100)		sdp->offset = sdp->period = 0;	else	{		for (i = 0; sdp->period > bshw_scsi_period[i] + 2; i ++)			;		sdp->period = bshw_scsi_period[i];	}}voidbshw_set_synchronous(bsc, ti)	struct bs_softc *bsc;	struct targ_info *ti;{	struct syncdata sd;	int i;	sd = ti->ti_syncnow;	bshw_adj_syncdata(&sd);	for (i = 0; sd.period != bshw_scsi_period[i]; i++)		;	ti->ti_sync = ((sd.offset & 0x0f) | bshw_chip_pval[i]);	bshw_set_vsp(bsc, ti->ti_id, ti->ti_sync);	if (bsc->sc_nexus == ti)		bshw_set_sync_reg(bsc, ti->ti_sync);}/* ctrl reg */voidbshw_setup_ctrl_reg(bsc, flags)	struct bs_softc *bsc;	u_int flags;{	u_int8_t regval;	regval = (flags & BS_SCSI_NOPARITY) ? CR_DEFAULT : CR_DEFAULT_HP;	if (bsc->sc_flags & BSDMATRANSFER)		regval |= CR_DMA;	write_wd33c93(bsc, wd3s_ctrl, regval);}/* sat command */voidbshw_issue_satcmd(bsc, cb, link)	struct bs_softc *bsc;	struct ccb *cb;	int link;{	int i;	BUS_IOW(addr_port, wd3s_cdb);	for (i = 0; i < cb->cmdlen - 1; i++)		BUS_IOW(ctrl_port, cb->cmd[i]);	BUS_IOW(ctrl_port, cb->cmd[i] | (link ? 1 : 0));}/* lock */voidbshw_lock(bsc)	struct bs_softc *bsc;{	bsc->sc_hwlock++;	write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank & (~MBR_IEN));}voidbshw_unlock(bsc)	struct bs_softc *bsc;{	if ((--bsc->sc_hwlock) <= 0)		write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank);}/********************************************** * DMA OPERATIONS **********************************************/#ifdef	__NetBSD__#include <i386/Cbus/dev/bs/bshw_dma.c>#include <i386/Cbus/dev/bs/bshw_pdma.c>#endif#ifdef	__FreeBSD__#include <i386/isa/bs/bshw_dma.c>#include <i386/isa/bs/bshw_pdma.c>#endif/********************************************** * DEBUG **********************************************//* misc */voidbshw_print_port(bsc)	struct bs_softc * bsc;{	int i, j;	int port = 0x0;	if (bsc == NULL)		bsc = gbsc;	printf("\n");	for (j = 0; j <= 0x70; j += 0x10)	{		printf("port %x: ", port);		for (i = 0; i < 0x10; i++)			printf("%x ", (u_int) read_wd33c93(bsc, port++));		printf("\n");	}}

⌨️ 快捷键说明

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