cissvar.h revision 87011
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 87011 2001-11-27 23:08:37Z msmith $
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/************************************************************************
7587011Smsmith * Command queue statistics
7687011Smsmith */
7787011Smsmith
7887011Smsmith#define CISSQ_FREE	0
7987011Smsmith#define CISSQ_BUSY	1
8087011Smsmith#define CISSQ_COMPLETE	2
8187011Smsmith#define CISSQ_COUNT	3
8287011Smsmith
8387011Smsmithstruct ciss_qstat
8487011Smsmith{
8587011Smsmith    u_int32_t	q_length;
8687011Smsmith    u_int32_t	q_max;
8787011Smsmith};
8887011Smsmith
8987011Smsmith/************************************************************************
9087011Smsmith * Driver version.  Only really significant to the ACU interface.
9187011Smsmith */
9287011Smsmith#define CISS_DRIVER_VERSION	20011009
9387011Smsmith
9487011Smsmith/************************************************************************
9587011Smsmith * Driver data structures
9687011Smsmith */
9787011Smsmith
9887011Smsmith/*
9987011Smsmith * Each command issued to the adapter is managed by a request
10087011Smsmith * structure.
10187011Smsmith */
10287011Smsmithstruct ciss_request
10387011Smsmith{
10487011Smsmith    TAILQ_ENTRY(ciss_request)	cr_link;
10587011Smsmith    int				cr_onq;		/* which queue we are on */
10687011Smsmith
10787011Smsmith    struct ciss_softc		*cr_sc;		/* controller softc */
10887011Smsmith    void			*cr_data;	/* data buffer */
10987011Smsmith    u_int32_t			cr_length;	/* data length */
11087011Smsmith    bus_dmamap_t		cr_datamap;	/* DMA map for data */
11187011Smsmith    int				cr_tag;
11287011Smsmith    int				cr_flags;
11387011Smsmith#define CISS_REQ_MAPPED		(1<<0)		/* data mapped */
11487011Smsmith#define CISS_REQ_SLEEP		(1<<1)		/* submitter sleeping */
11587011Smsmith#define CISS_REQ_POLL		(1<<2)		/* submitter polling */
11687011Smsmith#define CISS_REQ_DATAOUT	(1<<3)		/* data host->adapter */
11787011Smsmith#define CISS_REQ_DATAIN		(1<<4)		/* data adapter->host */
11887011Smsmith
11987011Smsmith    void			(* cr_complete)(struct ciss_request *);
12087011Smsmith    void			*cr_private;
12187011Smsmith};
12287011Smsmith
12387011Smsmith/*
12487011Smsmith * The adapter command structure is defined with a zero-length
12587011Smsmith * scatter/gather list size.  In practise, we want space for a
12687011Smsmith * scatter-gather list, and we also want to avoid having commands
12787011Smsmith * cross page boundaries.
12887011Smsmith *
12987011Smsmith * Note that 512 bytes yields 28 scatter/gather entries, or the
13087011Smsmith * ability to map (26 * PAGE_SIZE) + 2 bytes of data.  On x86, this is
13187011Smsmith * 104kB.  256 bytes would only yield 12 entries, giving a mere 40kB,
13287011Smsmith * too small.
13387011Smsmith */
13487011Smsmith
13587011Smsmith#define CISS_COMMAND_ALLOC_SIZE		512	/* XXX tune to get sensible s/g list length */
13687011Smsmith#define CISS_COMMAND_SG_LENGTH	((CISS_COMMAND_ALLOC_SIZE - sizeof(struct ciss_command)) \
13787011Smsmith				 / sizeof(struct ciss_sg_entry))
13887011Smsmith
13987011Smsmith/*
14087011Smsmith * Per-logical-drive data.
14187011Smsmith */
14287011Smsmithstruct ciss_ldrive
14387011Smsmith{
14487011Smsmith    union ciss_device_address	cl_address;
14587011Smsmith
14687011Smsmith    int				cl_status;
14787011Smsmith#define CISS_LD_NONEXISTENT	0
14887011Smsmith#define CISS_LD_ONLINE		1
14987011Smsmith#define CISS_LD_OFFLINE		2
15087011Smsmith
15187011Smsmith    struct ciss_bmic_id_ldrive	*cl_ldrive;
15287011Smsmith    struct ciss_bmic_id_lstatus	*cl_lstatus;
15387011Smsmith
15487011Smsmith    char			cl_name[16];		/* device name */
15587011Smsmith};
15687011Smsmith
15787011Smsmith/*
15887011Smsmith * Per-adapter data
15987011Smsmith */
16087011Smsmithstruct ciss_softc
16187011Smsmith{
16287011Smsmith    /* bus connections */
16387011Smsmith    device_t			ciss_dev;		/* bus attachment */
16487011Smsmith    dev_t			ciss_dev_t;		/* control device */
16587011Smsmith
16687011Smsmith    struct resource		*ciss_regs_resource;	/* register interface window */
16787011Smsmith    int				ciss_regs_rid;		/* resource ID */
16887011Smsmith    bus_space_handle_t		ciss_regs_bhandle;	/* bus space handle */
16987011Smsmith    bus_space_tag_t		ciss_regs_btag;		/* bus space tag */
17087011Smsmith
17187011Smsmith    struct resource		*ciss_cfg_resource;	/* config struct interface window */
17287011Smsmith    int				ciss_cfg_rid;		/* resource ID */
17387011Smsmith    struct ciss_config_table	*ciss_cfg;		/* config table in adapter memory */
17487011Smsmith    struct ciss_bmic_id_table	*ciss_id;		/* ID table in host memory */
17587011Smsmith    u_int32_t			ciss_heartbeat;		/* last heartbeat value */
17687011Smsmith    int				ciss_heart_attack;	/* number of times we have seen this value */
17787011Smsmith
17887011Smsmith    struct resource		*ciss_irq_resource;	/* interrupt */
17987011Smsmith    int				ciss_irq_rid;		/* resource ID */
18087011Smsmith    void			*ciss_intr;		/* interrupt handle */
18187011Smsmith
18287011Smsmith    bus_dma_tag_t		ciss_parent_dmat;	/* parent DMA tag */
18387011Smsmith    bus_dma_tag_t		ciss_buffer_dmat;	/* data buffer/command DMA tag */
18487011Smsmith
18587011Smsmith    u_int32_t			ciss_interrupt_mask;	/* controller interrupt mask bits */
18687011Smsmith
18787011Smsmith    int				ciss_max_requests;
18887011Smsmith    struct ciss_request		ciss_request[CISS_MAX_REQUESTS];	/* requests */
18987011Smsmith    void			*ciss_command;		/* command structures */
19087011Smsmith    bus_dma_tag_t		ciss_command_dmat;	/* command DMA tag */
19187011Smsmith    bus_dmamap_t		ciss_command_map;	/* command DMA map */
19287011Smsmith    u_int32_t			ciss_command_phys;	/* command array base address */
19387011Smsmith    TAILQ_HEAD(,ciss_request)	ciss_free;		/* requests available for reuse */
19487011Smsmith    TAILQ_HEAD(,ciss_request)	ciss_busy;		/* requests in the adapter */
19587011Smsmith    TAILQ_HEAD(,ciss_request)	ciss_complete;		/* requests which have been returned by the adapter */
19687011Smsmith
19787011Smsmith    struct callout_handle	ciss_periodic;		/* periodic event handling */
19887011Smsmith    struct ciss_request		*ciss_periodic_notify;	/* notify callback request */
19987011Smsmith
20087011Smsmith    struct ciss_notify		ciss_notify[CISS_MAX_EVENTS];
20187011Smsmith    int				ciss_notify_head;	/* saved-event ringbuffer */
20287011Smsmith    int				ciss_notify_tail;
20387011Smsmith
20487011Smsmith    struct ciss_ldrive		ciss_logical[CISS_MAX_LOGICAL];
20587011Smsmith
20687011Smsmith    struct cam_devq		*ciss_cam_devq;
20787011Smsmith    struct cam_sim		*ciss_cam_sim;
20887011Smsmith    struct cam_path		*ciss_cam_path;
20987011Smsmith
21087011Smsmith    int				ciss_flags;
21187011Smsmith#define CISS_FLAG_NOTIFY_OK	(1<<0)		/* notify command running OK */
21287011Smsmith#define CISS_FLAG_CONTROL_OPEN	(1<<1)		/* control device is open */
21387011Smsmith#define CISS_FLAG_ABORTING	(1<<2)		/* driver is going away */
21487011Smsmith#define CISS_FLAG_RUNNING	(1<<3)		/* driver is running (interrupts usable) */
21587011Smsmith
21687011Smsmith#define CISS_FLAG_FAKE_SYNCH	(1<<16)		/* needs SYNCHRONISE_CACHE faked */
21787011Smsmith#define CISS_FLAG_BMIC_ABORT	(1<<17)		/* use BMIC command to abort Notify on Event */
21887011Smsmith
21987011Smsmith    struct ciss_qstat		ciss_qstat[CISSQ_COUNT];	/* queue statistics */
22087011Smsmith};
22187011Smsmith
22287011Smsmith/*
22387011Smsmith * Given a request tag, find the corresponding command in virtual or
22487011Smsmith * physical space.
22587011Smsmith *
22687011Smsmith * The arithmetic here is due to the allocation of ciss_command structures
22787011Smsmith * inside CISS_COMMAND_ALLOC_SIZE blocks.  See the comment at the definition
22887011Smsmith * of CISS_COMMAND_ALLOC_SIZE above.
22987011Smsmith */
23087011Smsmith#define CISS_FIND_COMMAND(cr)							\
23187011Smsmith	(struct ciss_command *)((u_int8_t *)(cr)->cr_sc->ciss_command +		\
23287011Smsmith				((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE))
23387011Smsmith#define CISS_FIND_COMMANDPHYS(cr)	((cr)->cr_sc->ciss_command_phys + \
23487011Smsmith					 ((cr)->cr_tag * CISS_COMMAND_ALLOC_SIZE))
23587011Smsmith
23687011Smsmith/************************************************************************
23787011Smsmith * Debugging/diagnostic output.
23887011Smsmith */
23987011Smsmith
24087011Smsmith/*
24187011Smsmith * Debugging levels:
24287011Smsmith *  0 - quiet, only emit warnings
24387011Smsmith *  1 - talkative, log major events, but nothing on the I/O path
24487011Smsmith *  2 - noisy, log events on the I/O path
24587011Smsmith *  3 - extremely noisy, log items in loops
24687011Smsmith */
24787011Smsmith#ifdef CISS_DEBUG
24887011Smsmith# define debug(level, fmt, args...)							\
24987011Smsmith	do {										\
25087011Smsmith	    if (level <= CISS_DEBUG) printf("%s: " fmt "\n", __FUNCTION__ , ##args);	\
25187011Smsmith	} while(0)
25287011Smsmith# define debug_called(level)						\
25387011Smsmith	do {								\
25487011Smsmith	    if (level <= CISS_DEBUG) printf(__FUNCTION__ ": called\n");	\
25587011Smsmith	} while(0)
25687011Smsmith# define debug_struct(s)		printf("  SIZE %s: %d\n", #s, sizeof(struct s))
25787011Smsmith# define debug_union(s)			printf("  SIZE %s: %d\n", #s, sizeof(union s))
25887011Smsmith# define debug_type(s)			printf("  SIZE %s: %d\n", #s, sizeof(s))
25987011Smsmith# define debug_field(s, f)		printf("  OFFSET %s.%s: %d\n", #s, #f, ((int)&(((struct s *)0)->f)))
26087011Smsmith# define debug_const(c)			printf("  CONST %s %d/0x%x\n", #c, c, c);
26187011Smsmith#else
26287011Smsmith# define debug(level, fmt, args...)
26387011Smsmith# define debug_called(level)
26487011Smsmith# define debug_struct(s)
26587011Smsmith# define debug_union(s)
26687011Smsmith# define debug_type(s)
26787011Smsmith# define debug_field(s, f)
26887011Smsmith# define debug_const(c)
26987011Smsmith#endif
27087011Smsmith
27187011Smsmith#define ciss_printf(sc, fmt, args...)	device_printf(sc->ciss_dev, fmt , ##args)
27287011Smsmith
27387011Smsmith/************************************************************************
27487011Smsmith * Queue primitives
27587011Smsmith */
27687011Smsmith
27787011Smsmith#define CISSQ_ADD(sc, qname)					\
27887011Smsmith	do {							\
27987011Smsmith	    struct ciss_qstat *qs = &(sc)->ciss_qstat[qname];	\
28087011Smsmith								\
28187011Smsmith	    qs->q_length++;					\
28287011Smsmith	    if (qs->q_length > qs->q_max)			\
28387011Smsmith		qs->q_max = qs->q_length;			\
28487011Smsmith	} while(0)
28587011Smsmith
28687011Smsmith#define CISSQ_REMOVE(sc, qname)    (sc)->ciss_qstat[qname].q_length--
28787011Smsmith#define CISSQ_INIT(sc, qname)			\
28887011Smsmith	do {					\
28987011Smsmith	    sc->ciss_qstat[qname].q_length = 0;	\
29087011Smsmith	    sc->ciss_qstat[qname].q_max = 0;	\
29187011Smsmith	} while(0)
29287011Smsmith
29387011Smsmith
29487011Smsmith#define CISSQ_REQUEST_QUEUE(name, index)				\
29587011Smsmithstatic __inline void							\
29687011Smsmithciss_initq_ ## name (struct ciss_softc *sc)				\
29787011Smsmith{									\
29887011Smsmith    TAILQ_INIT(&sc->ciss_ ## name);					\
29987011Smsmith    CISSQ_INIT(sc, index);						\
30087011Smsmith}									\
30187011Smsmithstatic __inline void							\
30287011Smsmithciss_enqueue_ ## name (struct ciss_request *cr)				\
30387011Smsmith{									\
30487011Smsmith    int		s;							\
30587011Smsmith									\
30687011Smsmith    s = splcam();							\
30787011Smsmith    TAILQ_INSERT_TAIL(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
30887011Smsmith    CISSQ_ADD(cr->cr_sc, index);					\
30987011Smsmith    cr->cr_onq = index;							\
31087011Smsmith    splx(s);								\
31187011Smsmith}									\
31287011Smsmithstatic __inline void							\
31387011Smsmithciss_requeue_ ## name (struct ciss_request *cr)				\
31487011Smsmith{									\
31587011Smsmith    int		s;							\
31687011Smsmith									\
31787011Smsmith    s = splcam();							\
31887011Smsmith    TAILQ_INSERT_HEAD(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
31987011Smsmith    CISSQ_ADD(cr->cr_sc, index);					\
32087011Smsmith    cr->cr_onq = index;							\
32187011Smsmith    splx(s);								\
32287011Smsmith}									\
32387011Smsmithstatic __inline struct ciss_request *					\
32487011Smsmithciss_dequeue_ ## name (struct ciss_softc *sc)				\
32587011Smsmith{									\
32687011Smsmith    struct ciss_request	*cr;						\
32787011Smsmith    int			s;						\
32887011Smsmith									\
32987011Smsmith    s = splcam();							\
33087011Smsmith    if ((cr = TAILQ_FIRST(&sc->ciss_ ## name)) != NULL) {		\
33187011Smsmith	TAILQ_REMOVE(&sc->ciss_ ## name, cr, cr_link);			\
33287011Smsmith	CISSQ_REMOVE(sc, index);					\
33387011Smsmith	cr->cr_onq = -1;						\
33487011Smsmith    }									\
33587011Smsmith    splx(s);								\
33687011Smsmith    return(cr);								\
33787011Smsmith}									\
33887011Smsmithstatic __inline int							\
33987011Smsmithciss_remove_ ## name (struct ciss_request *cr)				\
34087011Smsmith{									\
34187011Smsmith    int			s, error;					\
34287011Smsmith									\
34387011Smsmith    s = splcam();							\
34487011Smsmith    if (cr->cr_onq != index) {						\
34587011Smsmith	printf("request on queue %d (expected %d)\n", cr->cr_onq, index);\
34687011Smsmith	error = 1;							\
34787011Smsmith    } else {								\
34887011Smsmith	TAILQ_REMOVE(&cr->cr_sc->ciss_ ## name, cr, cr_link);		\
34987011Smsmith	CISSQ_REMOVE(cr->cr_sc, index);					\
35087011Smsmith	cr->cr_onq = -1;						\
35187011Smsmith	error = 0;							\
35287011Smsmith    }									\
35387011Smsmith    splx(s);								\
35487011Smsmith    return(error);							\
35587011Smsmith}									\
35687011Smsmithstruct hack
35787011Smsmith
35887011SmsmithCISSQ_REQUEST_QUEUE(free, CISSQ_FREE);
35987011SmsmithCISSQ_REQUEST_QUEUE(busy, CISSQ_BUSY);
36087011SmsmithCISSQ_REQUEST_QUEUE(complete, CISSQ_COMPLETE);
36187011Smsmith
36287011Smsmith/********************************************************************************
36387011Smsmith * space-fill a character string
36487011Smsmith */
36587011Smsmithstatic __inline void
36687011Smsmithpadstr(char *targ, const char *src, int len)
36787011Smsmith{
36887011Smsmith    while (len-- > 0) {
36987011Smsmith	if (*src != 0) {
37087011Smsmith	    *targ++ = *src++;
37187011Smsmith	} else {
37287011Smsmith	    *targ++ = ' ';
37387011Smsmith	}
37487011Smsmith    }
37587011Smsmith}
376