NetBSD-5.0.2/sys/dev/ic/ninjascsi32var.h

/*	$NetBSD: ninjascsi32var.h,v 1.6 2008/07/09 19:08:44 joerg Exp $	*/

/*-
 * Copyright (c) 2004, 2007 The NetBSD Foundation, Inc.
 * All rights reserved.
 *
 * This code is derived from software contributed to The NetBSD Foundation
 * by ITOH Yasufumi.
 *
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
 */

#ifndef _NJSC32VAR_H_
#define _NJSC32VAR_H_

typedef unsigned	njsc32_model_t;
#define NJSC32_MODEL_MASK	0xff
#define NJSC32_MODEL_INVALID	0
#define NJSC32_MODEL_32BI	1
#define NJSC32_MODEL_32UDE	2
#define NJSC32_FLAG_DUALEDGE	0x100	/* supports DualEdge */

/*
 * time parameters (25us per unit?)
 */
#define NJSC32_SEL_TIMEOUT_TIME		20000	/* selection timeout (500ms) */
#define NJSC32_ARBITRATION_RETRY_TIME	4	/* 100us */

/* in microseconds */
#define NJSC32_REQ_TIMEOUT		10000	/* 10ms */
#define NJSC32_RESET_HOLD_TIME		26	/* 25us min */

/*
 * DMA page
 */
#ifdef NJSC32_AUTOPARAM
#define NJSC32_NUM_CMD	14	/* # simultaneous commands */
#else
#define NJSC32_NUM_CMD	15	/* # simultaneous commands */
#endif
#define NJSC32_NUM_SG	17	/* # scatter/gather table entries per command */

struct njsc32_dma_page {
	/*
	 * scatter/gather transfer table
	 */
	struct njsc32_sgtable	dp_sg[NJSC32_NUM_CMD][NJSC32_NUM_SG];
#define NJSC32_SIZE_SGT \
	(sizeof(struct njsc32_sgtable) * NJSC32_NUM_SG)

#ifdef NJSC32_AUTOPARAM
	/*
	 * device reads parameters from this structure (autoparam)
	 */
	struct njsc32_autoparam	dp_ap;
#endif
};

/* per command */
struct njsc32_cmd {
	TAILQ_ENTRY(njsc32_cmd)	c_q;
	struct njsc32_softc	*c_sc;

	/* on transfer */
	struct scsipi_xfer	*c_xs;
	struct njsc32_target	*c_target;
	struct njsc32_lu	*c_lu;
	u_int32_t		c_datacnt;	/* I/O buffer length */

	/* command status */
	int		c_flags;
#define NJSC32_CMD_DMA_MAPPED	0x01
#define NJSC32_CMD_TAGGED	0x02
#define NJSC32_CMD_TAGGED_HEAD	0x04

	/* SCSI pointer */
	u_int32_t	c_dp_cur;	/* current (or active) data pointer */
	u_int32_t	c_dp_saved;	/* saved data pointer */
	u_int32_t	c_dp_max;	/* max value of data pointer */

	/* last loaded scatter/gather table */
	unsigned	c_sgoffset;	/* # skip entries */
	u_int32_t	c_sgfixcnt;	/* # skip bytes in the top entry */

	/* command start/restart parameter */
	u_int8_t	c_msg_identify;	/* Identify message */
	u_int16_t	c_xferctl;
	u_int32_t	c_sgtdmaaddr;

	/* DMA resource */
	struct njsc32_sgtable	*c_sgt;		/* for host */
	bus_addr_t		c_sgt_dma;	/* for device */
#define NJSC32_CMD_DMAADDR_SGT(cmd, n)	\
		((cmd)->c_sgt_dma + sizeof(struct njsc32_sgtable) * (n))
	bus_dmamap_t		c_dmamap_xfer;
};

/* -1 for unaligned acccess */
#define NJSC32_MAX_XFER	((NJSC32_NUM_SG - 1) << PGSHIFT)

struct njsc32_softc {
	device_t		sc_dev;

	/* device spec */
	njsc32_model_t		sc_model;

	int			sc_clk;		/* one of following */
#define NJSC32_CLK_40M		NJSC32_CLOCK_DIV_4	/* 20MB/s */
#define NJSC32_CLK_20M		NJSC32_CLOCK_DIV_2	/* 10MB/s */
#define NJSC32_CLK_PCI_33M	NJSC32_CLOCK_PCICLK	/* 16.6MB/s */

	/* device register */
	bus_space_tag_t		sc_regt;
	bus_space_handle_t	sc_regh;

	unsigned		sc_flags;
#define NJSC32_IO_MAPPED		0x00000001
#define NJSC32_MEM_MAPPED		0x00000002
#define NJSC32_CMDPG_MAPPED		0x00000004
#define NJSC32_CANNOT_SUPPLY_TERMPWR	0x00000100

