cissvar.h revision 110366
187011Smsmith/*-
287011Smsmith * Copyright (c) 2001 Michael Smith
387011Smsmith * All rights reserved.
487011Smsmith *
587011Smsmith * Redistribution and use in source and binary forms, with or without
687011Smsmith * modification, are permitted provided that the following conditions
787011Smsmith * are met:
887011Smsmith * 1. Redistributions of source code must retain the above copyright
987011Smsmith *    notice, this list of conditions and the following disclaimer.
1087011Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1187011Smsmith *    notice, this list of conditions and the following disclaimer in the
1287011Smsmith *    documentation and/or other materials provided with the distribution.
1387011Smsmith *
1487011Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1587011Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1687011Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1787011Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1887011Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1987011Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2087011Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2187011Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2287011Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2387011Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2487011Smsmith * SUCH DAMAGE.
2587011Smsmith *
2687011Smsmith *	$FreeBSD: head/sys/dev/ciss/cissvar.h 110366 2003-02-05 08:43:46Z ps $
2787011Smsmith */
2887011Smsmith
2987011Smsmith/*
3087011Smsmith * CISS adapter driver datastructures
3187011Smsmith */
3287011Smsmith
3387011Smsmith/************************************************************************
3487011Smsmith * Tunable parameters
3587011Smsmith */
3687011Smsmith
3787011Smsmith/*
3887011Smsmith * There is no guaranteed upper bound on the number of concurrent
3987011Smsmith * commands an adapter may claim to support.  Cap it at a reasonable
4087011Smsmith * value.
4187011Smsmith */
4287011Smsmith#define CISS_MAX_REQUESTS	256
4387011Smsmith
4487011Smsmith/*
4587011Smsmith * Maximum number of logical drives we support.
4687011Smsmith */
4787011Smsmith#define CISS_MAX_LOGICAL	15
4887011Smsmith
4987011Smsmith/*
5087011Smsmith * Interrupt reduction can be controlled by tuning the interrupt
5187011Smsmith * coalesce delay and count paramters.  The delay (in microseconds)
5287011Smsmith * defers delivery of interrupts to increase the chance of there being
5387011Smsmith * more than one completed command ready when the interrupt is
5487011Smsmith * delivered.  The count expedites the delivery of the interrupt when
5587011Smsmith * the given number of commands are ready.
5687011Smsmith *
5787011Smsmith * If the delay is set to 0, interrupts are delivered immediately.
5887011Smsmith */
5987011Smsmith#define CISS_INTERRUPT_COALESCE_DELAY	1000
6087011Smsmith#define CISS_INTERRUPT_COALESCE_COUNT	16
6187011Smsmith
6287011Smsmith/*
6387011Smsmith * Heartbeat routine timeout in seconds.  Note that since event
6487011Smsmith * handling is performed on a callback basis, we don't need this to
6587011Smsmith * run very often.
6687011Smsmith */
6787011Smsmith#define CISS_HEARTBEAT_RATE		10
6887011Smsmith
6987011Smsmith/*
7087011Smsmith * Maximum number of events we will queue for a monitoring utility.
7187011Smsmith */
7287011Smsmith#define CISS_MAX_EVENTS		32
7387011Smsmith
7487011Smsmith/************************************************************************
7587187Smsmith * Compatibility with older versions of FreeBSD
7687187Smsmith */
7787187Smsmith#if __FreeBSD_version < 440001
7887187Smsmith#warning testing old-FreeBSD compat
7987187Smsmithtypedef struct proc	d_thread_t;
8087187Smsmith#endif
8187187Smsmith
8287187Smsmith/************************************************************************
8387011Smsmith * Command queue statistics
8487011Smsmith */
8587011Smsmith
8687011Smsmith#define CISSQ_FREE	0
8787011Smsmith#define CISSQ_BUSY	1
8887011Smsmith#define CISSQ_COMPLETE	2
8987011Smsmith#define CISSQ_COUNT	3
9087011Smsmith
9187011Smsmithstruct ciss_qstat
9287011Smsmith{
9387011Smsmith    u_int32_t	q_length;
9487011Smsmith    u_int32_t	q_max;
9587011Smsmith};
9687011Smsmith
9787011Smsmith/************************************************************************
9887011Smsmith * Driver version.  Only really significant to the ACU interface.
9987011Smsmith */
10087187Smsmith#define CISS_DRIVER_VERSION	20011201
10187011Smsmith
10287011Smsmith/************************************************************************
10387011Smsmith * Driver data structures
10487011Smsmith */
10587011Smsmith
10687011Smsmith/*
10787011Smsmith * Each command issued to the adapter is managed by a request
10887011Smsmith * structure.
10987011Smsmith */
11087011Smsmithstruct ciss_request
11187011Smsmith{
11287011Smsmith    TAILQ_ENTRY(ciss_request)	cr_link;
11387011Smsmith    int				cr_onq;		/* which queue we are on */
11487011Smsmith
11587011Smsmith    struct ciss_softc		*cr_sc;		/* controller softc */
11687011Smsmith    void			*cr_data;	/* data buffer */
11787011Smsmith    u_int32_t			cr_length;	/* data length */
11887011Smsmith    bus_dmamap_t		cr_datamap;	/* DMA map for data */
11987011Smsmith    int				cr_tag;
12087011Smsmith    int				cr_flags;
12187011Smsmith#define CISS_REQ_MAPPED		(1<<0)		/* data mapped */
12287011Smsmith#define CISS_REQ_SLEEP		(1<<1)		/* submitter sleeping */
12387011Smsmith#define CISS_REQ_POLL		(1<<2)		/* submitter polling */
12487011Smsmith#define CISS_REQ_DATAOUT	(1<<3)		/* data host->adapter */
12587011Smsmith#define CISS_REQ_DATAIN		(1<<4)		/* data adapter->host */
12687011Smsmith
12787011Smsmith    void			(* cr_complete)(struct ciss_request *);
12887011Smsmith    void			*cr_private;
12987011Smsmith};
13087011Smsmith
13187011Smsmith/*
13287011Smsmith * The adapter command structure is defined with a zero-length
13387011Smsmith * scatter/gather list size.  In practise, we want space for a
13487011Smsmith * scatter-gather list, and we also want to avoid having commands
13587011Smsmith * cross page boundaries.
13687011Smsmith *
13787011Smsmith * Note that 512 bytes yields 28 scatter/gather entries, or the
13887011Smsmith * ability to map (26 * PAGE_SIZE) + 2 bytes of data.  On x86, this is
13987011Smsmith * 104kB.  256 bytes would only yield 12 entries, giving a mere 40kB,
14087011Smsmith * too small.
14187011Smsmith */
14287011Smsmith
14387011Smsmith#define CISS_COMMAND_ALLOC_SIZE		512	/* XXX tune to get sensible s/g list length */
14487011Smsmith#define CISS_COMMAND_SG_LENGTH	((CISS_COMMAND_ALLOC_SIZE - sizeof(struct ciss_command)) \
14587011Smsmith				 / sizeof(struct ciss_sg_entry))
14687011Smsmith
14787011Smsmith/*
14887011Smsmith * Per-logical-drive data.
14987011Smsmith */
15087011Smsmithstruct ciss_ldrive
15187011Smsmith{
15287011Smsmith    union ciss_device_address	cl_address;
15387011Smsmith
15487011Smsmith    int				cl_status;
15587011Smsmith#define CISS_LD_NONEXISTENT	0
15687011Smsmith#define CISS_LD_ONLINE		1
15787011Smsmith#define CISS_LD_OFFLINE		2
15887011Smsmith
15987011Smsmith    struct ciss_bmic_id_ldrive	*cl_ldrive;
16087011Smsmith    struct ciss_bmic_id_lstatus	*cl_lstatus;
161110366Sps    struct ciss_ldrive_geometry	cl_geometry;
16287011Smsmith
16387011Smsmith    char			cl_name[16];		/* device name */
16487011Smsmith};
16587011Smsmith
16687011Smsmith/*
16787011Smsmith * Per-adapter data
16887011Smsmith */
16987011Smsmithstruct ciss_softc
17087011Smsmith{
17187011Smsmith    /* bus connections */
17287011Smsmith    device_t			ciss_dev;		/* bus attachment */
17387011Smsmith    dev_t			ciss_dev_t;		/* control device */
17487011Smsmith
17587011Smsmith    struct resource		*ciss_regs_resource;	/* register interface window */
17687011Smsmith    int				ciss_regs_rid;		/* resource ID */
17787011Smsmith    bus_space_handle_t		ciss_regs_bhandle;	/* bus space handle */
17887011Smsmith    bus_space_tag_t		ciss_regs_btag;		/* bus space tag */
17987011Smsmith
18087011Smsmith    struct resource		*ciss_cfg_resource;	/* config struct interface window */
18187011Smsmith    int				ciss_cfg_rid;		/* resource ID */
18287011Smsmith    struct ciss_config_table	*ciss_cfg;		/* config table in adapter memory */
18387011Smsmith    struct ciss_bmic_id_table	*ciss_id;		/* ID table in host memory */
18487011Smsmith    u_int32_t			ciss_heartbeat;		/* last heartbeat value */
18587011Smsmith    int				ciss_heart_attack;	/* number of times we have seen this value */
18687011Smsmith
18787011Smsmith    struct resource		*ciss_irq_resource;	/* interrupt */
18887011Smsmith    int				ciss_irq_rid;		/* resource ID */
18987011Smsmith    void			*ciss_intr;		/* interrupt handle */
19087011Smsmith
19187011Smsmith    bus_dma_tag_t		ciss_parent_dmat;	/* parent DMA tag */
19287011Smsmith    bus_dma_tag_t		ciss_buffer_dmat;	/* data buffer/command DMA tag */
19387011Smsmith
19487011Smsmith    u_int32_t			ciss_interrupt_mask;	/* controller interrupt mask bits */
19587011Smsmith
19687011Smsmith    int				ciss_max_requests;
19787011Smsmith    struct ciss_request		ciss_request[CISS_MAX_REQUESTS];	/* requests */
19887011Smsmith    void			*ciss_command;		/* command structures */
19987011Smsmith    bus_dma_tag_t		ciss_command_dmat;	/* command DMA tag */
20087011Smsmith    bus_dmamap_t		ciss_command_map;	/* command DMA map */
20187011Smsmith    u_int32_t			ciss_command_phys;	/* command array base address */
20287011Smsmith    TAILQ_HEAD(,ciss_request)	ciss_free;		/* requests available for reuse */
20387011Smsmith    TAILQ_HEAD(,ciss_request)	ciss_busy;		/* requests in the adapter */
20487011Smsmith    TAILQ_HEAD(,ciss_request)	ciss_complete;		/* requests which have been returned by the adapter */
20587011Smsmith
20687011Smsmith    struct callout_handle	ciss_periodic;		/* periodic event handling */
20787011Smsmith    struct ciss_request		*ciss_periodic_notify;	/* notify callback request */
20887011Smsmith
20987011Smsmith    struct ciss_notify		ciss_notify[CISS_MAX_EVENTS];
21087011Smsmith    int				ciss_notify_head;	/* saved-event ringbuffer */
21187011Smsmith    int				ciss_notify_tail;
21287011Smsmith
21387011Smsmith    struct ciss_ldrive		ciss_logical[CISS_MAX_LOGICAL];
21487011Smsmith
21587011Smsmith    struct cam_devq		*ciss_cam_devq;
21687011Smsmith    struct cam_sim		*ciss_cam_sim;
21787011Smsmith    struct cam_path		*ciss_cam_path;
21887011Smsmith
21987011Smsmith    int				ciss_flags;
22087011Smsmith#define CISS_FLAG_NOTIFY_OK	(1<<0)		/* notify command running OK */
22187011Smsmith#define CISS_FLAG_CONTROL_OPEN	(1<<1)		/* control device is open */
22287011Smsmith#define CISS_FLAG_ABORTING	(1<<2)		/* driver is going away */
22387011Smsmith#define CISS_FLAG_RUNNING	(1<<3)		/* driver is running (interrupts usable) */
22487011Smsmith
22587011Smsmith#define CISS_FLAG_FAKE_SYNCH	(1<<16)		/* needs SYNCHRONISE_CACHE faked */
22687011Smsmith#define CISS_FLAG_BMIC_ABORT	(1<<17)		/* use BMIC command to abort Notify on Event */
22787011Smsmith
22887011Smsmith    struct ciss_qstat		ciss_qstat[CISSQ_COUNT];	/* queue statistics */
22987011Smsmith};
23087011Smsmith
23187011Smsmith/*
23287011Smsmith * Given a request tag, find the corresponding command in virtual or
23387011Smsmith * physical space.
23487011Smsmith *
23587011Smsmith * The arithmetic here is due to the allocation of ciss_command structures
23687011Smsmith * inside CISS_COMMAND_ALLOC_SIZE blocks.  See the comment at the definition
23787011Smsmith * of CISS_COMMAND_ALLOC_SIZE above.
23887011Smsmith */
23987011Smsmith#define CISS_FIND_COMMAND(cr)							\
24087011Smsmith	(struct ciss_command *)((u_int8_t *)(cr)->cr_sc->ciss_command +		\
24187011Smsmith				((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE))
24287011Smsmith#define CISS_FIND_COMMANDPHYS(cr)	((cr)->cr_sc->ciss_command_phys + \
24387011Smsmith					 ((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE))
24487011Smsmith
24587011Smsmith/************************************************************************
24687011Smsmith * Debugging/diagnostic output.
24787011Smsmith */
24887011Smsmith
24987011Smsmith/*
25087011Smsmith * Debugging levels:
25187011Smsmith *  0 - quiet, only emit warnings
25287011Smsmith *  1 - talkative, log major events, but nothing on the I/O path
25387011Smsmith *  2 - noisy, log events on the I/O path
25487011Smsmith *  3 - extremely noisy, log items in loops
25587011Smsmith */
25687011Smsmith#ifdef CISS_DEBUG
25787011Smsmith# define debug(level, fmt, args...)							\
25887011Smsmith	do {										\
25987599Sobrien	    if (level <= CISS_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);	\
26087011Smsmith	} while(0)
26187011Smsmith# define debug_called(level)						\
26287011Smsmith	do {								\
26387599Sobrien	    if (level <= CISS_DEBUG) printf("%s: called\n", __func__);	\
26487011Smsmith	} while(0)
265106039Smux# define debug_struct(s)		printf("  SIZE %s: %zu\n", #s, sizeof(struct s))
266106039Smux# define debug_union(s)			printf("  SIZE %s: %zu\n", #s, sizeof(union s))
267106039Smux# define debug_type(s)			printf("  SIZE %s: %zu\n", #s, sizeof(s))
26887011Smsmith# define debug_field(s, f)		printf("  OFFSET %s.%s: %d\n", #s, #f, ((int)&(((struct s *)0)->f)))
269106039Smux# define debug_const(c)			printf("  CONST %s %jd/0x%jx\n", #c, (intmax_t)c, (intmax_t)c);
27087011Smsmith#else
27187011Smsmith# define debug(level, fmt, args...)
27287011Smsmith# define debug_called(level)
27387011Smsmith# define debug_struct(s)
27487011Smsmith# define debug_union(s)
27587011Smsmith# define debug_type(s)
27687011Smsmith# define debug_field(s, f)
27787011Smsmith# define debug_const(c)
27887011Smsmith#endif
27987011Smsmith
28087011Smsmith#define ciss_printf(sc, fmt, args...)	device_printf(sc->ciss_dev, fmt , ##args)
28187011Smsmith
28287011Smsmith/************************************************************************
28387011Smsmith * Queue primitives
28487011Smsmith */
28587011Smsmith
28687011Smsmith#define CISSQ_ADD(sc, qname)					\
28787011Smsmith	do {							\
28887011Smsmith	    struct ciss_qstat *qs = &(sc)->ciss_qstat[qname];	\
28987011Smsmith								\
29087011Smsmith	    qs->q_length++;					\
29187011Smsmith	    if (qs->q_length > qs->q_max)			\
29287011Smsmith		qs->q_max = qs->q_length;			\
29387011Smsmith	} while(0)
29487011Smsmith
29587011Smsmith#define CISSQ_REMOVE(sc, qname)    (sc)->ciss_qstat[qname].q_length--
29687011Smsmith#define CISSQ_INIT(sc, qname)			\
29787011Smsmith	do {					\
29887011Smsmith	    sc->ciss_qstat[qname].q_length = 0;	\
29987011Smsmith	    sc->ciss_qstat[qname].q_max = 0;	\
30087011Smsmith	} while(0)
30187011Smsmith
30287011Smsmith
30387011Smsmith#define CISSQ_REQUEST_QUEUE(name, index)				\
30487011Smsmithstatic __inline void							\
30587011Smsmithciss_initq_ ## name (struct ciss_softc *sc)				\
30687011Smsmith{									\
30787011Smsmith    TAILQ_INIT(&sc->ciss_ ## name);					\
30887011Smsmith    CISSQ_INIT(sc, index);						\
30987011Smsmith}									\
31087011Smsmithstatic __inline void							\
31187011Smsmithciss_enqueue_ ## name (struct ciss_request *cr)				\
31287011Smsmith{									\
31387011Smsmith    int		s;							\
31487011Smsmith									\
31587011Smsmith    s = splcam();							\
31687011Smsmith    TAILQ_INSERT_TAIL(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
31787011Smsmith    CISSQ_ADD(cr->cr_sc, index);					\
31887011Smsmith    cr->cr_onq = index;							\
31987011Smsmith    splx(s);								\
32087011Smsmith}									\
32187011Smsmithstatic __inline void							\
32287011Smsmithciss_requeue_ ## name (struct ciss_request *cr)				\
32387011Smsmith{									\
32487011Smsmith    int		s;							\
32587011Smsmith									\
32687011Smsmith    s = splcam();							\
32787011Smsmith    TAILQ_INSERT_HEAD(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
32887011Smsmith    CISSQ_ADD(cr->cr_sc, index);					\
32987011Smsmith    cr->cr_onq = index;							\
33087011Smsmith    splx(s);								\
33187011Smsmith}									\
33287011Smsmithstatic __inline struct ciss_request *					\
33387011Smsmithciss_dequeue_ ## name (struct ciss_softc *sc)				\
33487011Smsmith{									\
33587011Smsmith    struct ciss_request	*cr;						\
33687011Smsmith    int			s;						\
33787011Smsmith									\
33887011Smsmith    s = splcam();							\
33987011Smsmith    if ((cr = TAILQ_FIRST(&sc->ciss_ ## name)) != NULL) {		\
34087011Smsmith	TAILQ_REMOVE(&sc->ciss_ ## name, cr, cr_link);			\
34187011Smsmith	CISSQ_REMOVE(sc, index);					\
34287011Smsmith	cr->cr_onq = -1;						\
34387011Smsmith    }									\
34487011Smsmith    splx(s);								\
34587011Smsmith    return(cr);								\
34687011Smsmith}									\
34787011Smsmithstatic __inline int							\
34887011Smsmithciss_remove_ ## name (struct ciss_request *cr)				\
34987011Smsmith{									\
35087011Smsmith    int			s, error;					\
35187011Smsmith									\
35287011Smsmith    s = splcam();							\
35387011Smsmith    if (cr->cr_onq != index) {						\
35487011Smsmith	printf("request on queue %d (expected %d)\n", cr->cr_onq, index);\
35587011Smsmith	error = 1;							\
35687011Smsmith    } else {								\
35787011Smsmith	TAILQ_REMOVE(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
35887011Smsmith	CISSQ_REMOVE(cr->cr_sc, index);					\
35987011Smsmith	cr->cr_onq = -1;						\
36087011Smsmith	error = 0;							\
36187011Smsmith    }									\
36287011Smsmith    splx(s);								\
36387011Smsmith    return(error);							\
36487011Smsmith}									\
36587011Smsmithstruct hack
36687011Smsmith
36787011SmsmithCISSQ_REQUEST_QUEUE(free, CISSQ_FREE);
36887011SmsmithCISSQ_REQUEST_QUEUE(busy, CISSQ_BUSY);
36987011SmsmithCISSQ_REQUEST_QUEUE(complete, CISSQ_COMPLETE);
37087011Smsmith
37187011Smsmith/********************************************************************************
37287011Smsmith * space-fill a character string
37387011Smsmith */
37487011Smsmithstatic __inline void
37587011Smsmithpadstr(char *targ, const char *src, int len)
37687011Smsmith{
37787011Smsmith    while (len-- > 0) {
37887011Smsmith	if (*src != 0) {
37987011Smsmith	    *targ++ = *src++;
38087011Smsmith	} else {
38187011Smsmith	    *targ++ = ' ';
38287011Smsmith	}
38387011Smsmith    }
38487011Smsmith}
385