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

📄 asc.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 4 页
字号:
/*- * Copyright (c) 1992, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Ralph Campbell and Rick Macklem. * * 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 the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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. * *	@(#)asc.c	8.2 (Berkeley) 1/4/94 *//*  * Mach Operating System * Copyright (c) 1991,1990,1989 Carnegie Mellon University * All Rights Reserved. *  * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. *  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. *  * Carnegie Mellon requests users of this software to return to *  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU *  School of Computer Science *  Carnegie Mellon University *  Pittsburgh PA 15213-3890 *  * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. *//* * HISTORY * $Log:	scsi_53C94_hdw.c,v $ * Revision 2.5  91/02/05  17:45:07  mrt * 	Added author notices * 	[91/02/04  11:18:43  mrt] *  * 	Changed to use new Mach copyright * 	[91/02/02  12:17:20  mrt] *  * Revision 2.4  91/01/08  15:48:24  rpd * 	Added continuation argument to thread_block. * 	[90/12/27            rpd] *  * Revision 2.3  90/12/05  23:34:48  af * 	Recovered from pmax merge.. and from the destruction of a disk. * 	[90/12/03  23:40:40  af] *  * Revision 2.1.1.1  90/11/01  03:39:09  af * 	Created, from the DEC specs: * 	"PMAZ-AA TURBOchannel SCSI Module Functional Specification" * 	Workstation Systems Engineering, Palo Alto, CA. Aug 27, 1990. * 	And from the NCR data sheets * 	"NCR 53C94, 53C95, 53C96 Advances SCSI Controller" * 	[90/09/03            af] *//* *	File: scsi_53C94_hdw.h * 	Author: Alessandro Forin, Carnegie Mellon University *	Date:	9/90 * *	Bottom layer of the SCSI driver: chip-dependent functions * *	This file contains the code that is specific to the NCR 53C94 *	SCSI chip (Host Bus Adapter in SCSI parlance): probing, start *	operation, and interrupt routine. *//* * This layer works based on small simple 'scripts' that are installed * at the start of the command and drive the chip to completion. * The idea comes from the specs of the NCR 53C700 'script' processor. * * There are various reasons for this, mainly * - Performance: identify the common (successful) path, and follow it; *   at interrupt time no code is needed to find the current status * - Code size: it should be easy to compact common operations * - Adaptability: the code skeleton should adapt to different chips without *   terrible complications. * - Error handling: and it is easy to modify the actions performed *   by the scripts to cope with strange but well identified sequences * */#include <asc.h>#if NASC > 0#include <sys/param.h>#include <sys/systm.h>#include <sys/dkstat.h>#include <sys/buf.h>#include <sys/conf.h>#include <sys/errno.h>#include <machine/machConst.h>#include <pmax/dev/device.h>#include <pmax/dev/scsi.h>#include <pmax/dev/ascreg.h>#include <pmax/pmax/asic.h>#include <pmax/pmax/kmin.h>#include <pmax/pmax/pmaxtype.h>#define	readback(a)	{ register int foo; foo = (a); }extern int pmax_boardtype;/* * In 4ns ticks. */int	asc_to_scsi_period[] = {	32,	33,	34,	35,	5,	5,	6,	7,	8,	9,	10,	11,	12,	13,	14,	15,	16,	17,	18,	19,	20,	21,	22,	23,	24,	25,	26,	27,	28,	29,	30,	31,};/* * Internal forward declarations. */static void asc_reset();static void asc_startcmd();#ifdef DEBUGint	asc_debug = 1;int	asc_debug_cmd;int	asc_debug_bn;int	asc_debug_sz;#define NLOG 32struct asc_log {	u_int	status;	u_char	state;	u_char	msg;	int	target;	int	resid;} asc_log[NLOG], *asc_logp = asc_log;#define PACK(unit, status, ss, ir) \	((unit << 24) | (status << 16) | (ss << 8) | ir)#endif/* * Scripts are entries in a state machine table. * A script has four parts: a pre-condition, an action, a command to the chip, * and an index into asc_scripts for the next state. The first triggers error * handling if not satisfied and in our case it is formed by the * values of the interrupt register and status register, this * basically captures the phase of the bus and the TC and BS * bits.  The action part is just a function pointer, and the * command is what the 53C94 should be told to do at the end * of the action processing.  This command is only issued and the * script proceeds if the action routine returns TRUE. * See asc_intr() for how and where this is all done. */typedef struct script {	int		condition;	/* expected state at interrupt time */	int		(*action)();	/* extra operations */	int		command;	/* command to the chip */	struct script	*next;		/* index into asc_scripts for next state */} script_t;/* Matching on the condition value */#define	SCRIPT_MATCH(ir, csr)		((ir) | (((csr) & 0x67) << 8))/* forward decls of script actions */static int script_nop();		/* when nothing needed */static int asc_end();			/* all come to an end */static int asc_get_status();		/* get status from target */static int asc_dma_in();		/* start reading data from target */static int asc_last_dma_in();		/* cleanup after all data is read */static int asc_resume_in();		/* resume data in after a message */static int asc_resume_dma_in();		/* resume DMA after a disconnect */static int asc_dma_out();		/* send data to target via dma */static int asc_last_dma_out();		/* cleanup after all data is written */static int asc_resume_out();		/* resume data out after a message */static int asc_resume_dma_out();	/* resume DMA after a disconnect */static int asc_sendsync();		/* negotiate sync xfer */static int asc_replysync();		/* negotiate sync xfer */static int asc_msg_in();		/* process a message byte */static int asc_disconnect();		/* process an expected disconnect *//* Define the index into asc_scripts for various state transitions */#define	SCRIPT_DATA_IN		0#define	SCRIPT_CONTINUE_IN	2#define	SCRIPT_DATA_OUT		3#define	SCRIPT_CONTINUE_OUT	5#define	SCRIPT_SIMPLE		6#define	SCRIPT_GET_STATUS	7#define	SCRIPT_MSG_IN		9#define	SCRIPT_REPLY_SYNC	11#define	SCRIPT_TRY_SYNC		12#define	SCRIPT_DISCONNECT	15#define	SCRIPT_RESEL		16#define	SCRIPT_RESUME_IN	17#define	SCRIPT_RESUME_DMA_IN	18#define	SCRIPT_RESUME_OUT	19#define	SCRIPT_RESUME_DMA_OUT	20#define	SCRIPT_RESUME_NO_DATA	21/* * Scripts */script_t asc_scripts[] = {	/* start data in */	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAI),	/*  0 */		asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_DATA_IN + 1]},	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/*  1 */		asc_last_dma_in, ASC_CMD_I_COMPLETE,		&asc_scripts[SCRIPT_GET_STATUS]},	/* continue data in after a chunk is finished */	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/*  2 */		asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_DATA_IN + 1]},	/* start data out */	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_DATAO),	/*  3 */		asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_DATA_OUT + 1]},	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/*  4 */		asc_last_dma_out, ASC_CMD_I_COMPLETE,		&asc_scripts[SCRIPT_GET_STATUS]},	/* continue data out after a chunk is finished */	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/*  5 */		asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_DATA_OUT + 1]},	/* simple command with no data transfer */	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_STATUS),	/*  6 */		script_nop, ASC_CMD_I_COMPLETE,		&asc_scripts[SCRIPT_GET_STATUS]},	/* get status and finish command */	{SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN),			/*  7 */		asc_get_status, ASC_CMD_MSG_ACPT,		&asc_scripts[SCRIPT_GET_STATUS + 1]},	{SCRIPT_MATCH(ASC_INT_DISC, 0),					/*  8 */		asc_end, ASC_CMD_NOP,		&asc_scripts[SCRIPT_GET_STATUS + 1]},	/* message in */	{SCRIPT_MATCH(ASC_INT_FC, ASC_PHASE_MSG_IN),			/*  9 */		asc_msg_in, ASC_CMD_MSG_ACPT,		&asc_scripts[SCRIPT_MSG_IN + 1]},	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN),			/* 10 */		script_nop, ASC_CMD_XFER_INFO,		&asc_scripts[SCRIPT_MSG_IN]},	/* send synchonous negotiation reply */	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_OUT),			/* 11 */		asc_replysync, ASC_CMD_XFER_INFO,		&asc_scripts[SCRIPT_REPLY_SYNC]},	/* try to negotiate synchonous transfer parameters */	{SCRIPT_MATCH(ASC_INT_FC | ASC_INT_BS, ASC_PHASE_MSG_OUT),	/* 12 */		asc_sendsync, ASC_CMD_XFER_INFO,		&asc_scripts[SCRIPT_TRY_SYNC + 1]},	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_MSG_IN),			/* 13 */		script_nop, ASC_CMD_XFER_INFO,		&asc_scripts[SCRIPT_MSG_IN]},	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_COMMAND),			/* 14 */		script_nop, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_RESUME_NO_DATA]},	/* handle a disconnect */	{SCRIPT_MATCH(ASC_INT_DISC, ASC_PHASE_DATAO),			/* 15 */		asc_disconnect, ASC_CMD_ENABLE_SEL,		&asc_scripts[SCRIPT_RESEL]},	/* reselect sequence: this is just a placeholder so match fails */	{SCRIPT_MATCH(0, ASC_PHASE_MSG_IN),				/* 16 */		script_nop, ASC_CMD_MSG_ACPT,		&asc_scripts[SCRIPT_RESEL]},	/* resume data in after a message */	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/* 17 */		asc_resume_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_DATA_IN + 1]},	/* resume partial DMA data in after a message */	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),			/* 18 */		asc_resume_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_DATA_IN + 1]},	/* resume data out after a message */	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/* 19 */		asc_resume_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_DATA_OUT + 1]},	/* resume partial DMA data out after a message */	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),			/* 20 */		asc_resume_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,		&asc_scripts[SCRIPT_DATA_OUT + 1]},	/* resume after a message when there is no more data */	{SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_STATUS),			/* 21 */		script_nop, ASC_CMD_I_COMPLETE,		&asc_scripts[SCRIPT_GET_STATUS]},};/* * State kept for each active SCSI device. */typedef struct scsi_state {	script_t *script;	/* saved script while processing error */	int	statusByte;	/* status byte returned during STATUS_PHASE */	int	error;		/* errno to pass back to device driver */	u_char	*dmaBufAddr;	/* DMA buffer address */	u_int	dmaBufSize;	/* DMA buffer size */	int	dmalen;		/* amount to transfer in this chunk */	int	dmaresid;	/* amount not transfered if chunk suspended */	int	buflen;		/* total remaining amount of data to transfer */	char	*buf;		/* current pointer within scsicmd->buf */	int	flags;		/* see below */	int	msglen;		/* number of message bytes to read */	int	msgcnt;		/* number of message bytes received */	u_char	sync_period;	/* DMA synchronous period */	u_char	sync_offset;	/* DMA synchronous xfer offset or 0 if async */	u_char	msg_out;	/* next MSG_OUT byte to send */	u_char	msg_in[16];	/* buffer for multibyte messages */} State;/* state flags */#define DISCONN		0x01	/* true if currently disconnected from bus */#define DMA_IN_PROGRESS	0x02	/* true if data DMA started */#define DMA_IN		0x04	/* true if reading from SCSI device */#define DMA_OUT		0x10	/* true if writing to SCSI device */#define DID_SYNC	0x20	/* true if synchronous offset was negotiated */#define TRY_SYNC	0x40	/* true if try neg. synchronous offset */#define PARITY_ERR	0x80	/* true if parity error seen *//* * State kept for each active SCSI host interface (53C94). */struct asc_softc {	asc_regmap_t	*regs;		/* chip address */	volatile int	*dmar;		/* DMA address register address */	u_char		*buff;		/* RAM buffer address (uncached) */	int		myid;		/* SCSI ID of this interface */	int		myidmask;	/* ~(1 << myid) */	int		state;		/* current SCSI connection state */	int		target;		/* target SCSI ID if busy */	script_t	*script;	/* next expected interrupt & action */	ScsiCmd		*cmd[ASC_NCMD];	/* active command indexed by SCSI ID */	State		st[ASC_NCMD];	/* state info for each active command */	void		(*dma_start)();	/* Start dma routine */	void		(*dma_end)();	/* End dma routine */	u_char		*dma_next;	int		dma_xfer;	/* Dma len still to go */	int		min_period;	/* Min transfer period clk/byte */	int		max_period;	/* Max transfer period clk/byte */	int		ccf;		/* CCF, whatever that really is? */	int		timeout_250;	/* 250ms timeout */	int		tb_ticks;	/* 4ns. ticks/tb channel ticks */} asc_softc[NASC];#define	ASC_STATE_IDLE		0	/* idle state */#define	ASC_STATE_BUSY		1	/* selecting or currently connected */#define ASC_STATE_TARGET	2	/* currently selected as target */#define ASC_STATE_RESEL		3	/* currently waiting for reselect */typedef struct asc_softc *asc_softc_t;/* * Dma operations. */#define	ASCDMA_READ	1#define	ASCDMA_WRITE	2static void tb_dma_start(), tb_dma_end(), asic_dma_start(), asic_dma_end();extern u_long asc_iomem;extern u_long asic_base;/* * Definition of the controller for the auto-configuration program. */int	asc_probe();void	asc_start();void	asc_intr();struct	driver ascdriver = {	"asc", asc_probe, asc_start, 0, asc_intr,};/* * Test to see if device is present. * Return true if found and initialized ok. */asc_probe(cp)	register struct pmax_ctlr *cp;{	register asc_softc_t asc;	register asc_regmap_t *regs;	int unit, id, s, i;	int bufsiz;	if ((unit = cp->pmax_unit) >= NASC)		return (0);	if (badaddr(cp->pmax_addr + ASC_OFFSET_53C94, 1))		return (0);	asc = &asc_softc[unit];	/*	 * Initialize hw descriptor, cache some pointers	 */	asc->regs = (asc_regmap_t *)(cp->pmax_addr + ASC_OFFSET_53C94);	/*	 * Set up machine dependencies.	 * 1) how to do dma	 * 2) timing based on turbochannel frequency	 */	switch (pmax_boardtype) {	case DS_3MIN:	case DS_MAXINE:	case DS_3MAXPLUS:	    if (unit == 0) {		asc->buff = (u_char *)MACH_PHYS_TO_UNCACHED(asc_iomem);		bufsiz = 8192;		*((volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base)) = -1;		*((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;		*((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;		asc->dma_start = asic_dma_start;		asc->dma_end = asic_dma_end;		break;	    }	    /*	     * Fall through for turbochannel option.	     */

⌨️ 快捷键说明

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