	/*
	 * controller state
	 */
	enum njsc32_stat {
		NJSC32_STAT_IDLE,
		NJSC32_STAT_ARBIT,	/* initiator started arbitration */
		NJSC32_STAT_CONNECT,	/* command is active (connection) */
		NJSC32_STAT_RESEL,	/* a target did Reselection */
		NJSC32_STAT_RESEL_LUN,	/* received Identify message */
		NJSC32_STAT_RECONNECT,	/* command is active (reconnection) */
		NJSC32_STAT_RESET,	/* resetting bus */
		NJSC32_STAT_RESET1,	/* waiting for bus reset release */
		NJSC32_STAT_RESET2,	/* waiting for bus reset release */
		NJSC32_STAT_DETACH	/* detaching */
	} sc_stat;

	/* interrupt handle */
	void			*sc_ih;

	/* for DMA */
	bus_dma_tag_t		sc_dmat;
	struct njsc32_dma_page	*sc_cmdpg;	/* scatter/gather table page */
#if 0
	bus_addr_t		sc_cmdpg_dma;
#endif
	bus_dma_segment_t	sc_cmdpg_seg;
	bus_dmamap_t		sc_dmamap_cmdpg;
	int			sc_cmdpg_nsegs;

#ifdef NJSC32_AUTOPARAM
	u_int32_t		sc_ap_dma;	/* autoparam DMA address */
#endif

	/* for monitoring bus reset */
	struct callout		sc_callout;

	/*
	 * command control structure
	 */
	struct njsc32_cmd	sc_cmds[NJSC32_NUM_CMD];
	TAILQ_HEAD(njsc32_cmd_head, njsc32_cmd)
				sc_freecmd,	/* free list */
				sc_reqcmd;	/* waiting commands */

	struct njsc32_cmd	*sc_curcmd;	/* currently active command */
	int			sc_ncmd;	/* total # commands available */
	int			sc_nusedcmds;	/* # used commands */

	/* reselection */
	int			sc_reselid, sc_resellun;

	/* message in buffer */
#define NJSC32_MSGIN_LEN	20
	u_int8_t		sc_msginbuf[NJSC32_MSGIN_LEN];
	int			sc_msgincnt;

	/* message out buffer */
#define NJSC32_MSGOUT_LEN	16
	u_int8_t		sc_msgout[NJSC32_MSGOUT_LEN];
	size_t			sc_msgoutlen;
	size_t			sc_msgoutidx;

	/* sync timing table */
	const struct njsc32_sync_param {
		u_int8_t	sp_period;	/* transfer period */
		u_int8_t	sp_ackw;	/* ACK width parameter */
		u_int8_t	sp_sample;	/* sampling period */
	} *sc_synct;
	int	sc_sync_max;

	/* for scsipi layer */
	struct device		*sc_scsi;
	struct scsipi_adapter	sc_adapter;
	struct scsipi_channel	sc_channel;

	/* per-target */
	struct njsc32_target {
		enum njsc32_tarst {
			NJSC32_TARST_DONE,	/* negotiation done */
			NJSC32_TARST_INIT,
			NJSC32_TARST_DE,	/* negotiating DualEdge */
			NJSC32_TARST_WDTR,	/* negotiating width */
			NJSC32_TARST_SDTR,	/* negotiating sync */
			NJSC32_TARST_ASYNC	/* negotiating async */
		} t_state;
		int	t_flags;
#define NJSC32_TARF_TAG		0x0001	/* tagged queueing is enabled */
#define NJSC32_TARF_SYNC	0x0002	/* negotiate for sync transfer */
#define NJSC32_TARF_DE		0x0004	/* negotiate for DualEdge transfer */

		int		t_syncperiod;
		int		t_syncoffset;

		u_int8_t	t_sync;
		u_int8_t	t_ackwidth;
		u_int8_t	t_targetid;	/* initiator and target id */
		u_int8_t	t_sample;

		u_int16_t	t_xferctl;	/* DualEdge flag */

		/* per logical unit */
		struct njsc32_lu {
			/*
			 * disconnected commands
			 */
			struct njsc32_cmd *lu_cmd;	/* untagged command */
			struct njsc32_cmd_head	lu_q;	/* tagged commands */
		} t_lus[NJSC32_NLU];
	} sc_targets[NJSC32_MAX_TARGET_ID + 1];
};

#ifdef _KERNEL
void	njsc32_attach(struct njsc32_softc *);
int	njsc32_detach(struct njsc32_softc *, int);
int	njsc32_intr(void *);
#endif

#endif	/* _NJSC32VAR_H_ */