xref: /freebsd/sys/dev/mpt/mpt.h (revision 5cc0208a757d2b37c43398bf68fec145568c1a25)
19b631363SMatt Jacob /* $FreeBSD$ */
2098ca2bdSWarner Losh /*-
39b631363SMatt Jacob  * Generic defines for LSI '909 FC  adapters.
49b631363SMatt Jacob  * FreeBSD Version.
59b631363SMatt Jacob  *
69b631363SMatt Jacob  * Copyright (c)  2000, 2001 by Greg Ansley
79b631363SMatt Jacob  *
89b631363SMatt Jacob  * Redistribution and use in source and binary forms, with or without
99b631363SMatt Jacob  * modification, are permitted provided that the following conditions
109b631363SMatt Jacob  * are met:
119b631363SMatt Jacob  * 1. Redistributions of source code must retain the above copyright
129b631363SMatt Jacob  *    notice immediately at the beginning of the file, without modification,
139b631363SMatt Jacob  *    this list of conditions, and the following disclaimer.
149b631363SMatt Jacob  * 2. The name of the author may not be used to endorse or promote products
159b631363SMatt Jacob  *    derived from this software without specific prior written permission.
169b631363SMatt Jacob  *
179b631363SMatt Jacob  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
189b631363SMatt Jacob  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199b631363SMatt Jacob  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
209b631363SMatt Jacob  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
219b631363SMatt Jacob  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
229b631363SMatt Jacob  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
239b631363SMatt Jacob  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
249b631363SMatt Jacob  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
259b631363SMatt Jacob  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
269b631363SMatt Jacob  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
279b631363SMatt Jacob  * SUCH DAMAGE.
28b0a2fdeeSScott Long  *
29b0a2fdeeSScott Long  * Additional Copyright (c) 2002 by Matthew Jacob under same license.
309b631363SMatt Jacob  */
319b631363SMatt Jacob /*
32b0a2fdeeSScott Long  * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
33b0a2fdeeSScott Long  * Copyright (c) 2004, 2005 Justin T. Gibbs
34b0a2fdeeSScott Long  * Copyright (c) 2005, WHEEL Sp. z o.o.
35b0a2fdeeSScott Long  * All rights reserved.
36b0a2fdeeSScott Long  *
37b0a2fdeeSScott Long  * Redistribution and use in source and binary forms, with or without
38b0a2fdeeSScott Long  * modification, are permitted provided that the following conditions are
39b0a2fdeeSScott Long  * met:
40b0a2fdeeSScott Long  * 1. Redistributions of source code must retain the above copyright
41b0a2fdeeSScott Long  *    notice, this list of conditions and the following disclaimer.
42b0a2fdeeSScott Long  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
43b0a2fdeeSScott Long  *    substantially similar to the "NO WARRANTY" disclaimer below
44b0a2fdeeSScott Long  *    ("Disclaimer") and any redistribution must be conditioned upon including
45b0a2fdeeSScott Long  *    a substantially similar Disclaimer requirement for further binary
46b0a2fdeeSScott Long  *    redistribution.
47286e947fSJustin T. Gibbs  * 3. Neither the names of the above listed copyright holders nor the names
48286e947fSJustin T. Gibbs  *    of any contributors may be used to endorse or promote products derived
49286e947fSJustin T. Gibbs  *    from this software without specific prior written permission.
50b0a2fdeeSScott Long  *
51b0a2fdeeSScott Long  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
52b0a2fdeeSScott Long  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53b0a2fdeeSScott Long  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54b0a2fdeeSScott Long  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
55b0a2fdeeSScott Long  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56b0a2fdeeSScott Long  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57b0a2fdeeSScott Long  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58b0a2fdeeSScott Long  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59b0a2fdeeSScott Long  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60b0a2fdeeSScott Long  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
61b0a2fdeeSScott Long  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
629b631363SMatt Jacob  */
639b631363SMatt Jacob 
649b631363SMatt Jacob #ifndef _MPT_H_
659b631363SMatt Jacob #define _MPT_H_
66b0a2fdeeSScott Long 
67b0a2fdeeSScott Long /********************************* OS Includes ********************************/
68b0a2fdeeSScott Long #include <sys/types.h>
69b0a2fdeeSScott Long #include <sys/param.h>
70b0a2fdeeSScott Long #include <sys/systm.h>
71b0a2fdeeSScott Long #include <sys/endian.h>
72b0a2fdeeSScott Long #include <sys/eventhandler.h>
73b0a2fdeeSScott Long #if __FreeBSD_version < 500000
74b0a2fdeeSScott Long #include <sys/kernel.h>
75b0a2fdeeSScott Long #include <sys/queue.h>
76b0a2fdeeSScott Long #include <sys/malloc.h>
77b0a2fdeeSScott Long #else
78b0a2fdeeSScott Long #include <sys/lock.h>
79b0a2fdeeSScott Long #include <sys/kernel.h>
80b0a2fdeeSScott Long #include <sys/queue.h>
81b0a2fdeeSScott Long #include <sys/malloc.h>
82b0a2fdeeSScott Long #include <sys/mutex.h>
83b0a2fdeeSScott Long #include <sys/condvar.h>
84b0a2fdeeSScott Long #endif
85b0a2fdeeSScott Long #include <sys/proc.h>
86b0a2fdeeSScott Long #include <sys/bus.h>
87b0a2fdeeSScott Long #include <sys/module.h>
88b0a2fdeeSScott Long 
89b0a2fdeeSScott Long #include <machine/bus.h>
90b0a2fdeeSScott Long #include <machine/clock.h>
91b0a2fdeeSScott Long #include <machine/cpu.h>
92b0a2fdeeSScott Long #include <machine/resource.h>
93b0a2fdeeSScott Long 
94b0a2fdeeSScott Long #include <sys/rman.h>
95b0a2fdeeSScott Long 
96b0a2fdeeSScott Long #include "opt_ddb.h"
97b0a2fdeeSScott Long 
98b0a2fdeeSScott Long /**************************** Register Definitions ****************************/
99b0a2fdeeSScott Long #include <dev/mpt/mpt_reg.h>
100b0a2fdeeSScott Long 
101b0a2fdeeSScott Long /******************************* MPI Definitions ******************************/
102b0a2fdeeSScott Long #include <dev/mpt/mpilib/mpi_type.h>
103b0a2fdeeSScott Long #include <dev/mpt/mpilib/mpi.h>
104b0a2fdeeSScott Long #include <dev/mpt/mpilib/mpi_cnfg.h>
105b0a2fdeeSScott Long #include <dev/mpt/mpilib/mpi_ioc.h>
106b0a2fdeeSScott Long #include <dev/mpt/mpilib/mpi_raid.h>
107b0a2fdeeSScott Long 
108b0a2fdeeSScott Long /* XXX For mpt_debug.c */
109b0a2fdeeSScott Long #include <dev/mpt/mpilib/mpi_init.h>
110b0a2fdeeSScott Long 
111b0a2fdeeSScott Long /****************************** Misc Definitions ******************************/
1129b631363SMatt Jacob #define MPT_OK (0)
1139b631363SMatt Jacob #define MPT_FAIL (0x10000)
1149b631363SMatt Jacob 
115b0a2fdeeSScott Long #define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array))
1169b631363SMatt Jacob 
117b0a2fdeeSScott Long /**************************** Forward Declarations ****************************/
118b0a2fdeeSScott Long struct mpt_softc;
119b0a2fdeeSScott Long struct mpt_personality;
120b0a2fdeeSScott Long typedef struct req_entry request_t;
1219b631363SMatt Jacob 
122b0a2fdeeSScott Long /************************* Personality Module Support *************************/
123b0a2fdeeSScott Long typedef int mpt_load_handler_t(struct mpt_personality *);
124b0a2fdeeSScott Long typedef int mpt_probe_handler_t(struct mpt_softc *);
125b0a2fdeeSScott Long typedef int mpt_attach_handler_t(struct mpt_softc *);
126b0a2fdeeSScott Long typedef int mpt_event_handler_t(struct mpt_softc *, request_t *,
127b0a2fdeeSScott Long 				MSG_EVENT_NOTIFY_REPLY *);
128b0a2fdeeSScott Long typedef void mpt_reset_handler_t(struct mpt_softc *, int /*type*/);
129b0a2fdeeSScott Long /* XXX Add return value and use for veto? */
130b0a2fdeeSScott Long typedef void mpt_shutdown_handler_t(struct mpt_softc *);
131b0a2fdeeSScott Long typedef void mpt_detach_handler_t(struct mpt_softc *);
132b0a2fdeeSScott Long typedef int mpt_unload_handler_t(struct mpt_personality *);
133b0a2fdeeSScott Long 
134b0a2fdeeSScott Long struct mpt_personality
135b0a2fdeeSScott Long {
136b0a2fdeeSScott Long 	const char		*name;
137b0a2fdeeSScott Long 	uint32_t		 id;		/* Assigned identifier. */
138b0a2fdeeSScott Long 	u_int			 use_count;	/* Instances using personality*/
139b0a2fdeeSScott Long 	mpt_load_handler_t	*load;		/* configure personailty */
140b0a2fdeeSScott Long #define MPT_PERS_FIRST_HANDLER(pers) (&(pers)->load)
141b0a2fdeeSScott Long 	mpt_probe_handler_t	*probe;		/* configure personailty */
142b0a2fdeeSScott Long 	mpt_attach_handler_t	*attach;	/* initialize device instance */
143b0a2fdeeSScott Long 	mpt_event_handler_t	*event;		/* Handle MPI event. */
144b0a2fdeeSScott Long 	mpt_reset_handler_t	*reset;		/* Re-init after reset. */
145b0a2fdeeSScott Long 	mpt_shutdown_handler_t	*shutdown;	/* Shutdown instance. */
146b0a2fdeeSScott Long 	mpt_detach_handler_t	*detach;	/* release device instance */
147b0a2fdeeSScott Long 	mpt_unload_handler_t	*unload;	/* Shutdown personality */
148b0a2fdeeSScott Long #define MPT_PERS_LAST_HANDLER(pers) (&(pers)->unload)
1499b631363SMatt Jacob };
1509b631363SMatt Jacob 
151b0a2fdeeSScott Long int mpt_modevent(module_t, int, void *);
1529b631363SMatt Jacob 
153b0a2fdeeSScott Long /* Maximum supported number of personalities. */
154b0a2fdeeSScott Long #define MPT_MAX_PERSONALITIES	(15)
1559b631363SMatt Jacob 
156b0a2fdeeSScott Long #define MPT_PERSONALITY_DEPEND(name, dep, vmin, vpref, vmax) \
157b0a2fdeeSScott Long 	MODULE_DEPEND(name, dep, vmin, vpref, vmax)
158b0a2fdeeSScott Long 
159b0a2fdeeSScott Long #define DECLARE_MPT_PERSONALITY(name, order)				  \
160b0a2fdeeSScott Long 	static moduledata_t name##_mod = {				  \
161b0a2fdeeSScott Long 		#name, mpt_modevent, &name##_personality		  \
162b0a2fdeeSScott Long 	};								  \
163b0a2fdeeSScott Long 	DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, order);	  \
164b0a2fdeeSScott Long 	MODULE_VERSION(name, 1);					  \
165b0a2fdeeSScott Long 	MPT_PERSONALITY_DEPEND(name, mpt_core, 1, 1, 1)
166b0a2fdeeSScott Long 
167b0a2fdeeSScott Long /******************************* Bus DMA Support ******************************/
168b0a2fdeeSScott Long /* XXX Need to update bus_dmamap_sync to take a range argument. */
169b0a2fdeeSScott Long #define bus_dmamap_sync_range(dma_tag, dmamap, offset, len, op)	\
170b0a2fdeeSScott Long 	bus_dmamap_sync(dma_tag, dmamap, op)
171b0a2fdeeSScott Long 
172b0a2fdeeSScott Long #if __FreeBSD_version >= 501102
173b0a2fdeeSScott Long #define mpt_dma_tag_create(mpt, parent_tag, alignment, boundary,	\
174b0a2fdeeSScott Long 			   lowaddr, highaddr, filter, filterarg,	\
175b0a2fdeeSScott Long 			   maxsize, nsegments, maxsegsz, flags,		\
176b0a2fdeeSScott Long 			   dma_tagp)					\
177b0a2fdeeSScott Long 	bus_dma_tag_create(parent_tag, alignment, boundary,		\
178b0a2fdeeSScott Long 			   lowaddr, highaddr, filter, filterarg,	\
179b0a2fdeeSScott Long 			   maxsize, nsegments, maxsegsz, flags,		\
180b0a2fdeeSScott Long 			   busdma_lock_mutex, &Giant,			\
181b0a2fdeeSScott Long 			   dma_tagp)
182b0a2fdeeSScott Long #else
183b0a2fdeeSScott Long #define mpt_dma_tag_create(mpt, parent_tag, alignment, boundary,	\
184b0a2fdeeSScott Long 			   lowaddr, highaddr, filter, filterarg,	\
185b0a2fdeeSScott Long 			   maxsize, nsegments, maxsegsz, flags,		\
186b0a2fdeeSScott Long 			   dma_tagp)					\
187b0a2fdeeSScott Long 	bus_dma_tag_create(parent_tag, alignment, boundary,		\
188b0a2fdeeSScott Long 			   lowaddr, highaddr, filter, filterarg,	\
189b0a2fdeeSScott Long 			   maxsize, nsegments, maxsegsz, flags,		\
190b0a2fdeeSScott Long 			   dma_tagp)
191b0a2fdeeSScott Long #endif
192b0a2fdeeSScott Long 
193b0a2fdeeSScott Long struct mpt_map_info {
194b0a2fdeeSScott Long 	struct mpt_softc *mpt;
195b0a2fdeeSScott Long 	int		  error;
196b0a2fdeeSScott Long 	uint32_t	  phys;
197b0a2fdeeSScott Long };
198b0a2fdeeSScott Long 
199b0a2fdeeSScott Long void mpt_map_rquest(void *, bus_dma_segment_t *, int, int);
200b0a2fdeeSScott Long 
201b0a2fdeeSScott Long /**************************** Kernel Thread Support ***************************/
202b0a2fdeeSScott Long #if __FreeBSD_version > 500005
203b0a2fdeeSScott Long #define mpt_kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
204b0a2fdeeSScott Long 	kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg)
205b0a2fdeeSScott Long #else
206b0a2fdeeSScott Long #define mpt_kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
207b0a2fdeeSScott Long 	kthread_create(func, farg, proc_ptr, fmtstr, arg)
208b0a2fdeeSScott Long #endif
209b0a2fdeeSScott Long 
210b0a2fdeeSScott Long /****************************** Timer Facilities ******************************/
211b0a2fdeeSScott Long #if __FreeBSD_version > 500000
212b0a2fdeeSScott Long #define mpt_callout_init(c)	callout_init(c, /*mpsafe*/0);
213b0a2fdeeSScott Long #else
214b0a2fdeeSScott Long #define mpt_callout_init(c)	callout_init(c);
215b0a2fdeeSScott Long #endif
216b0a2fdeeSScott Long 
217b0a2fdeeSScott Long /********************************** Endianess *********************************/
218b0a2fdeeSScott Long static __inline uint64_t
219b0a2fdeeSScott Long u64toh(U64 s)
220b0a2fdeeSScott Long {
221b0a2fdeeSScott Long 	uint64_t result;
222b0a2fdeeSScott Long 
223b0a2fdeeSScott Long 	result = le32toh(s.Low);
224b0a2fdeeSScott Long 	result |= ((uint64_t)le32toh(s.High)) << 32;
225b0a2fdeeSScott Long 	return (result);
226b0a2fdeeSScott Long }
227b0a2fdeeSScott Long 
228b0a2fdeeSScott Long /**************************** MPI Transaction State ***************************/
229b0a2fdeeSScott Long typedef enum {
230b0a2fdeeSScott Long 	REQ_STATE_FREE		= 0x00,
231b0a2fdeeSScott Long 	REQ_STATE_ALLOCATED	= 0x01,
232b0a2fdeeSScott Long 	REQ_STATE_QUEUED	= 0x02,
233b0a2fdeeSScott Long 	REQ_STATE_DONE		= 0x04,
234b0a2fdeeSScott Long 	REQ_STATE_TIMEDOUT	= 0x08,
235b0a2fdeeSScott Long 	REQ_STATE_NEED_WAKEUP	= 0x10,
236b0a2fdeeSScott Long 	REQ_STATE_MASK		= 0xFF
237b0a2fdeeSScott Long } mpt_req_state_t;
238b0a2fdeeSScott Long 
239b0a2fdeeSScott Long struct req_entry {
240b0a2fdeeSScott Long 	TAILQ_ENTRY(req_entry) links;	/* Pointer to next in list */
241b0a2fdeeSScott Long 	mpt_req_state_t	state;		/* Request State Information */
242b0a2fdeeSScott Long 	uint16_t	index;		/* Index of this entry */
243b0a2fdeeSScott Long 	uint16_t	IOCStatus;	/* Completion status */
244b0a2fdeeSScott Long 	union ccb      *ccb;		/* CAM request */
245b0a2fdeeSScott Long 	void	       *req_vbuf;	/* Virtual Address of Entry */
246b0a2fdeeSScott Long 	void	       *sense_vbuf;	/* Virtual Address of sense data */
247b0a2fdeeSScott Long 	bus_addr_t	req_pbuf;	/* Physical Address of Entry */
248b0a2fdeeSScott Long 	bus_addr_t	sense_pbuf;	/* Physical Address of sense data */
249b0a2fdeeSScott Long 	bus_dmamap_t	dmap;		/* DMA map for data buffer */
250b0a2fdeeSScott Long };
251b0a2fdeeSScott Long 
252b0a2fdeeSScott Long /**************************** Handler Registration ****************************/
253b0a2fdeeSScott Long /*
254b0a2fdeeSScott Long  * Global table of registered reply handlers.  The
255b0a2fdeeSScott Long  * handler is indicated by byte 3 of the request
256b0a2fdeeSScott Long  * index submitted to the IOC.  This allows the
257b0a2fdeeSScott Long  * driver core to perform generic processing without
258b0a2fdeeSScott Long  * any knowledge of per-personality behavior.
259b0a2fdeeSScott Long  *
260b0a2fdeeSScott Long  * MPT_NUM_REPLY_HANDLERS must be a power of 2
261b0a2fdeeSScott Long  * to allow the easy generation of a mask.
262b0a2fdeeSScott Long  *
263b0a2fdeeSScott Long  * The handler offsets used by the core are hard coded
264b0a2fdeeSScott Long  * allowing faster code generation when assigning a handler
265b0a2fdeeSScott Long  * to a request.  All "personalities" must use the
266b0a2fdeeSScott Long  * the handler registration mechanism.
267b0a2fdeeSScott Long  *
268b0a2fdeeSScott Long  * The IOC handlers that are rarely executed are placed
269b0a2fdeeSScott Long  * at the tail of the table to make it more likely that
270b0a2fdeeSScott Long  * all commonly executed handlers fit in a single cache
271b0a2fdeeSScott Long  * line.
272b0a2fdeeSScott Long  */
273b0a2fdeeSScott Long #define MPT_NUM_REPLY_HANDLERS		(16)
274b0a2fdeeSScott Long #define MPT_REPLY_HANDLER_EVENTS	MPT_CBI_TO_HID(0)
275b0a2fdeeSScott Long #define MPT_REPLY_HANDLER_CONFIG	MPT_CBI_TO_HID(MPT_NUM_REPLY_HANDLERS-1)
276b0a2fdeeSScott Long #define MPT_REPLY_HANDLER_HANDSHAKE	MPT_CBI_TO_HID(MPT_NUM_REPLY_HANDLERS-2)
277b0a2fdeeSScott Long typedef int mpt_reply_handler_t(struct mpt_softc *mpt, request_t *request,
278b0a2fdeeSScott Long 				 MSG_DEFAULT_REPLY *reply_frame);
279b0a2fdeeSScott Long typedef union {
280b0a2fdeeSScott Long 	mpt_reply_handler_t	*reply_handler;
281b0a2fdeeSScott Long } mpt_handler_t;
282b0a2fdeeSScott Long 
283b0a2fdeeSScott Long typedef enum {
284b0a2fdeeSScott Long 	MPT_HANDLER_REPLY,
285b0a2fdeeSScott Long 	MPT_HANDLER_EVENT,
286b0a2fdeeSScott Long 	MPT_HANDLER_RESET,
287b0a2fdeeSScott Long 	MPT_HANDLER_SHUTDOWN
288b0a2fdeeSScott Long } mpt_handler_type;
289b0a2fdeeSScott Long 
290b0a2fdeeSScott Long struct mpt_handler_record
291b0a2fdeeSScott Long {
292b0a2fdeeSScott Long 	LIST_ENTRY(mpt_handler_record)	links;
293b0a2fdeeSScott Long 	mpt_handler_t			handler;
294b0a2fdeeSScott Long };
295b0a2fdeeSScott Long 
296b0a2fdeeSScott Long LIST_HEAD(mpt_handler_list, mpt_handler_record);
2979b631363SMatt Jacob 
2989b631363SMatt Jacob /*
299b0a2fdeeSScott Long  * The handler_id is currently unused but would contain the
300b0a2fdeeSScott Long  * handler ID used in the MsgContext field to allow direction
301b0a2fdeeSScott Long  * of replies to the handler.  Registrations that don't require
302b0a2fdeeSScott Long  * a handler id can pass in NULL for the handler_id.
303b0a2fdeeSScott Long  *
304b0a2fdeeSScott Long  * Deregistrations for handlers without a handler id should
305b0a2fdeeSScott Long  * pass in MPT_HANDLER_ID_NONE.
3069b631363SMatt Jacob  */
307b0a2fdeeSScott Long #define MPT_HANDLER_ID_NONE		(0xFFFFFFFF)
308b0a2fdeeSScott Long int mpt_register_handler(struct mpt_softc *, mpt_handler_type,
309b0a2fdeeSScott Long 			 mpt_handler_t, uint32_t *);
310b0a2fdeeSScott Long int mpt_deregister_handler(struct mpt_softc *, mpt_handler_type,
311b0a2fdeeSScott Long 			   mpt_handler_t, uint32_t);
3129b631363SMatt Jacob 
313b0a2fdeeSScott Long /******************* Per-Controller Instance Data Structures ******************/
314b0a2fdeeSScott Long TAILQ_HEAD(req_queue, req_entry);
3159b631363SMatt Jacob 
316b0a2fdeeSScott Long /* Structure for saving proper values for modifyable PCI config registers */
317b0a2fdeeSScott Long struct mpt_pci_cfg {
318b0a2fdeeSScott Long 	uint16_t Command;
319b0a2fdeeSScott Long 	uint16_t LatencyTimer_LineSize;
320b0a2fdeeSScott Long 	uint32_t IO_BAR;
321b0a2fdeeSScott Long 	uint32_t Mem0_BAR[2];
322b0a2fdeeSScott Long 	uint32_t Mem1_BAR[2];
323b0a2fdeeSScott Long 	uint32_t ROM_BAR;
324b0a2fdeeSScott Long 	uint8_t  IntLine;
325b0a2fdeeSScott Long 	uint32_t PMCSR;
3269b631363SMatt Jacob };
3279b631363SMatt Jacob 
328b0a2fdeeSScott Long typedef enum {
329b0a2fdeeSScott Long 	MPT_RVF_NONE		= 0x0,
330b0a2fdeeSScott Long 	MPT_RVF_ACTIVE		= 0x1,
331b0a2fdeeSScott Long 	MPT_RVF_ANNOUNCED	= 0x2,
332b0a2fdeeSScott Long 	MPT_RVF_UP2DATE		= 0x4,
333b0a2fdeeSScott Long 	MPT_RVF_REFERENCED	= 0x8,
334b0a2fdeeSScott Long 	MPT_RVF_WCE_CHANGED	= 0x10
335b0a2fdeeSScott Long } mpt_raid_volume_flags;
336b0a2fdeeSScott Long 
337b0a2fdeeSScott Long struct mpt_raid_volume {
338b0a2fdeeSScott Long 	CONFIG_PAGE_RAID_VOL_0	       *config_page;
339b0a2fdeeSScott Long 	MPI_RAID_VOL_INDICATOR		sync_progress;
340b0a2fdeeSScott Long 	mpt_raid_volume_flags		flags;
341b0a2fdeeSScott Long 	u_int				quieced_disks;
3429b631363SMatt Jacob };
3439b631363SMatt Jacob 
344b0a2fdeeSScott Long typedef enum {
345b0a2fdeeSScott Long 	MPT_RDF_NONE		= 0x00,
346b0a2fdeeSScott Long 	MPT_RDF_ACTIVE		= 0x01,
347b0a2fdeeSScott Long 	MPT_RDF_ANNOUNCED	= 0x02,
348b0a2fdeeSScott Long 	MPT_RDF_UP2DATE		= 0x04,
349b0a2fdeeSScott Long 	MPT_RDF_REFERENCED	= 0x08,
350b0a2fdeeSScott Long 	MPT_RDF_QUIESCING	= 0x10,
351b0a2fdeeSScott Long 	MPT_RDF_QUIESCED	= 0x20
352b0a2fdeeSScott Long } mpt_raid_disk_flags;
3539b631363SMatt Jacob 
354b0a2fdeeSScott Long struct mpt_raid_disk {
355b0a2fdeeSScott Long 	CONFIG_PAGE_RAID_PHYS_DISK_0	config_page;
356b0a2fdeeSScott Long 	struct mpt_raid_volume	       *volume;
357b0a2fdeeSScott Long 	u_int				member_number;
358b0a2fdeeSScott Long 	u_int				pass_thru_active;
359b0a2fdeeSScott Long 	mpt_raid_disk_flags		flags;
3609b631363SMatt Jacob };
3619b631363SMatt Jacob 
362b0a2fdeeSScott Long struct mpt_evtf_record {
363b0a2fdeeSScott Long 	MSG_EVENT_NOTIFY_REPLY		reply;
364b0a2fdeeSScott Long 	uint32_t			context;
365b0a2fdeeSScott Long 	LIST_ENTRY(mpt_evtf_record)	links;
3669b631363SMatt Jacob };
3679b631363SMatt Jacob 
368b0a2fdeeSScott Long LIST_HEAD(mpt_evtf_list, mpt_evtf_record);
3699b631363SMatt Jacob 
370b0a2fdeeSScott Long struct mpt_softc {
371b0a2fdeeSScott Long 	device_t		dev;
372b0a2fdeeSScott Long #if __FreeBSD_version < 500000
373b0a2fdeeSScott Long 	int			mpt_splsaved;
374b0a2fdeeSScott Long 	uint32_t		mpt_islocked;
375b0a2fdeeSScott Long #else
376b0a2fdeeSScott Long 	struct mtx		mpt_lock;
377b0a2fdeeSScott Long #endif
378b0a2fdeeSScott Long 	uint32_t		mpt_pers_mask;
379b0a2fdeeSScott Long 	uint32_t		: 15,
380b0a2fdeeSScott Long 		raid_mwce_set	: 1,
381b0a2fdeeSScott Long 		getreqwaiter	: 1,
382b0a2fdeeSScott Long 		shutdwn_raid    : 1,
383b0a2fdeeSScott Long 		shutdwn_recovery: 1,
384b0a2fdeeSScott Long 		unit		: 8,
385b0a2fdeeSScott Long 		outofbeer	: 1,
386b0a2fdeeSScott Long 		mpt_locksetup	: 1,
387b0a2fdeeSScott Long 		disabled	: 1,
388b0a2fdeeSScott Long 		is_fc		: 1,
389b0a2fdeeSScott Long 		bus		: 1;	/* FC929/1030 have two busses */
3909b631363SMatt Jacob 
391b0a2fdeeSScott Long 	u_int			verbose;
3929b631363SMatt Jacob 
393b0a2fdeeSScott Long 	/*
394b0a2fdeeSScott Long 	 * IOC Facts
395b0a2fdeeSScott Long 	 */
396b0a2fdeeSScott Long 	uint16_t	mpt_global_credits;
397b0a2fdeeSScott Long 	uint16_t	request_frame_size;
398b0a2fdeeSScott Long 	uint8_t		mpt_max_devices;
399b0a2fdeeSScott Long 	uint8_t		mpt_max_buses;
4009b631363SMatt Jacob 
401b0a2fdeeSScott Long 	/*
402b0a2fdeeSScott Long 	 * Port Facts
403b0a2fdeeSScott Long 	 * XXX - Add multi-port support!.
404b0a2fdeeSScott Long 	 */
405b0a2fdeeSScott Long 	uint16_t	mpt_ini_id;
406b0a2fdeeSScott Long 	uint16_t	mpt_port_type;
407b0a2fdeeSScott Long 	uint16_t	mpt_proto_flags;
4089b631363SMatt Jacob 
409b0a2fdeeSScott Long 	/*
410b0a2fdeeSScott Long 	 * Device Configuration Information
411b0a2fdeeSScott Long 	 */
412b0a2fdeeSScott Long 	union {
413b0a2fdeeSScott Long 		struct mpt_spi_cfg {
414b0a2fdeeSScott Long 			CONFIG_PAGE_SCSI_PORT_0		_port_page0;
415b0a2fdeeSScott Long 			CONFIG_PAGE_SCSI_PORT_1		_port_page1;
416b0a2fdeeSScott Long 			CONFIG_PAGE_SCSI_PORT_2		_port_page2;
417b0a2fdeeSScott Long 			CONFIG_PAGE_SCSI_DEVICE_0	_dev_page0[16];
418b0a2fdeeSScott Long 			CONFIG_PAGE_SCSI_DEVICE_1	_dev_page1[16];
419b0a2fdeeSScott Long 			uint16_t			_tag_enable;
420b0a2fdeeSScott Long 			uint16_t			_disc_enable;
421b0a2fdeeSScott Long 			uint16_t			_update_params0;
422b0a2fdeeSScott Long 			uint16_t			_update_params1;
423b0a2fdeeSScott Long 		} spi;
424b0a2fdeeSScott Long #define	mpt_port_page0		cfg.spi._port_page0
425b0a2fdeeSScott Long #define	mpt_port_page1		cfg.spi._port_page1
426b0a2fdeeSScott Long #define	mpt_port_page2		cfg.spi._port_page2
427b0a2fdeeSScott Long #define	mpt_dev_page0		cfg.spi._dev_page0
428b0a2fdeeSScott Long #define	mpt_dev_page1		cfg.spi._dev_page1
429b0a2fdeeSScott Long #define	mpt_tag_enable		cfg.spi._tag_enable
430b0a2fdeeSScott Long #define	mpt_disc_enable		cfg.spi._disc_enable
431b0a2fdeeSScott Long #define	mpt_update_params0	cfg.spi._update_params0
432b0a2fdeeSScott Long #define	mpt_update_params1	cfg.spi._update_params1
433b0a2fdeeSScott Long 		struct mpi_fc_cfg {
434b0a2fdeeSScott Long 			uint8_t	nada;
435b0a2fdeeSScott Long 		} fc;
436b0a2fdeeSScott Long 	} cfg;
437b0a2fdeeSScott Long 
438b0a2fdeeSScott Long 	/* Controller Info */
439b0a2fdeeSScott Long 	CONFIG_PAGE_IOC_2 *	ioc_page2;
440b0a2fdeeSScott Long 	CONFIG_PAGE_IOC_3 *	ioc_page3;
441b0a2fdeeSScott Long 
442b0a2fdeeSScott Long 	/* Raid Data */
443b0a2fdeeSScott Long 	struct mpt_raid_volume* raid_volumes;
444b0a2fdeeSScott Long 	struct mpt_raid_disk*	raid_disks;
445b0a2fdeeSScott Long 	u_int			raid_max_volumes;
446b0a2fdeeSScott Long 	u_int			raid_max_disks;
447b0a2fdeeSScott Long 	u_int			raid_page0_len;
448b0a2fdeeSScott Long 	u_int			raid_wakeup;
449b0a2fdeeSScott Long 	u_int			raid_rescan;
450b0a2fdeeSScott Long 	u_int			raid_resync_rate;
451b0a2fdeeSScott Long 	u_int			raid_mwce_setting;
452b0a2fdeeSScott Long 	u_int			raid_queue_depth;
4535cc0208aSAlexander Kabaev 	u_int			raid_nonopt_volumes;
454b0a2fdeeSScott Long 	struct proc	       *raid_thread;
455b0a2fdeeSScott Long 	struct callout		raid_timer;
456b0a2fdeeSScott Long 
457b0a2fdeeSScott Long 	/*
458b0a2fdeeSScott Long 	 * PCI Hardware info
459b0a2fdeeSScott Long 	 */
460b0a2fdeeSScott Long 	struct resource *	pci_irq;	/* Interrupt map for chip */
461b0a2fdeeSScott Long 	void *			ih;		/* Interupt handle */
462b0a2fdeeSScott Long 	struct mpt_pci_cfg	pci_cfg;	/* saved PCI conf registers */
463b0a2fdeeSScott Long 
464b0a2fdeeSScott Long 	/*
465b0a2fdeeSScott Long 	 * DMA Mapping Stuff
466b0a2fdeeSScott Long 	 */
467b0a2fdeeSScott Long 	struct resource *	pci_reg;	/* Register map for chip */
468b0a2fdeeSScott Long 	int			pci_mem_rid;	/* Resource ID */
469b0a2fdeeSScott Long 	bus_space_tag_t		pci_st;		/* Bus tag for registers */
470b0a2fdeeSScott Long 	bus_space_handle_t	pci_sh;		/* Bus handle for registers */
471b0a2fdeeSScott Long 	/* PIO versions of above. */
472b0a2fdeeSScott Long 	int			pci_pio_rid;
473b0a2fdeeSScott Long 	struct resource *	pci_pio_reg;
474b0a2fdeeSScott Long 	bus_space_tag_t		pci_pio_st;
475b0a2fdeeSScott Long 	bus_space_handle_t	pci_pio_sh;
476b0a2fdeeSScott Long 
477b0a2fdeeSScott Long 	bus_dma_tag_t		parent_dmat;	/* DMA tag for parent PCI bus */
478b0a2fdeeSScott Long 	bus_dma_tag_t		reply_dmat;	/* DMA tag for reply memory */
479b0a2fdeeSScott Long 	bus_dmamap_t		reply_dmap;	/* DMA map for reply memory */
480b0a2fdeeSScott Long 	uint8_t		       *reply;		/* KVA of reply memory */
481b0a2fdeeSScott Long 	bus_addr_t		reply_phys;	/* BusAddr of reply memory */
482b0a2fdeeSScott Long 
483b0a2fdeeSScott Long 	bus_dma_tag_t		buffer_dmat;	/* DMA tag for buffers */
484b0a2fdeeSScott Long 	bus_dma_tag_t		request_dmat;	/* DMA tag for request memroy */
485b0a2fdeeSScott Long 	bus_dmamap_t		request_dmap;	/* DMA map for request memroy */
486b0a2fdeeSScott Long 	uint8_t		       *request;	/* KVA of Request memory */
487b0a2fdeeSScott Long 	bus_addr_t		request_phys;	/* BusADdr of request memory */
488b0a2fdeeSScott Long 
489b0a2fdeeSScott Long 	u_int			reset_cnt;
490b0a2fdeeSScott Long 
491b0a2fdeeSScott Long 	/*
492b0a2fdeeSScott Long 	 * CAM && Software Management
493b0a2fdeeSScott Long 	 */
494b0a2fdeeSScott Long 	request_t	       *request_pool;
495b0a2fdeeSScott Long 	struct req_queue	request_free_list;
496b0a2fdeeSScott Long 	struct req_queue	request_pending_list;
497b0a2fdeeSScott Long 	struct req_queue	request_timeout_list;
498b0a2fdeeSScott Long 
499b0a2fdeeSScott Long 	/*
500b0a2fdeeSScott Long 	 * Deferred frame acks due to resource shortage.
501b0a2fdeeSScott Long 	 */
502b0a2fdeeSScott Long 	struct mpt_evtf_list	ack_frames;
503b0a2fdeeSScott Long 
504b0a2fdeeSScott Long 
505b0a2fdeeSScott Long 	struct cam_sim	       *sim;
506b0a2fdeeSScott Long 	struct cam_path	       *path;
507b0a2fdeeSScott Long 
508b0a2fdeeSScott Long 	struct cam_sim	       *phydisk_sim;
509b0a2fdeeSScott Long 	struct cam_path	       *phydisk_path;
510b0a2fdeeSScott Long 
511b0a2fdeeSScott Long 	struct proc	       *recovery_thread;
512b0a2fdeeSScott Long 	request_t	       *tmf_req;
513b0a2fdeeSScott Long 
514b0a2fdeeSScott Long 	uint32_t		sequence;	/* Sequence Number */
515b0a2fdeeSScott Long 	uint32_t		timeouts;	/* timeout count */
516b0a2fdeeSScott Long 	uint32_t		success;	/* successes afer timeout */
517b0a2fdeeSScott Long 
518b0a2fdeeSScott Long 	/* Opposing port in a 929 or 1030, or NULL */
519b0a2fdeeSScott Long 	struct mpt_softc *	mpt2;
520b0a2fdeeSScott Long 
521b0a2fdeeSScott Long 	/* FW Image management */
522b0a2fdeeSScott Long 	uint32_t		fw_image_size;
523b0a2fdeeSScott Long 	uint8_t		       *fw_image;
524b0a2fdeeSScott Long 	bus_dma_tag_t		fw_dmat;	/* DMA tag for firmware image */
525b0a2fdeeSScott Long 	bus_dmamap_t		fw_dmap;	/* DMA map for firmware image */
526b0a2fdeeSScott Long 	bus_addr_t		fw_phys;	/* BusAddr of request memory */
527b0a2fdeeSScott Long 
528b0a2fdeeSScott Long 	/* Shutdown Event Handler. */
529b0a2fdeeSScott Long 	eventhandler_tag         eh;
530b0a2fdeeSScott Long 
531b0a2fdeeSScott Long 	TAILQ_ENTRY(mpt_softc)	links;
532b0a2fdeeSScott Long };
533b0a2fdeeSScott Long 
534b0a2fdeeSScott Long /***************************** Locking Primatives *****************************/
535b0a2fdeeSScott Long #if __FreeBSD_version < 500000
536b0a2fdeeSScott Long #define	MPT_IFLAGS		INTR_TYPE_CAM
537b0a2fdeeSScott Long #define	MPT_LOCK(mpt)		mpt_lockspl(mpt)
538b0a2fdeeSScott Long #define	MPT_UNLOCK(mpt)		mpt_unlockspl(mpt)
539b0a2fdeeSScott Long #define	MPTLOCK_2_CAMLOCK	MPT_UNLOCK
540b0a2fdeeSScott Long #define	CAMLOCK_2_MPTLOCK	MPT_LOCK
541b0a2fdeeSScott Long #define	MPT_LOCK_SETUP(mpt)
542b0a2fdeeSScott Long #define	MPT_LOCK_DESTROY(mpt)
543b0a2fdeeSScott Long 
544b0a2fdeeSScott Long static __inline void mpt_lockspl(struct mpt_softc *mpt);
545b0a2fdeeSScott Long static __inline void mpt_unlockspl(struct mpt_softc *mpt);
546b0a2fdeeSScott Long 
547b0a2fdeeSScott Long static __inline void
548b0a2fdeeSScott Long mpt_lockspl(struct mpt_softc *mpt)
549b0a2fdeeSScott Long {
550b0a2fdeeSScott Long        int s;
551b0a2fdeeSScott Long 
552b0a2fdeeSScott Long        s = splcam();
553b0a2fdeeSScott Long        if (mpt->mpt_islocked++ == 0) {
554b0a2fdeeSScott Long                mpt->mpt_splsaved = s;
555b0a2fdeeSScott Long        } else {
556b0a2fdeeSScott Long                splx(s);
557b0a2fdeeSScott Long 	       panic("Recursed lock with mask: 0x%x\n", s);
558b0a2fdeeSScott Long        }
559b0a2fdeeSScott Long }
560b0a2fdeeSScott Long 
561b0a2fdeeSScott Long static __inline void
562b0a2fdeeSScott Long mpt_unlockspl(struct mpt_softc *mpt)
563b0a2fdeeSScott Long {
564b0a2fdeeSScott Long        if (mpt->mpt_islocked) {
565b0a2fdeeSScott Long                if (--mpt->mpt_islocked == 0) {
566b0a2fdeeSScott Long                        splx(mpt->mpt_splsaved);
567b0a2fdeeSScott Long                }
568b0a2fdeeSScott Long        } else
569b0a2fdeeSScott Long 	       panic("Negative lock count\n");
570b0a2fdeeSScott Long }
571b0a2fdeeSScott Long 
572b0a2fdeeSScott Long static __inline int
573b0a2fdeeSScott Long mpt_sleep(struct mpt_softc *mpt, void *ident, int priority,
574b0a2fdeeSScott Long 	   const char *wmesg, int timo)
575b0a2fdeeSScott Long {
576b0a2fdeeSScott Long 	int saved_cnt;
577b0a2fdeeSScott Long 	int saved_spl;
578b0a2fdeeSScott Long 	int error;
579b0a2fdeeSScott Long 
580b0a2fdeeSScott Long 	KASSERT(mpt->mpt_islocked <= 1, ("Invalid lock count on tsleep"));
581b0a2fdeeSScott Long 	saved_cnt = mpt->mpt_islocked;
582b0a2fdeeSScott Long 	saved_spl = mpt->mpt_splsaved;
583b0a2fdeeSScott Long 	mpt->mpt_islocked = 0;
584b0a2fdeeSScott Long 	error = tsleep(ident, priority, wmesg, timo);
585b0a2fdeeSScott Long 	KASSERT(mpt->mpt_islocked = 0, ("Invalid lock count on wakeup"));
586b0a2fdeeSScott Long 	mpt->mpt_islocked = saved_cnt;
587b0a2fdeeSScott Long 	mpt->mpt_splsaved = saved_spl;
588b0a2fdeeSScott Long 	return (error);
589b0a2fdeeSScott Long }
590b0a2fdeeSScott Long 
591b0a2fdeeSScott Long #else
592b0a2fdeeSScott Long #if	LOCKING_WORKED_AS_IT_SHOULD
593b0a2fdeeSScott Long #error "Shouldn't Be Here!"
594b0a2fdeeSScott Long #define	MPT_IFLAGS		INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE
595b0a2fdeeSScott Long #define	MPT_LOCK_SETUP(mpt)						\
596b0a2fdeeSScott Long 		mtx_init(&mpt->mpt_lock, "mpt", NULL, MTX_DEF);		\
597b0a2fdeeSScott Long 		mpt->mpt_locksetup = 1
598b0a2fdeeSScott Long #define	MPT_LOCK_DESTROY(mpt)						\
599b0a2fdeeSScott Long 	if (mpt->mpt_locksetup) {					\
600b0a2fdeeSScott Long 		mtx_destroy(&mpt->mpt_lock);				\
601b0a2fdeeSScott Long 		mpt->mpt_locksetup = 0;					\
602b0a2fdeeSScott Long 	}
603b0a2fdeeSScott Long 
604b0a2fdeeSScott Long #define	MPT_LOCK(mpt)		mtx_lock(&(mpt)->mpt_lock)
605b0a2fdeeSScott Long #define	MPT_UNLOCK(mpt)		mtx_unlock(&(mpt)->mpt_lock)
606b0a2fdeeSScott Long #define	MPTLOCK_2_CAMLOCK(mpt)	\
607b0a2fdeeSScott Long 	mtx_unlock(&(mpt)->mpt_lock); mtx_lock(&Giant)
608b0a2fdeeSScott Long #define	CAMLOCK_2_MPTLOCK(mpt)	\
609b0a2fdeeSScott Long 	mtx_unlock(&Giant); mtx_lock(&(mpt)->mpt_lock)
610b0a2fdeeSScott Long #define mpt_sleep(mpt, ident, priority, wmesg, timo) \
611b0a2fdeeSScott Long 	msleep(ident, &(mpt)->mpt_lock, priority, wmesg, timo)
612b0a2fdeeSScott Long #else
613b0a2fdeeSScott Long #define	MPT_IFLAGS		INTR_TYPE_CAM | INTR_ENTROPY
614b0a2fdeeSScott Long #define	MPT_LOCK_SETUP(mpt)	do { } while (0)
615b0a2fdeeSScott Long #define	MPT_LOCK_DESTROY(mpt)	do { } while (0)
616b0a2fdeeSScott Long #define	MPT_LOCK(mpt)		do { } while (0)
617b0a2fdeeSScott Long #define	MPT_UNLOCK(mpt)		do { } while (0)
618b0a2fdeeSScott Long #define	MPTLOCK_2_CAMLOCK(mpt)	do { } while (0)
619b0a2fdeeSScott Long #define	CAMLOCK_2_MPTLOCK(mpt)	do { } while (0)
620b0a2fdeeSScott Long #define mpt_sleep(mpt, ident, priority, wmesg, timo) \
621b0a2fdeeSScott Long 	tsleep(ident, priority, wmesg, timo)
622b0a2fdeeSScott Long #endif
623b0a2fdeeSScott Long #endif
624b0a2fdeeSScott Long 
625b0a2fdeeSScott Long /******************************* Register Access ******************************/
626b0a2fdeeSScott Long static __inline void mpt_write(struct mpt_softc *, size_t, uint32_t);
627b0a2fdeeSScott Long static __inline uint32_t mpt_read(struct mpt_softc *, int);
628b0a2fdeeSScott Long static __inline void mpt_pio_write(struct mpt_softc *, size_t, uint32_t);
629b0a2fdeeSScott Long static __inline uint32_t mpt_pio_read(struct mpt_softc *, int);
630b0a2fdeeSScott Long 
631b0a2fdeeSScott Long static __inline void
632b0a2fdeeSScott Long mpt_write(struct mpt_softc *mpt, size_t offset, uint32_t val)
633b0a2fdeeSScott Long {
634b0a2fdeeSScott Long 	bus_space_write_4(mpt->pci_st, mpt->pci_sh, offset, val);
635b0a2fdeeSScott Long }
636b0a2fdeeSScott Long 
637b0a2fdeeSScott Long static __inline uint32_t
638b0a2fdeeSScott Long mpt_read(struct mpt_softc *mpt, int offset)
639b0a2fdeeSScott Long {
640b0a2fdeeSScott Long 	return (bus_space_read_4(mpt->pci_st, mpt->pci_sh, offset));
641b0a2fdeeSScott Long }
642b0a2fdeeSScott Long 
643b0a2fdeeSScott Long /*
644b0a2fdeeSScott Long  * Some operations (e.g. diagnostic register writes while the ARM proccessor
645b0a2fdeeSScott Long  * is disabled), must be performed using "PCI pio" operations.  On non-PCI
646b0a2fdeeSScott Long  * busses, these operations likely map to normal register accesses.
647b0a2fdeeSScott Long  */
648b0a2fdeeSScott Long static __inline void
649b0a2fdeeSScott Long mpt_pio_write(struct mpt_softc *mpt, size_t offset, uint32_t val)
650b0a2fdeeSScott Long {
651b0a2fdeeSScott Long 	bus_space_write_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset, val);
652b0a2fdeeSScott Long }
653b0a2fdeeSScott Long 
654b0a2fdeeSScott Long static __inline uint32_t
655b0a2fdeeSScott Long mpt_pio_read(struct mpt_softc *mpt, int offset)
656b0a2fdeeSScott Long {
657b0a2fdeeSScott Long 	return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset));
658b0a2fdeeSScott Long }
659b0a2fdeeSScott Long /*********************** Reply Frame/Request Management ***********************/
660b0a2fdeeSScott Long /* Max MPT Reply we are willing to accept (must be power of 2) */
661b0a2fdeeSScott Long #define MPT_REPLY_SIZE   	128
662b0a2fdeeSScott Long 
663b0a2fdeeSScott Long #define MPT_MAX_REQUESTS(mpt)	((mpt)->is_fc ? 1024 : 256)
664b0a2fdeeSScott Long #define MPT_REQUEST_AREA 512
665b0a2fdeeSScott Long #define MPT_SENSE_SIZE    32	/* included in MPT_REQUEST_SIZE */
666b0a2fdeeSScott Long #define MPT_REQ_MEM_SIZE(mpt)	(MPT_MAX_REQUESTS(mpt) * MPT_REQUEST_AREA)
667b0a2fdeeSScott Long 
668b0a2fdeeSScott Long #define MPT_CONTEXT_CB_SHIFT	(16)
669b0a2fdeeSScott Long #define MPT_CBI(handle)	(handle >> MPT_CONTEXT_CB_SHIFT)
670b0a2fdeeSScott Long #define MPT_CBI_TO_HID(cbi)	((cbi) << MPT_CONTEXT_CB_SHIFT)
671b0a2fdeeSScott Long #define MPT_CONTEXT_TO_CBI(x)	\
672b0a2fdeeSScott Long     (((x) >> MPT_CONTEXT_CB_SHIFT) & (MPT_NUM_REPLY_HANDLERS - 1))
673b0a2fdeeSScott Long #define MPT_CONTEXT_REQI_MASK 0xFFFF
674b0a2fdeeSScott Long #define MPT_CONTEXT_TO_REQI(x)	\
675b0a2fdeeSScott Long     ((x) & MPT_CONTEXT_REQI_MASK)
676b0a2fdeeSScott Long 
677b0a2fdeeSScott Long /*
678b0a2fdeeSScott Long  * Convert a 32bit physical address returned from IOC to an
679b0a2fdeeSScott Long  * offset into our reply frame memory or the kvm address needed
680b0a2fdeeSScott Long  * to access the data.  The returned address is only the low
681b0a2fdeeSScott Long  * 32 bits, so mask our base physical address accordingly.
682b0a2fdeeSScott Long  */
683b0a2fdeeSScott Long #define MPT_REPLY_BADDR(x)		\
684b0a2fdeeSScott Long 	(x << 1)
685b0a2fdeeSScott Long #define MPT_REPLY_OTOV(m, i) 		\
686b0a2fdeeSScott Long 	((void *)(&m->reply[i]))
687b0a2fdeeSScott Long 
688b0a2fdeeSScott Long #define	MPT_DUMP_REPLY_FRAME(mpt, reply_frame)		\
689b0a2fdeeSScott Long do {							\
690b0a2fdeeSScott Long 	if (mpt->verbose >= MPT_PRT_DEBUG)		\
691b0a2fdeeSScott Long 		mpt_dump_reply_frame(mpt, reply_frame);	\
692b0a2fdeeSScott Long } while(0)
693b0a2fdeeSScott Long 
694b0a2fdeeSScott Long static __inline uint32_t mpt_pop_reply_queue(struct mpt_softc *mpt);
695b0a2fdeeSScott Long static __inline void mpt_free_reply(struct mpt_softc *mpt, uint32_t ptr);
696b0a2fdeeSScott Long 
697b0a2fdeeSScott Long /*
698b0a2fdeeSScott Long  * Give the reply buffer back to the IOC after we have
699b0a2fdeeSScott Long  * finished processing it.
700b0a2fdeeSScott Long  */
701b0a2fdeeSScott Long static __inline void
702b0a2fdeeSScott Long mpt_free_reply(struct mpt_softc *mpt, uint32_t ptr)
703b0a2fdeeSScott Long {
704b0a2fdeeSScott Long      mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
705b0a2fdeeSScott Long }
706b0a2fdeeSScott Long 
707b0a2fdeeSScott Long /* Get a reply from the IOC */
708b0a2fdeeSScott Long static __inline uint32_t
709b0a2fdeeSScott Long mpt_pop_reply_queue(struct mpt_softc *mpt)
710b0a2fdeeSScott Long {
711b0a2fdeeSScott Long      return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
712b0a2fdeeSScott Long }
713b0a2fdeeSScott Long 
714b0a2fdeeSScott Long void mpt_complete_request_chain(struct mpt_softc *mpt,
715b0a2fdeeSScott Long 				struct req_queue *chain, u_int iocstatus);
716b0a2fdeeSScott Long /************************** Scatter Gather Managment **************************/
717b0a2fdeeSScott Long /*
718b0a2fdeeSScott Long  * We cannot tell prior to getting IOC facts how big the IOC's request
719b0a2fdeeSScott Long  * area is. Because of this we cannot tell at compile time how many
720b0a2fdeeSScott Long  * simple SG elements we can fit within an IOC request prior to having
721b0a2fdeeSScott Long  * to put in a chain element.
722b0a2fdeeSScott Long  *
723b0a2fdeeSScott Long  * Experimentally we know that the Ultra4 parts have a 96 byte request
724b0a2fdeeSScott Long  * element size and the Fibre Channel units have a 144 byte request
725b0a2fdeeSScott Long  * element size. Therefore, if we have 512-32 (== 480) bytes of request
726b0a2fdeeSScott Long  * area to play with, we have room for between 3 and 5 request sized
727b0a2fdeeSScott Long  * regions- the first of which is the command  plus a simple SG list,
728b0a2fdeeSScott Long  * the rest of which are chained continuation SG lists. Given that the
729b0a2fdeeSScott Long  * normal request we use is 48 bytes w/o the first SG element, we can
730b0a2fdeeSScott Long  * assume we have 480-48 == 432 bytes to have simple SG elements and/or
731b0a2fdeeSScott Long  * chain elements. If we assume 32 bit addressing, this works out to
732b0a2fdeeSScott Long  * 54 SG or chain elements. If we assume 5 chain elements, then we have
733b0a2fdeeSScott Long  * a maximum of 49 seperate actual SG segments.
734b0a2fdeeSScott Long  */
735b0a2fdeeSScott Long #define MPT_SGL_MAX		49
736b0a2fdeeSScott Long 
737b0a2fdeeSScott Long #define	MPT_RQSL(mpt)		(mpt->request_frame_size << 2)
738b0a2fdeeSScott Long #define	MPT_NSGL(mpt)		(MPT_RQSL(mpt) / sizeof (SGE_SIMPLE32))
739b0a2fdeeSScott Long 
740b0a2fdeeSScott Long #define	MPT_NSGL_FIRST(mpt)				\
741b0a2fdeeSScott Long 	(((mpt->request_frame_size << 2) -		\
742b0a2fdeeSScott Long 	sizeof (MSG_SCSI_IO_REQUEST) -			\
743b0a2fdeeSScott Long 	sizeof (SGE_IO_UNION)) / sizeof (SGE_SIMPLE32))
744b0a2fdeeSScott Long 
745b0a2fdeeSScott Long /***************************** IOC Initialization *****************************/
746b0a2fdeeSScott Long int mpt_reset(struct mpt_softc *, int /*reinit*/);
747b0a2fdeeSScott Long 
748b0a2fdeeSScott Long /****************************** Debugging/Logging *****************************/
749b0a2fdeeSScott Long typedef struct mpt_decode_entry {
750b0a2fdeeSScott Long 	char    *name;
751b0a2fdeeSScott Long 	u_int	 value;
752b0a2fdeeSScott Long 	u_int	 mask;
753b0a2fdeeSScott Long } mpt_decode_entry_t;
754b0a2fdeeSScott Long 
755b0a2fdeeSScott Long int mpt_decode_value(mpt_decode_entry_t *table, u_int num_entries,
756b0a2fdeeSScott Long 		     const char *name, u_int value, u_int *cur_column,
757b0a2fdeeSScott Long 		     u_int wrap_point);
758b0a2fdeeSScott Long 
759b0a2fdeeSScott Long enum {
760b0a2fdeeSScott Long 	MPT_PRT_ALWAYS,
761b0a2fdeeSScott Long 	MPT_PRT_FATAL,
762b0a2fdeeSScott Long 	MPT_PRT_ERROR,
763b0a2fdeeSScott Long 	MPT_PRT_WARN,
764b0a2fdeeSScott Long 	MPT_PRT_INFO,
765b0a2fdeeSScott Long 	MPT_PRT_DEBUG,
766b0a2fdeeSScott Long 	MPT_PRT_TRACE
767b0a2fdeeSScott Long };
768b0a2fdeeSScott Long 
769b0a2fdeeSScott Long #define mpt_lprt(mpt, level, ...)		\
770b0a2fdeeSScott Long do {						\
771b0a2fdeeSScott Long 	if (level <= (mpt)->verbose)		\
772b0a2fdeeSScott Long 		mpt_prt(mpt, __VA_ARGS__);	\
773b0a2fdeeSScott Long } while (0)
774b0a2fdeeSScott Long 
775b0a2fdeeSScott Long #define mpt_lprtc(mpt, level, ...)		 \
776b0a2fdeeSScott Long do {						 \
777b0a2fdeeSScott Long 	if (level <= (mpt)->debug_level)	 \
778b0a2fdeeSScott Long 		mpt_prtc(mpt, __VA_ARGS__);	 \
779b0a2fdeeSScott Long } while (0)
780b0a2fdeeSScott Long 
781b0a2fdeeSScott Long void mpt_prt(struct mpt_softc *, const char *, ...);
782b0a2fdeeSScott Long void mpt_prtc(struct mpt_softc *, const char *, ...);
783b0a2fdeeSScott Long 
784b0a2fdeeSScott Long /**************************** Unclassified Routines ***************************/
785b0a2fdeeSScott Long void		mpt_send_cmd(struct mpt_softc *mpt, request_t *req);
786b0a2fdeeSScott Long int		mpt_recv_handshake_reply(struct mpt_softc *mpt,
787b0a2fdeeSScott Long 					 size_t reply_len, void *reply);
788b0a2fdeeSScott Long int		mpt_wait_req(struct mpt_softc *mpt, request_t *req,
789b0a2fdeeSScott Long 			     mpt_req_state_t state, mpt_req_state_t mask,
790b0a2fdeeSScott Long 			     int sleep_ok, int time_ms);
791b0a2fdeeSScott Long void		mpt_enable_ints(struct mpt_softc *mpt);
792b0a2fdeeSScott Long void		mpt_disable_ints(struct mpt_softc *mpt);
793b0a2fdeeSScott Long int		mpt_attach(struct mpt_softc *mpt);
794b0a2fdeeSScott Long int		mpt_shutdown(struct mpt_softc *mpt);
795b0a2fdeeSScott Long int		mpt_detach(struct mpt_softc *mpt);
796b0a2fdeeSScott Long int		mpt_send_handshake_cmd(struct mpt_softc *mpt,
797b0a2fdeeSScott Long 				       size_t len, void *cmd);
798b0a2fdeeSScott Long request_t *	mpt_get_request(struct mpt_softc *mpt, int sleep_ok);
799b0a2fdeeSScott Long void		mpt_free_request(struct mpt_softc *mpt, request_t *req);
800b0a2fdeeSScott Long void		mpt_intr(void *arg);
801b0a2fdeeSScott Long void		mpt_check_doorbell(struct mpt_softc *mpt);
802b0a2fdeeSScott Long void		mpt_dump_reply_frame(struct mpt_softc *mpt,
803b0a2fdeeSScott Long 				     MSG_DEFAULT_REPLY *reply_frame);
804b0a2fdeeSScott Long 
805b0a2fdeeSScott Long void		mpt_set_config_regs(struct mpt_softc *);
806b0a2fdeeSScott Long int		mpt_issue_cfg_req(struct mpt_softc */*mpt*/, request_t */*req*/,
807b0a2fdeeSScott Long 				  u_int /*Action*/, u_int /*PageVersion*/,
808b0a2fdeeSScott Long 				  u_int /*PageLength*/, u_int /*PageNumber*/,
809b0a2fdeeSScott Long 				  u_int /*PageType*/, uint32_t /*PageAddress*/,
810b0a2fdeeSScott Long 				  bus_addr_t /*addr*/, bus_size_t/*len*/,
811b0a2fdeeSScott Long 				  int /*sleep_ok*/, int /*timeout_ms*/);
812b0a2fdeeSScott Long int		mpt_read_cfg_header(struct mpt_softc *, int /*PageType*/,
813b0a2fdeeSScott Long 				    int /*PageNumber*/,
814b0a2fdeeSScott Long 				    uint32_t /*PageAddress*/,
815b0a2fdeeSScott Long 				    CONFIG_PAGE_HEADER *,
816b0a2fdeeSScott Long 				    int /*sleep_ok*/, int /*timeout_ms*/);
817b0a2fdeeSScott Long int		mpt_read_cfg_page(struct mpt_softc *t, int /*Action*/,
818b0a2fdeeSScott Long 				  uint32_t /*PageAddress*/,
819b0a2fdeeSScott Long 				  CONFIG_PAGE_HEADER *, size_t /*len*/,
820b0a2fdeeSScott Long 				  int /*sleep_ok*/, int /*timeout_ms*/);
821b0a2fdeeSScott Long int		mpt_write_cfg_page(struct mpt_softc *, int /*Action*/,
822b0a2fdeeSScott Long 				   uint32_t /*PageAddress*/,
823b0a2fdeeSScott Long 				   CONFIG_PAGE_HEADER *, size_t /*len*/,
824b0a2fdeeSScott Long 				   int /*sleep_ok*/, int /*timeout_ms*/);
825b0a2fdeeSScott Long static __inline int
826b0a2fdeeSScott Long mpt_read_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress,
827b0a2fdeeSScott Long 		      CONFIG_PAGE_HEADER *hdr, size_t len,
828b0a2fdeeSScott Long 		      int sleep_ok, int timeout_ms)
829b0a2fdeeSScott Long {
830b0a2fdeeSScott Long 	return (mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT,
831b0a2fdeeSScott Long 				  PageAddress, hdr, len, sleep_ok, timeout_ms));
832b0a2fdeeSScott Long }
833b0a2fdeeSScott Long 
834b0a2fdeeSScott Long static __inline int
835b0a2fdeeSScott Long mpt_write_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress,
836b0a2fdeeSScott Long 		       CONFIG_PAGE_HEADER *hdr, size_t len, int sleep_ok,
837b0a2fdeeSScott Long 		       int timeout_ms)
838b0a2fdeeSScott Long {
839b0a2fdeeSScott Long 	return (mpt_write_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT,
840b0a2fdeeSScott Long 				   PageAddress, hdr, len, sleep_ok,
841b0a2fdeeSScott Long 				   timeout_ms));
842b0a2fdeeSScott Long }
843ce68dae5SMatt Jacob 
8449b631363SMatt Jacob /* mpt_debug.c functions */
8459b631363SMatt Jacob void mpt_print_reply(void *vmsg);
846b0a2fdeeSScott Long void mpt_print_db(uint32_t mb);
8479b631363SMatt Jacob void mpt_print_config_reply(void *vmsg);
848b0a2fdeeSScott Long char *mpt_ioc_diag(uint32_t diag);
849b0a2fdeeSScott Long void mpt_req_state(mpt_req_state_t state);
8509b631363SMatt Jacob void mpt_print_config_request(void *vmsg);
8519b631363SMatt Jacob void mpt_print_request(void *vmsg);
852b0a2fdeeSScott Long void mpt_print_scsi_io_request(MSG_SCSI_IO_REQUEST *msg);
8539b631363SMatt Jacob #endif /* _MPT_H_ */
854