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

📄 bsfunc.c

📁 freebsd v4.4内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$NecBSD: bsfunc.c,v 1.2 1997/10/31 17:43:37 honda 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 <i386/Cbus/dev/bs/bsif.h>#endif#ifdef	__FreeBSD__#include <i386/isa/bs/bsif.h>#endif#ifdef	BS_STATICSstruct bs_statics bs_statics[NTARGETS];u_int bs_linkcmd_count[NTARGETS];u_int bs_bounce_used[NTARGETS];#endif	/* BS_STATICS */#ifdef	BS_DEBUGint bs_debug_flag = 0;#endif	/* BS_DEBUG */static void bs_print_syncmsg __P((struct targ_info *, char*));static void bs_timeout_target __P((struct targ_info *));static void bs_kill_msg __P((struct ccb *cb));static int bs_start_target __P((struct targ_info *));static int bs_check_target __P((struct targ_info *));/************************************************************* * CCB ************************************************************/GENERIC_CCB_STATIC_ALLOC(bs, ccb)GENERIC_CCB(bs, ccb, ccb_chain)/************************************************************* * TIMEOUT ************************************************************/static voidbs_timeout_target(ti)	struct targ_info *ti;{	struct bs_softc *bsc = ti->ti_bsc;	ti->ti_error |= BSTIMEOUT;	bsc->sc_flags |= BSRESET;	if (ti->ti_herrcnt ++ >= HARDRETRIES)	{		bs_printf(ti, "timeout", "async transfer!");		ti->ti_syncmax.period = ti->ti_syncmax.offset = 0;	}}voidbstimeout(arg)	void *arg;{	struct bs_softc *bsc = (struct bs_softc *) arg;	struct targ_info *ti;	struct ccb *cb;	int s;	s = splbio();	bsc->sc_flags &= ~BSSTARTTIMEOUT;	/* check */	if ((ti = bsc->sc_nexus) && (cb = ti->ti_ctab.tqh_first))	{		if ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0)			bs_timeout_target(ti);	}	else for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)	{		if (bsc->sc_dtgnum && ti->ti_phase < DISCONNECTED)			continue;		cb = ti->ti_ctab.tqh_first;		if (cb && ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0))			bs_timeout_target(ti);	}	/* try to recover */	if (bsc->sc_flags & BSRESET)	{		bs_debug_print_all(bsc);		bs_printf(ti, "timeout", "bus hang up");		bs_reset_nexus(bsc);	}	bs_start_timeout(bsc);	splx(s);}/************************************************** * MAKE CCB & MSG CCB *************************************************/static u_int8_t cmd_unit_ready[6];struct ccb *bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout)	struct targ_info *ti;	u_int lun;	u_int8_t *cmd;	u_int cmdlen;	u_int8_t *data;	u_int datalen;	u_int flags;	int timeout;{	struct ccb *cb;	if ((cb = bs_get_ccb(XSBS_SCSI_NOSLEEP)) == NULL)		bs_panic(ti->ti_bsc, "can not get ccb mem");	cb->xs = NULL;	cb->lun = lun;	cb->cmd = (cmd ? cmd : cmd_unit_ready);	cb->cmdlen = (cmd ? cmdlen : sizeof(cmd_unit_ready));	cb->data = data;	cb->datalen = (data ? datalen : 0);	cb->msgoutlen = 0;	cb->flags = flags & BSCFLAGSMASK;	bs_targ_flags(ti, cb);	cb->rcnt = 0;	cb->tcmax = (timeout > BS_DEFAULT_TIMEOUT_SECOND ? timeout :				BS_DEFAULT_TIMEOUT_SECOND);	TAILQ_INSERT_HEAD(&ti->ti_ctab, cb, ccb_chain);	return cb;}struct ccb *bs_make_msg_ccb(ti, lun, cb, msg, timex)	struct targ_info *ti;	u_int lun;	struct ccb *cb;	struct msgbase *msg;	u_int timex;{	u_int flags;	flags = BSFORCEIOPOLL | msg->flag;	if (cb == NULL)		cb = bs_make_internal_ccb(ti, lun, NULL, 0, NULL, 0,					   flags, timex);	else		cb->flags |= flags & BSCFLAGSMASK;	cb->msgoutlen = msg->msglen;	bcopy(msg->msg, cb->msgout, msg->msglen);	return cb;}intbs_send_msg(ti, lun, msg, timex)	struct targ_info *ti;	u_int lun;	struct msgbase *msg;	int timex;{	struct ccb *cb;	cb = bs_make_msg_ccb(ti, lun, NULL, msg, timex);	bscmdstart(ti, BSCMDSTART);	return bs_scsi_cmd_poll(ti, cb);}static voidbs_kill_msg(cb)	struct ccb *cb;{	cb->msgoutlen = 0;}/************************************************** * MAKE SENSE CCB **************************************************/struct ccb *bs_request_sense(ti)	struct targ_info *ti;{	struct ccb *cb;	bzero(ti->scsi_cmd, sizeof(struct scsi_sense));	bzero(&ti->sense, sizeof(struct scsi_sense_data));	ti->scsi_cmd[0] = REQUEST_SENSE;	ti->scsi_cmd[1] = (ti->ti_lun << 5);	ti->scsi_cmd[4] = sizeof(struct scsi_sense_data);	cb = bs_make_internal_ccb(ti, ti->ti_lun, ti->scsi_cmd,				     sizeof(struct scsi_sense),				     (u_int8_t *) & ti->sense,				     sizeof(struct scsi_sense_data),				     BSFORCEIOPOLL,				     BS_DEFAULT_TIMEOUT_SECOND);	cb->flags |= BSSENSECCB;	return cb;}/************************************************** * SYNC MSG *************************************************//* sync neg */intbs_start_syncmsg(ti, cb, flag)	struct targ_info *ti;	struct ccb *cb;	int flag;{	struct syncdata *negp, *maxp;	struct msgbase msg;	u_int lun;	negp = &ti->ti_syncnow;	maxp = &ti->ti_syncmax;	ti->ti_state = BS_TARG_SYNCH;	if (flag == BS_SYNCMSG_REQUESTED)	{		if (negp->offset > maxp->offset)			negp->offset = maxp->offset;		if (negp->offset != 0 && negp->period < maxp->period)			negp->period = maxp->period;		msg.flag = 0;		lun = ti->ti_lun;		if (cb == NULL)			cb = ti->ti_ctab.tqh_first;	}	else if (ti->ti_cfgflags & BS_SCSI_SYNC)	{		negp->offset = maxp->offset;		negp->period = maxp->period;		msg.flag = BSERROROK;		lun = 0;	}	else	{		ti->ti_state = BS_TARG_RDY;		return COMPLETE;	}	BS_SETUP_SYNCSTATE(flag);	msg.msg[0] = MSG_EXTEND;	msg.msg[1] = MSG_EXTEND_SYNCHLEN;	msg.msg[2] = MSG_EXTEND_SYNCHCODE;	msg.msg[3] = negp->period;	msg.msg[4] = negp->offset;	msg.msglen = MSG_EXTEND_SYNCHLEN + 2;	bs_make_msg_ccb(ti, lun, cb, &msg, BS_SYNC_TIMEOUT);	return COMPLETE;}static voidbs_print_syncmsg(ti, s)	struct targ_info *ti;	char *s;{	struct bs_softc *bsc = ti->ti_bsc;	struct syncdata *negp;	u_int speed;	negp = &ti->ti_syncnow;	speed = (negp->offset && negp->period) ?		(2500 / ((u_int) negp->period)) : 0;	printf("%s(%d:%d): <%s> ", bsc->sc_dvname, ti->ti_id, ti->ti_lun, s);	printf("period 0x%x offset %d chip (0x%x)", negp->period, negp->offset,		ti->ti_sync);	if (speed)		printf(" %d.%d M/s", speed / 10, speed % 10);	printf("\n");}intbs_analyze_syncmsg(ti, cb)	struct targ_info *ti;	struct ccb *cb;{	struct bs_softc *bsc = ti->ti_bsc;	u_int8_t ans = ti->ti_syncnow.state;	struct syncdata *negp, *maxp;	struct syncdata bdata;	char *s = NULL;	u_int8_t period;	negp = &ti->ti_syncnow;	bdata = *negp;	maxp = &ti->ti_syncmax;	switch(ans)	{	case BS_SYNCMSG_REJECT:		period = 0;		s = "msg reject";		break;	case BS_SYNCMSG_ASSERT:		period = 0;		s = "no msg";		break;	default:		if (negp->offset != 0 && negp->period < maxp->period)		{			period = 0xff;			s = "illegal(period)";		}		else if (negp->offset > maxp->offset)		{			period = 0xff;			s = "illegal(offset)";		}		else			period = negp->offset ? negp->period : 0;		break;	}	if (s == NULL)	{		bshw_adj_syncdata(negp);		*maxp = *negp;		if (ans == BS_SYNCMSG_REQUESTED)			s = "requested";		else			s = negp->offset ? "synchronous" : "async";	}	else	{		negp->offset = maxp->offset = 0;		bshw_adj_syncdata(negp);		bshw_adj_syncdata(maxp);	}	/* really setup hardware */	bshw_set_synchronous(bsc, ti);	if (cb == NULL || (period >= negp->period && period <= negp->period + 2))	{		bs_print_syncmsg(ti, s);		BS_SETUP_TARGSTATE(BS_TARG_RDY);		BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);		if (cb)			bs_kill_msg(cb);		return 0;	}	else	{		bs_printf(ti, "bs_analyze_syncmsg",			  "sync(period) mismatch, retry neg...");		printf("expect(%d:0x%x) => reply(%d:0x%x)\n",			bdata.offset, bdata.period, negp->offset, negp->period);		bs_start_syncmsg(ti, cb, BS_SYNCMSG_ASSERT);		return EINVAL;	}}/************************************************** * ABORT AND RESET MSG **************************************************//* send device reset msg and wait */voidbs_reset_device(ti)	struct targ_info *ti;{	struct msgbase msg;	msg.msglen = 1;	msg.msg[0] = MSG_RESET;	msg.flag = 0;	bs_send_msg(ti, 0, &msg, 0);	delay(ti->ti_bsc->sc_RSTdelay);	bs_check_target(ti);}/* send abort msg */struct ccb *bs_force_abort(ti)	struct targ_info *ti;{	struct bs_softc *bsc = ti->ti_bsc;	struct msgbase msg;	struct ccb *cb = ti->ti_ctab.tqh_first;	u_int lun;	if (cb)	{		lun = cb->lun;		cb->rcnt++;	}	else		lun = 0;	msg.msglen = 1;	msg.msg[0] = MSG_ABORT;	msg.flag = 0;	cb = bs_make_msg_ccb(ti, lun, NULL, &msg, 0);	bscmdstart(ti, BSCMDSTART);	if (bsc->sc_nexus == ti)		BS_LOAD_SDP	return cb;}/************************************************** * COMPLETE SCSI BUS RESET *************************************************//* * XXX: * 1) reset scsi bus (ie. all target reseted). * 2) chip reset. * 3) check target status. * 4) sync neg with all targets. * 5) setup sync reg in host. * 6) recover previous nexus. */voidbs_scsibus_start(bsc)	struct bs_softc *bsc;{	struct targ_info *ti, *nextti = NULL;	int error = HASERROR;	u_int querm, bits, skip = 0;	querm = (bsc->sc_hstate == BSC_BOOTUP);	bsc->sc_hstate = BSC_TARG_CHECK;

⌨️ 快捷键说明

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