mpt.h revision 169293
1186545Srwatson/* $FreeBSD: head/sys/dev/mpt/mpt.h 169293 2007-05-05 20:18:24Z mjacob $ */
2186545Srwatson/*-
3186545Srwatson * Generic defines for LSI '909 FC  adapters.
4186545Srwatson * FreeBSD Version.
5186545Srwatson *
6186545Srwatson * Copyright (c)  2000, 2001 by Greg Ansley
7186545Srwatson *
8186545Srwatson * Redistribution and use in source and binary forms, with or without
9186545Srwatson * modification, are permitted provided that the following conditions
10186545Srwatson * are met:
11186545Srwatson * 1. Redistributions of source code must retain the above copyright
12186545Srwatson *    notice immediately at the beginning of the file, without modification,
13186545Srwatson *    this list of conditions, and the following disclaimer.
14186545Srwatson * 2. The name of the author may not be used to endorse or promote products
15186545Srwatson *    derived from this software without specific prior written permission.
16186545Srwatson *
17186545Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18186545Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19186545Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20186545Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
21186545Srwatson * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22186545Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23186545Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24186545Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25186545Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26186545Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27186545Srwatson * SUCH DAMAGE.
28186545Srwatson */
29189279Srwatson/*-
30186545Srwatson * Copyright (c) 2002, 2006 by Matthew Jacob
31186545Srwatson * All rights reserved.
32186545Srwatson *
33186545Srwatson * Redistribution and use in source and binary forms, with or without
34186545Srwatson * modification, are permitted provided that the following conditions are
35186545Srwatson * met:
36186545Srwatson * 1. Redistributions of source code must retain the above copyright
37186545Srwatson *    notice, this list of conditions and the following disclaimer.
38186545Srwatson * 2. Redistributions in binary form must reproduce at minimum a disclaimer
39186545Srwatson *    substantially similar to the "NO WARRANTY" disclaimer below
40186545Srwatson *    ("Disclaimer") and any redistribution must be conditioned upon including
41186545Srwatson *    a substantially similar Disclaimer requirement for further binary
42186545Srwatson *    redistribution.
43186545Srwatson * 3. Neither the names of the above listed copyright holders nor the names
44186545Srwatson *    of any contributors may be used to endorse or promote products derived
45186545Srwatson *    from this software without specific prior written permission.
46186545Srwatson *
47186545Srwatson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
48186545Srwatson * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
49186545Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
50186545Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
51186545Srwatson * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
52186545Srwatson * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
53186545Srwatson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
54186545Srwatson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
55186545Srwatson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
56186545Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
57186545Srwatson * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58186545Srwatson *
59186545Srwatson * Support from Chris Ellsworth in order to make SAS adapters work
60186545Srwatson * is gratefully acknowledged.
61186545Srwatson *
62186545Srwatson *
63186545Srwatson * Support from LSI-Logic has also gone a great deal toward making this a
64186545Srwatson * workable subsystem and is gratefully acknowledged.
65186545Srwatson */
66186545Srwatson/*
67189279Srwatson * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
68186545Srwatson * Copyright (c) 2004, 2005 Justin T. Gibbs
69186545Srwatson * Copyright (c) 2005, WHEEL Sp. z o.o.
70186545Srwatson * All rights reserved.
71186545Srwatson *
72186545Srwatson * Redistribution and use in source and binary forms, with or without
73186545Srwatson * modification, are permitted provided that the following conditions are
74186545Srwatson * met:
75186545Srwatson * 1. Redistributions of source code must retain the above copyright
76186545Srwatson *    notice, this list of conditions and the following disclaimer.
77189279Srwatson * 2. Redistributions in binary form must reproduce at minimum a disclaimer
78186545Srwatson *    substantially similar to the "NO WARRANTY" disclaimer below
79186545Srwatson *    ("Disclaimer") and any redistribution must be conditioned upon including
80186545Srwatson *    a substantially similar Disclaimer requirement for further binary
81186545Srwatson *    redistribution.
82186545Srwatson * 3. Neither the names of the above listed copyright holders nor the names
83186545Srwatson *    of any contributors may be used to endorse or promote products derived
84186545Srwatson *    from this software without specific prior written permission.
85186545Srwatson *
86186545Srwatson * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
87186545Srwatson * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
88186545Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
89186545Srwatson * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
90186545Srwatson * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
91186545Srwatson * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
92186545Srwatson * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
93186545Srwatson * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
94186545Srwatson * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
95186545Srwatson * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
96186545Srwatson * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
97186545Srwatson */
98186545Srwatson
99186545Srwatson#ifndef _MPT_H_
100186545Srwatson#define _MPT_H_
101186545Srwatson
102186545Srwatson/********************************* OS Includes ********************************/
103186545Srwatson#include <sys/types.h>
104186545Srwatson#include <sys/param.h>
105186545Srwatson#include <sys/systm.h>
106186545Srwatson#include <sys/endian.h>
107186545Srwatson#include <sys/eventhandler.h>
108186545Srwatson#if __FreeBSD_version < 500000
109186545Srwatson#include <sys/kernel.h>
110186545Srwatson#include <sys/queue.h>
111186545Srwatson#include <sys/malloc.h>
112186545Srwatson#include <sys/devicestat.h>
113#else
114#include <sys/lock.h>
115#include <sys/kernel.h>
116#include <sys/queue.h>
117#include <sys/malloc.h>
118#include <sys/mutex.h>
119#include <sys/condvar.h>
120#endif
121#include <sys/proc.h>
122#include <sys/bus.h>
123#include <sys/module.h>
124
125#include <machine/cpu.h>
126#include <machine/resource.h>
127
128#if __FreeBSD_version < 500000
129#include <machine/bus.h>
130#include <machine/clock.h>
131#endif
132
133#include <sys/rman.h>
134
135#if __FreeBSD_version < 500000
136#include <pci/pcireg.h>
137#include <pci/pcivar.h>
138#else
139#include <dev/pci/pcireg.h>
140#include <dev/pci/pcivar.h>
141#endif
142
143#include <machine/bus.h>
144#include "opt_ddb.h"
145
146/**************************** Register Definitions ****************************/
147#include <dev/mpt/mpt_reg.h>
148
149/******************************* MPI Definitions ******************************/
150#include <dev/mpt/mpilib/mpi_type.h>
151#include <dev/mpt/mpilib/mpi.h>
152#include <dev/mpt/mpilib/mpi_cnfg.h>
153#include <dev/mpt/mpilib/mpi_ioc.h>
154#include <dev/mpt/mpilib/mpi_raid.h>
155
156/* XXX For mpt_debug.c */
157#include <dev/mpt/mpilib/mpi_init.h>
158
159#define	MPT_S64_2_SCALAR(y)	((((int64_t)y.High) << 32) | (y.Low))
160#define	MPT_U64_2_SCALAR(y)	((((uint64_t)y.High) << 32) | (y.Low))
161
162/****************************** Misc Definitions ******************************/
163/* #define MPT_TEST_MULTIPATH	1 */
164#define MPT_OK (0)
165#define MPT_FAIL (0x10000)
166
167#define NUM_ELEMENTS(array) (sizeof(array) / sizeof(*array))
168
169#define	MPT_ROLE_NONE		0
170#define	MPT_ROLE_INITIATOR	1
171#define	MPT_ROLE_TARGET		2
172#define	MPT_ROLE_BOTH		3
173#define	MPT_ROLE_DEFAULT	MPT_ROLE_INITIATOR
174
175/**************************** Forward Declarations ****************************/
176struct mpt_softc;
177struct mpt_personality;
178typedef struct req_entry request_t;
179
180/************************* Personality Module Support *************************/
181typedef int mpt_load_handler_t(struct mpt_personality *);
182typedef int mpt_probe_handler_t(struct mpt_softc *);
183typedef int mpt_attach_handler_t(struct mpt_softc *);
184typedef int mpt_enable_handler_t(struct mpt_softc *);
185typedef void mpt_ready_handler_t(struct mpt_softc *);
186typedef int mpt_event_handler_t(struct mpt_softc *, request_t *,
187				MSG_EVENT_NOTIFY_REPLY *);
188typedef void mpt_reset_handler_t(struct mpt_softc *, int /*type*/);
189/* XXX Add return value and use for veto? */
190typedef void mpt_shutdown_handler_t(struct mpt_softc *);
191typedef void mpt_detach_handler_t(struct mpt_softc *);
192typedef int mpt_unload_handler_t(struct mpt_personality *);
193
194struct mpt_personality
195{
196	const char		*name;
197	uint32_t		 id;		/* Assigned identifier. */
198	u_int			 use_count;	/* Instances using personality*/
199	mpt_load_handler_t	*load;		/* configure personailty */
200#define MPT_PERS_FIRST_HANDLER(pers) (&(pers)->load)
201	mpt_probe_handler_t	*probe;		/* configure personailty */
202	mpt_attach_handler_t	*attach;	/* initialize device instance */
203	mpt_enable_handler_t	*enable;	/* enable device */
204	mpt_ready_handler_t	*ready;		/* final open for business */
205	mpt_event_handler_t	*event;		/* Handle MPI event. */
206	mpt_reset_handler_t	*reset;		/* Re-init after reset. */
207	mpt_shutdown_handler_t	*shutdown;	/* Shutdown instance. */
208	mpt_detach_handler_t	*detach;	/* release device instance */
209	mpt_unload_handler_t	*unload;	/* Shutdown personality */
210#define MPT_PERS_LAST_HANDLER(pers) (&(pers)->unload)
211};
212
213int mpt_modevent(module_t, int, void *);
214
215/* Maximum supported number of personalities. */
216#define MPT_MAX_PERSONALITIES	(15)
217
218#define MPT_PERSONALITY_DEPEND(name, dep, vmin, vpref, vmax) \
219	MODULE_DEPEND(name, dep, vmin, vpref, vmax)
220
221#define DECLARE_MPT_PERSONALITY(name, order)				  \
222	static moduledata_t name##_mod = {				  \
223		#name, mpt_modevent, &name##_personality		  \
224	};								  \
225	DECLARE_MODULE(name, name##_mod, SI_SUB_DRIVERS, order);	  \
226	MODULE_VERSION(name, 1);					  \
227	MPT_PERSONALITY_DEPEND(name, mpt_core, 1, 1, 1)
228
229/******************************* Bus DMA Support ******************************/
230/* XXX Need to update bus_dmamap_sync to take a range argument. */
231#define bus_dmamap_sync_range(dma_tag, dmamap, offset, len, op)	\
232	bus_dmamap_sync(dma_tag, dmamap, op)
233
234#if __FreeBSD_version < 600000
235#define	bus_get_dma_tag(x)	NULL
236#endif
237#if __FreeBSD_version >= 501102
238#define mpt_dma_tag_create(mpt, parent_tag, alignment, boundary,	\
239			   lowaddr, highaddr, filter, filterarg,	\
240			   maxsize, nsegments, maxsegsz, flags,		\
241			   dma_tagp)					\
242	bus_dma_tag_create(parent_tag, alignment, boundary,		\
243			   lowaddr, highaddr, filter, filterarg,	\
244			   maxsize, nsegments, maxsegsz, flags,		\
245			   busdma_lock_mutex, &(mpt)->mpt_lock,		\
246			   dma_tagp)
247#else
248#define mpt_dma_tag_create(mpt, parent_tag, alignment, boundary,	\
249			   lowaddr, highaddr, filter, filterarg,	\
250			   maxsize, nsegments, maxsegsz, flags,		\
251			   dma_tagp)					\
252	bus_dma_tag_create(parent_tag, alignment, boundary,		\
253			   lowaddr, highaddr, filter, filterarg,	\
254			   maxsize, nsegments, maxsegsz, flags,		\
255			   dma_tagp)
256#endif
257
258struct mpt_map_info {
259	struct mpt_softc *mpt;
260	int		  error;
261	uint32_t	  phys;
262};
263
264void mpt_map_rquest(void *, bus_dma_segment_t *, int, int);
265/* **************************** NewBUS interrupt Crock ************************/
266#if __FreeBSD_version < 700031
267#define	mpt_setup_intr(d, i, f, U, if, ifa, hp)	\
268	bus_setup_intr(d, i, f, if, ifa, hp)
269#else
270#define	mpt_setup_intr	bus_setup_intr
271#endif
272
273/**************************** Kernel Thread Support ***************************/
274#if __FreeBSD_version > 500005
275#define mpt_kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
276	kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg)
277#else
278#define mpt_kthread_create(func, farg, proc_ptr, flags, stackpgs, fmtstr, arg) \
279	kthread_create(func, farg, proc_ptr, fmtstr, arg)
280#endif
281
282/****************************** Timer Facilities ******************************/
283#if __FreeBSD_version > 500000
284#define mpt_callout_init(c)	callout_init(c, /*mpsafe*/1);
285#else
286#define mpt_callout_init(c)	callout_init(c);
287#endif
288
289/********************************** Endianess *********************************/
290#define	MPT_2_HOST64(ptr, tag)	ptr->tag = le64toh(ptr->tag)
291#define	MPT_2_HOST32(ptr, tag)	ptr->tag = le32toh(ptr->tag)
292#define	MPT_2_HOST16(ptr, tag)	ptr->tag = le16toh(ptr->tag)
293
294#define	HOST_2_MPT64(ptr, tag)	ptr->tag = htole64(ptr->tag)
295#define	HOST_2_MPT32(ptr, tag)	ptr->tag = htole32(ptr->tag)
296#define	HOST_2_MPT16(ptr, tag)	ptr->tag = htole16(ptr->tag)
297
298#if	_BYTE_ORDER == _BIG_ENDIAN
299void mpt2host_sge_simple_union(SGE_SIMPLE_UNION *);
300void mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *);
301void mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *);
302void mpt2host_config_page_ioc2(CONFIG_PAGE_IOC_2 *);
303void mpt2host_config_page_raid_vol_0(CONFIG_PAGE_RAID_VOL_0 *);
304void mpt2host_mpi_raid_vol_indicator(MPI_RAID_VOL_INDICATOR *);
305#else
306#define	mpt2host_sge_simple_union(x)		do { ; } while (0)
307#define	mpt2host_iocfacts_reply(x)		do { ; } while (0)
308#define	mpt2host_portfacts_reply(x)		do { ; } while (0)
309#define	mpt2host_config_page_ioc2(x)		do { ; } while (0)
310#define	mpt2host_config_page_raid_vol_0(x)	do { ; } while (0)
311#define	mpt2host_mpi_raid_vol_indicator(x)	do { ; } while (0)
312#endif
313
314/**************************** MPI Transaction State ***************************/
315typedef enum {
316	REQ_STATE_NIL		= 0x00,
317	REQ_STATE_FREE		= 0x01,
318	REQ_STATE_ALLOCATED	= 0x02,
319	REQ_STATE_QUEUED	= 0x04,
320	REQ_STATE_DONE		= 0x08,
321	REQ_STATE_TIMEDOUT	= 0x10,
322	REQ_STATE_NEED_WAKEUP	= 0x20,
323	REQ_STATE_LOCKED	= 0x80,	/* can't be freed */
324	REQ_STATE_MASK		= 0xFF
325} mpt_req_state_t;
326
327struct req_entry {
328	TAILQ_ENTRY(req_entry) links;	/* Pointer to next in list */
329	mpt_req_state_t	state;		/* Request State Information */
330	uint16_t	index;		/* Index of this entry */
331	uint16_t	IOCStatus;	/* Completion status */
332	uint16_t	ResponseCode;	/* TMF Reponse Code */
333	uint16_t	serno;		/* serial number */
334	union ccb      *ccb;		/* CAM request */
335	void	       *req_vbuf;	/* Virtual Address of Entry */
336	void	       *sense_vbuf;	/* Virtual Address of sense data */
337	bus_addr_t	req_pbuf;	/* Physical Address of Entry */
338	bus_addr_t	sense_pbuf;	/* Physical Address of sense data */
339	bus_dmamap_t	dmap;		/* DMA map for data buffers */
340	struct req_entry *chain;	/* for SGE overallocations */
341	struct callout  callout;	/* Timeout for the request */
342};
343
344/**************************** MPI Target State Info ***************************/
345
346typedef struct {
347	uint32_t reply_desc;	/* current reply descriptor */
348	uint32_t resid;		/* current data residual */
349	uint32_t bytes_xfered;	/* current relative offset */
350	union ccb *ccb;		/* pointer to currently active ccb */
351	request_t *req;		/* pointer to currently active assist request */
352	uint32_t
353		is_local : 1,
354		nxfers	 : 31;
355	uint32_t tag_id;
356	enum {
357		TGT_STATE_NIL,
358		TGT_STATE_LOADING,
359		TGT_STATE_LOADED,
360		TGT_STATE_IN_CAM,
361                TGT_STATE_SETTING_UP_FOR_DATA,
362                TGT_STATE_MOVING_DATA,
363                TGT_STATE_MOVING_DATA_AND_STATUS,
364                TGT_STATE_SENDING_STATUS
365	} state;
366} mpt_tgt_state_t;
367
368/*
369 * When we get an incoming command it has its own tag which is called the
370 * IoIndex. This is the value we gave that particular command buffer when
371 * we originally assigned it. It's just a number, really. The FC card uses
372 * it as an RX_ID. We can use it to index into mpt->tgt_cmd_ptrs, which
373 * contains pointers the request_t structures related to that IoIndex.
374 *
375 * What *we* do is construct a tag out of the index for the target command
376 * which owns the incoming ATIO plus a rolling sequence number.
377 */
378#define	MPT_MAKE_TAGID(mpt, req, ioindex)	\
379 ((ioindex << 18) | (((mpt->sequence++) & 0x3f) << 12) | (req->index & 0xfff))
380
381#ifdef	INVARIANTS
382#define	MPT_TAG_2_REQ(a, b)		mpt_tag_2_req(a, (uint32_t) b)
383#else
384#define	MPT_TAG_2_REQ(mpt, tag)		mpt->tgt_cmd_ptrs[tag >> 18]
385#endif
386
387#define	MPT_TGT_STATE(mpt, req) ((mpt_tgt_state_t *) \
388    (&((uint8_t *)req->req_vbuf)[MPT_RQSL(mpt) - sizeof (mpt_tgt_state_t)]))
389
390STAILQ_HEAD(mpt_hdr_stailq, ccb_hdr);
391#define	MPT_MAX_LUNS	256
392typedef struct {
393	struct mpt_hdr_stailq	atios;
394	struct mpt_hdr_stailq	inots;
395	int enabled;
396} tgt_resource_t;
397#define	MPT_MAX_ELS	64
398
399/**************************** Handler Registration ****************************/
400/*
401 * Global table of registered reply handlers.  The
402 * handler is indicated by byte 3 of the request
403 * index submitted to the IOC.  This allows the
404 * driver core to perform generic processing without
405 * any knowledge of per-personality behavior.
406 *
407 * MPT_NUM_REPLY_HANDLERS must be a power of 2
408 * to allow the easy generation of a mask.
409 *
410 * The handler offsets used by the core are hard coded
411 * allowing faster code generation when assigning a handler
412 * to a request.  All "personalities" must use the
413 * the handler registration mechanism.
414 *
415 * The IOC handlers that are rarely executed are placed
416 * at the tail of the table to make it more likely that
417 * all commonly executed handlers fit in a single cache
418 * line.
419 */
420#define MPT_NUM_REPLY_HANDLERS		(32)
421#define MPT_REPLY_HANDLER_EVENTS	MPT_CBI_TO_HID(0)
422#define MPT_REPLY_HANDLER_CONFIG	MPT_CBI_TO_HID(MPT_NUM_REPLY_HANDLERS-1)
423#define MPT_REPLY_HANDLER_HANDSHAKE	MPT_CBI_TO_HID(MPT_NUM_REPLY_HANDLERS-2)
424typedef int mpt_reply_handler_t(struct mpt_softc *mpt, request_t *request,
425    uint32_t reply_desc, MSG_DEFAULT_REPLY *reply_frame);
426typedef union {
427	mpt_reply_handler_t	*reply_handler;
428} mpt_handler_t;
429
430typedef enum {
431	MPT_HANDLER_REPLY,
432	MPT_HANDLER_EVENT,
433	MPT_HANDLER_RESET,
434	MPT_HANDLER_SHUTDOWN
435} mpt_handler_type;
436
437struct mpt_handler_record
438{
439	LIST_ENTRY(mpt_handler_record)	links;
440	mpt_handler_t			handler;
441};
442
443LIST_HEAD(mpt_handler_list, mpt_handler_record);
444
445/*
446 * The handler_id is currently unused but would contain the
447 * handler ID used in the MsgContext field to allow direction
448 * of replies to the handler.  Registrations that don't require
449 * a handler id can pass in NULL for the handler_id.
450 *
451 * Deregistrations for handlers without a handler id should
452 * pass in MPT_HANDLER_ID_NONE.
453 */
454#define MPT_HANDLER_ID_NONE		(0xFFFFFFFF)
455int mpt_register_handler(struct mpt_softc *, mpt_handler_type,
456			 mpt_handler_t, uint32_t *);
457int mpt_deregister_handler(struct mpt_softc *, mpt_handler_type,
458			   mpt_handler_t, uint32_t);
459
460/******************* Per-Controller Instance Data Structures ******************/
461TAILQ_HEAD(req_queue, req_entry);
462
463/* Structure for saving proper values for modifyable PCI config registers */
464struct mpt_pci_cfg {
465	uint16_t Command;
466	uint16_t LatencyTimer_LineSize;
467	uint32_t IO_BAR;
468	uint32_t Mem0_BAR[2];
469	uint32_t Mem1_BAR[2];
470	uint32_t ROM_BAR;
471	uint8_t  IntLine;
472	uint32_t PMCSR;
473};
474
475typedef enum {
476	MPT_RVF_NONE		= 0x0,
477	MPT_RVF_ACTIVE		= 0x1,
478	MPT_RVF_ANNOUNCED	= 0x2,
479	MPT_RVF_UP2DATE		= 0x4,
480	MPT_RVF_REFERENCED	= 0x8,
481	MPT_RVF_WCE_CHANGED	= 0x10
482} mpt_raid_volume_flags;
483
484struct mpt_raid_volume {
485	CONFIG_PAGE_RAID_VOL_0	       *config_page;
486	MPI_RAID_VOL_INDICATOR		sync_progress;
487	mpt_raid_volume_flags		flags;
488	u_int				quiesced_disks;
489};
490
491typedef enum {
492	MPT_RDF_NONE		= 0x00,
493	MPT_RDF_ACTIVE		= 0x01,
494	MPT_RDF_ANNOUNCED	= 0x02,
495	MPT_RDF_UP2DATE		= 0x04,
496	MPT_RDF_REFERENCED	= 0x08,
497	MPT_RDF_QUIESCING	= 0x10,
498	MPT_RDF_QUIESCED	= 0x20
499} mpt_raid_disk_flags;
500
501struct mpt_raid_disk {
502	CONFIG_PAGE_RAID_PHYS_DISK_0	config_page;
503	struct mpt_raid_volume	       *volume;
504	u_int				member_number;
505	u_int				pass_thru_active;
506	mpt_raid_disk_flags		flags;
507};
508
509struct mpt_evtf_record {
510	MSG_EVENT_NOTIFY_REPLY		reply;
511	uint32_t			context;
512	LIST_ENTRY(mpt_evtf_record)	links;
513};
514
515LIST_HEAD(mpt_evtf_list, mpt_evtf_record);
516
517struct mpt_softc {
518	device_t		dev;
519#if __FreeBSD_version < 500000
520	uint32_t		mpt_islocked;
521	int			mpt_splsaved;
522#else
523	struct mtx		mpt_lock;
524	int			mpt_locksetup;
525#endif
526	uint32_t		mpt_pers_mask;
527	uint32_t
528				: 8,
529		unit		: 8,
530		ready		: 1,
531		fw_uploaded	: 1,
532		msi_enable	: 1,
533		twildcard	: 1,
534		tenabled	: 1,
535		do_cfg_role	: 1,
536		raid_enabled	: 1,
537		raid_mwce_set	: 1,
538		getreqwaiter	: 1,
539		shutdwn_raid    : 1,
540		shutdwn_recovery: 1,
541		outofbeer	: 1,
542		disabled	: 1,
543		is_spi		: 1,
544		is_sas		: 1,
545		is_fc		: 1;
546
547	u_int			cfg_role;
548	u_int			role;	/* role: none, ini, target, both */
549
550	u_int			verbose;
551#ifdef	MPT_TEST_MULTIPATH
552	int			failure_id;
553#endif
554
555	/*
556	 * IOC Facts
557	 */
558	MSG_IOC_FACTS_REPLY	ioc_facts;
559
560	/*
561	 * Port Facts
562	 */
563	MSG_PORT_FACTS_REPLY *	port_facts;
564#define	mpt_ini_id	port_facts[0].PortSCSIID
565#define	mpt_max_tgtcmds	port_facts[0].MaxPostedCmdBuffers
566
567	/*
568	 * Device Configuration Information
569	 */
570	union {
571		struct mpt_spi_cfg {
572			CONFIG_PAGE_SCSI_PORT_0		_port_page0;
573			CONFIG_PAGE_SCSI_PORT_1		_port_page1;
574			CONFIG_PAGE_SCSI_PORT_2		_port_page2;
575			CONFIG_PAGE_SCSI_DEVICE_0	_dev_page0[16];
576			CONFIG_PAGE_SCSI_DEVICE_1	_dev_page1[16];
577			uint16_t			_tag_enable;
578			uint16_t			_disc_enable;
579		} spi;
580#define	mpt_port_page0		cfg.spi._port_page0
581#define	mpt_port_page1		cfg.spi._port_page1
582#define	mpt_port_page2		cfg.spi._port_page2
583#define	mpt_dev_page0		cfg.spi._dev_page0
584#define	mpt_dev_page1		cfg.spi._dev_page1
585#define	mpt_tag_enable		cfg.spi._tag_enable
586#define	mpt_disc_enable		cfg.spi._disc_enable
587		struct mpi_fc_cfg {
588			CONFIG_PAGE_FC_PORT_0 _port_page0;
589			uint32_t _port_speed;
590#define	mpt_fcport_page0	cfg.fc._port_page0
591#define	mpt_fcport_speed	cfg.fc._port_speed
592		} fc;
593	} cfg;
594#if __FreeBSD_version >= 500000
595	/*
596	 * Device config information stored up for sysctl to access
597	 */
598	union {
599		struct {
600			unsigned int initiator_id;
601		} spi;
602		struct {
603			char wwnn[19];
604			char wwpn[19];
605		} fc;
606	} scinfo;
607#endif
608
609	/* Controller Info for RAID information */
610	CONFIG_PAGE_IOC_2 *	ioc_page2;
611	CONFIG_PAGE_IOC_3 *	ioc_page3;
612
613	/* Raid Data */
614	struct mpt_raid_volume* raid_volumes;
615	struct mpt_raid_disk*	raid_disks;
616	u_int			raid_max_volumes;
617	u_int			raid_max_disks;
618	u_int			raid_page0_len;
619	u_int			raid_wakeup;
620	u_int			raid_rescan;
621	u_int			raid_resync_rate;
622	u_int			raid_mwce_setting;
623	u_int			raid_queue_depth;
624	u_int			raid_nonopt_volumes;
625	struct proc	       *raid_thread;
626	struct callout		raid_timer;
627
628	/*
629	 * PCI Hardware info
630	 */
631	int			pci_msi_count;
632	struct resource *	pci_irq;	/* Interrupt map for chip */
633	void *			ih;		/* Interupt handle */
634	struct mpt_pci_cfg	pci_cfg;	/* saved PCI conf registers */
635
636	/*
637	 * DMA Mapping Stuff
638	 */
639	struct resource *	pci_reg;	/* Register map for chip */
640	int			pci_mem_rid;	/* Resource ID */
641	bus_space_tag_t		pci_st;		/* Bus tag for registers */
642	bus_space_handle_t	pci_sh;		/* Bus handle for registers */
643	/* PIO versions of above. */
644	int			pci_pio_rid;
645	struct resource *	pci_pio_reg;
646	bus_space_tag_t		pci_pio_st;
647	bus_space_handle_t	pci_pio_sh;
648
649	bus_dma_tag_t		parent_dmat;	/* DMA tag for parent PCI bus */
650	bus_dma_tag_t		reply_dmat;	/* DMA tag for reply memory */
651	bus_dmamap_t		reply_dmap;	/* DMA map for reply memory */
652	uint8_t		       *reply;		/* KVA of reply memory */
653	bus_addr_t		reply_phys;	/* BusAddr of reply memory */
654
655	bus_dma_tag_t		buffer_dmat;	/* DMA tag for buffers */
656	bus_dma_tag_t		request_dmat;	/* DMA tag for request memroy */
657	bus_dmamap_t		request_dmap;	/* DMA map for request memroy */
658	uint8_t		       *request;	/* KVA of Request memory */
659	bus_addr_t		request_phys;	/* BusAddr of request memory */
660
661	uint32_t		max_seg_cnt;	/* calculated after IOC facts */
662
663	/*
664	 * Hardware management
665	 */
666	u_int			reset_cnt;
667
668	/*
669	 * CAM && Software Management
670	 */
671	request_t	       *request_pool;
672	struct req_queue	request_free_list;
673	struct req_queue	request_pending_list;
674	struct req_queue	request_timeout_list;
675
676
677	struct cam_sim	       *sim;
678	struct cam_path	       *path;
679
680	struct cam_sim	       *phydisk_sim;
681	struct cam_path	       *phydisk_path;
682
683	struct proc	       *recovery_thread;
684	request_t	       *tmf_req;
685
686	/*
687	 * Deferred frame acks due to resource shortage.
688	 */
689	struct mpt_evtf_list	ack_frames;
690
691	/*
692	 * Target Mode Support
693	 */
694	uint32_t		scsi_tgt_handler_id;
695	request_t **		tgt_cmd_ptrs;
696	request_t **		els_cmd_ptrs;	/* FC only */
697
698	/*
699	 * *snork*- this is chosen to be here *just in case* somebody
700	 * forgets to point to it exactly and we index off of trt with
701	 * CAM_LUN_WILDCARD.
702	 */
703	tgt_resource_t		trt_wildcard;		/* wildcard luns */
704	tgt_resource_t		trt[MPT_MAX_LUNS];
705	uint16_t		tgt_cmds_allocated;
706	uint16_t		els_cmds_allocated;	/* FC only */
707
708	uint16_t		timeouts;	/* timeout count */
709	uint16_t		success;	/* successes afer timeout */
710	uint16_t		sequence;	/* Sequence Number */
711	uint16_t		pad3;
712
713
714	/* Paired port in some dual adapters configurations */
715	struct mpt_softc *	mpt2;
716
717	/* FW Image management */
718	uint32_t		fw_image_size;
719	uint8_t		       *fw_image;
720	bus_dma_tag_t		fw_dmat;	/* DMA tag for firmware image */
721	bus_dmamap_t		fw_dmap;	/* DMA map for firmware image */
722	bus_addr_t		fw_phys;	/* BusAddr of firmware image */
723
724	/* Shutdown Event Handler. */
725	eventhandler_tag         eh;
726
727	TAILQ_ENTRY(mpt_softc)	links;
728};
729
730static __inline void mpt_assign_serno(struct mpt_softc *, request_t *);
731
732static __inline void
733mpt_assign_serno(struct mpt_softc *mpt, request_t *req)
734{
735	if ((req->serno = mpt->sequence++) == 0) {
736		req->serno = mpt->sequence++;
737	}
738}
739
740/***************************** Locking Primitives *****************************/
741#if __FreeBSD_version < 500000
742#define	MPT_IFLAGS		INTR_TYPE_CAM
743#define	MPT_LOCK(mpt)		mpt_lockspl(mpt)
744#define	MPT_UNLOCK(mpt)		mpt_unlockspl(mpt)
745#define	MPT_OWNED(mpt)		mpt->mpt_islocked
746#define	MPT_LOCK_ASSERT(mpt)
747#define	MPTLOCK_2_CAMLOCK	MPT_UNLOCK
748#define	CAMLOCK_2_MPTLOCK	MPT_LOCK
749#define	MPT_LOCK_SETUP(mpt)
750#define	MPT_LOCK_DESTROY(mpt)
751
752static __inline void mpt_lockspl(struct mpt_softc *mpt);
753static __inline void mpt_unlockspl(struct mpt_softc *mpt);
754
755static __inline void
756mpt_lockspl(struct mpt_softc *mpt)
757{
758       int s;
759
760       s = splcam();
761       if (mpt->mpt_islocked++ == 0) {
762               mpt->mpt_splsaved = s;
763       } else {
764               splx(s);
765	       panic("Recursed lock with mask: 0x%x\n", s);
766       }
767}
768
769static __inline void
770mpt_unlockspl(struct mpt_softc *mpt)
771{
772       if (mpt->mpt_islocked) {
773               if (--mpt->mpt_islocked == 0) {
774                       splx(mpt->mpt_splsaved);
775               }
776       } else
777	       panic("Negative lock count\n");
778}
779
780static __inline int
781mpt_sleep(struct mpt_softc *mpt, void *ident, int priority,
782	   const char *wmesg, int timo)
783{
784	int saved_cnt;
785	int saved_spl;
786	int error;
787
788	KASSERT(mpt->mpt_islocked <= 1, ("Invalid lock count on tsleep"));
789	saved_cnt = mpt->mpt_islocked;
790	saved_spl = mpt->mpt_splsaved;
791	mpt->mpt_islocked = 0;
792	error = tsleep(ident, priority, wmesg, timo);
793	KASSERT(mpt->mpt_islocked == 0, ("Invalid lock count on wakeup"));
794	mpt->mpt_islocked = saved_cnt;
795	mpt->mpt_splsaved = saved_spl;
796	return (error);
797}
798
799#define mpt_req_timeout(req, ticks, func, arg) \
800	callout_reset(&(req)->callout, (ticks), (func), (arg));
801#define mpt_req_untimeout(req, func, arg) \
802	callout_stop(&(req)->callout)
803#define mpt_req_timeout_init(req) \
804	callout_init(&(req)->callout)
805
806#else
807#if 1
808#define	MPT_IFLAGS		INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE
809#define	MPT_LOCK_SETUP(mpt)						\
810		mtx_init(&mpt->mpt_lock, "mpt", NULL, MTX_DEF);		\
811		mpt->mpt_locksetup = 1
812#define	MPT_LOCK_DESTROY(mpt)						\
813	if (mpt->mpt_locksetup) {					\
814		mtx_destroy(&mpt->mpt_lock);				\
815		mpt->mpt_locksetup = 0;					\
816	}
817
818#define	MPT_LOCK(mpt)		mtx_lock(&(mpt)->mpt_lock)
819#define	MPT_UNLOCK(mpt)		mtx_unlock(&(mpt)->mpt_lock)
820#define	MPT_OWNED(mpt)		mtx_owned(&(mpt)->mpt_lock)
821#define	MPT_LOCK_ASSERT(mpt)	mtx_assert(&(mpt)->mpt_lock, MA_OWNED)
822#define	MPTLOCK_2_CAMLOCK(mpt)
823#define	CAMLOCK_2_MPTLOCK(mpt)
824#define mpt_sleep(mpt, ident, priority, wmesg, timo) \
825	msleep(ident, &(mpt)->mpt_lock, priority, wmesg, timo)
826#define mpt_req_timeout(req, ticks, func, arg) \
827	callout_reset(&(req)->callout, (ticks), (func), (arg));
828#define mpt_req_untimeout(req, func, arg) \
829	callout_stop(&(req)->callout)
830#define mpt_req_timeout_init(req) \
831	callout_init(&(req)->callout, 1)
832
833#else
834
835#define	MPT_IFLAGS		INTR_TYPE_CAM | INTR_ENTROPY
836#define	MPT_LOCK_SETUP(mpt)	do { } while (0)
837#define	MPT_LOCK_DESTROY(mpt)	do { } while (0)
838#define	MPT_LOCK_ASSERT(mpt)	mtx_assert(&Giant, MA_OWNED)
839#define	MPT_LOCK(mpt)		mtx_lock(&Giant)
840#define	MPT_UNLOCK(mpt)		mtx_unlock(&Giant)
841#define	MPTLOCK_2_CAMLOCK(mpt)
842#define	CAMLOCK_2_MPTLOCK(mpt)
843
844static __inline int
845mpt_sleep(struct mpt_softc *, void *, int, const char *, int);
846
847#define mpt_ccb_timeout(ccb, ticks, func, arg) \
848	do {	\
849		(ccb)->ccb_h.timeout_ch = timeout((func), (arg), (ticks)); \
850	} while (0)
851#define mpt_ccb_untimeout(ccb, func, arg) \
852	untimeout((func), (arg), (ccb)->ccb_h.timeout_ch)
853#define mpt_ccb_timeout_init(ccb) \
854	callout_handle_init(&(ccb)->ccb_h.timeout_ch)
855
856static __inline int
857mpt_sleep(struct mpt_softc *mpt, void *i, int p, const char *w, int t)
858{
859	int r;
860	r = tsleep(i, p, w, t);
861	return (r);
862}
863#endif
864#endif
865
866/******************************* Register Access ******************************/
867static __inline void mpt_write(struct mpt_softc *, size_t, uint32_t);
868static __inline uint32_t mpt_read(struct mpt_softc *, int);
869static __inline void mpt_pio_write(struct mpt_softc *, size_t, uint32_t);
870static __inline uint32_t mpt_pio_read(struct mpt_softc *, int);
871
872static __inline void
873mpt_write(struct mpt_softc *mpt, size_t offset, uint32_t val)
874{
875	bus_space_write_4(mpt->pci_st, mpt->pci_sh, offset, val);
876}
877
878static __inline uint32_t
879mpt_read(struct mpt_softc *mpt, int offset)
880{
881	return (bus_space_read_4(mpt->pci_st, mpt->pci_sh, offset));
882}
883
884/*
885 * Some operations (e.g. diagnostic register writes while the ARM proccessor
886 * is disabled), must be performed using "PCI pio" operations.  On non-PCI
887 * busses, these operations likely map to normal register accesses.
888 */
889static __inline void
890mpt_pio_write(struct mpt_softc *mpt, size_t offset, uint32_t val)
891{
892	bus_space_write_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset, val);
893}
894
895static __inline uint32_t
896mpt_pio_read(struct mpt_softc *mpt, int offset)
897{
898	return (bus_space_read_4(mpt->pci_pio_st, mpt->pci_pio_sh, offset));
899}
900/*********************** Reply Frame/Request Management ***********************/
901/* Max MPT Reply we are willing to accept (must be power of 2) */
902#define MPT_REPLY_SIZE   	256
903
904/*
905 * Must be less than 16384 in order for target mode to work
906 */
907#define MPT_MAX_REQUESTS(mpt)	512
908#define MPT_REQUEST_AREA	512
909#define MPT_SENSE_SIZE		32	/* included in MPT_REQUEST_AREA */
910#define MPT_REQ_MEM_SIZE(mpt)	(MPT_MAX_REQUESTS(mpt) * MPT_REQUEST_AREA)
911
912#define MPT_CONTEXT_CB_SHIFT	(16)
913#define MPT_CBI(handle)		(handle >> MPT_CONTEXT_CB_SHIFT)
914#define MPT_CBI_TO_HID(cbi)	((cbi) << MPT_CONTEXT_CB_SHIFT)
915#define MPT_CONTEXT_TO_CBI(x)	\
916    (((x) >> MPT_CONTEXT_CB_SHIFT) & (MPT_NUM_REPLY_HANDLERS - 1))
917#define MPT_CONTEXT_REQI_MASK	0xFFFF
918#define MPT_CONTEXT_TO_REQI(x)	((x) & MPT_CONTEXT_REQI_MASK)
919
920/*
921 * Convert a 32bit physical address returned from IOC to an
922 * offset into our reply frame memory or the kvm address needed
923 * to access the data.  The returned address is only the low
924 * 32 bits, so mask our base physical address accordingly.
925 */
926#define MPT_REPLY_BADDR(x)		\
927	(x << 1)
928#define MPT_REPLY_OTOV(m, i) 		\
929	((void *)(&m->reply[i]))
930
931#define	MPT_DUMP_REPLY_FRAME(mpt, reply_frame)		\
932do {							\
933	if (mpt->verbose > MPT_PRT_DEBUG)		\
934		mpt_dump_reply_frame(mpt, reply_frame);	\
935} while(0)
936
937static __inline uint32_t mpt_pop_reply_queue(struct mpt_softc *mpt);
938static __inline void mpt_free_reply(struct mpt_softc *mpt, uint32_t ptr);
939
940/*
941 * Give the reply buffer back to the IOC after we have
942 * finished processing it.
943 */
944static __inline void
945mpt_free_reply(struct mpt_softc *mpt, uint32_t ptr)
946{
947     mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
948}
949
950/* Get a reply from the IOC */
951static __inline uint32_t
952mpt_pop_reply_queue(struct mpt_softc *mpt)
953{
954     return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
955}
956
957void
958mpt_complete_request_chain(struct mpt_softc *, struct req_queue *, u_int);
959
960/************************** Scatter Gather Managment **************************/
961/* MPT_RQSL- size of request frame, in bytes */
962#define	MPT_RQSL(mpt)		(mpt->ioc_facts.RequestFrameSize << 2)
963
964/* MPT_NSGL- how many SG entries can fit in a request frame size */
965#define	MPT_NSGL(mpt)		(MPT_RQSL(mpt) / sizeof (SGE_IO_UNION))
966
967/* MPT_NRFM- how many request frames can fit in each request alloc we make */
968#define	MPT_NRFM(mpt)		(MPT_REQUEST_AREA / MPT_RQSL(mpt))
969
970/*
971 * MPT_NSGL_FIRST- # of SG elements that can fit after
972 * an I/O request but still within the request frame.
973 * Do this safely based upon SGE_IO_UNION.
974 *
975 * Note that the first element is *within* the SCSI request.
976 */
977#define	MPT_NSGL_FIRST(mpt)	\
978    ((MPT_RQSL(mpt) - sizeof (MSG_SCSI_IO_REQUEST) + sizeof (SGE_IO_UNION)) / \
979    sizeof (SGE_IO_UNION))
980
981/***************************** IOC Initialization *****************************/
982int mpt_reset(struct mpt_softc *, int /*reinit*/);
983
984/****************************** Debugging ************************************/
985typedef struct mpt_decode_entry {
986	char    *name;
987	u_int	 value;
988	u_int	 mask;
989} mpt_decode_entry_t;
990
991int mpt_decode_value(mpt_decode_entry_t *table, u_int num_entries,
992		     const char *name, u_int value, u_int *cur_column,
993		     u_int wrap_point);
994
995void mpt_dump_data(struct mpt_softc *, const char *, void *, int);
996void mpt_dump_request(struct mpt_softc *, request_t *);
997
998enum {
999	MPT_PRT_ALWAYS,
1000	MPT_PRT_FATAL,
1001	MPT_PRT_ERROR,
1002	MPT_PRT_WARN,
1003	MPT_PRT_INFO,
1004	MPT_PRT_NEGOTIATION,
1005	MPT_PRT_DEBUG,
1006	MPT_PRT_DEBUG1,
1007	MPT_PRT_DEBUG2,
1008	MPT_PRT_DEBUG3,
1009	MPT_PRT_TRACE,
1010	MPT_PRT_NONE=100
1011};
1012
1013#if __FreeBSD_version > 500000
1014#define mpt_lprt(mpt, level, ...)		\
1015do {						\
1016	if (level <= (mpt)->verbose)		\
1017		mpt_prt(mpt, __VA_ARGS__);	\
1018} while (0)
1019
1020#define mpt_lprtc(mpt, level, ...)		 \
1021do {						 \
1022	if (level <= (mpt)->debug_level)	 \
1023		mpt_prtc(mpt, __VA_ARGS__);	 \
1024} while (0)
1025#else
1026void mpt_lprt(struct mpt_softc *, int, const char *, ...)
1027	__printflike(3, 4);
1028void mpt_lprtc(struct mpt_softc *, int, const char *, ...)
1029	__printflike(3, 4);
1030#endif
1031void mpt_prt(struct mpt_softc *, const char *, ...)
1032	__printflike(2, 3);
1033void mpt_prtc(struct mpt_softc *, const char *, ...)
1034	__printflike(2, 3);
1035
1036/**************************** Target Mode Related ***************************/
1037static __inline int mpt_cdblen(uint8_t, int);
1038static __inline int
1039mpt_cdblen(uint8_t cdb0, int maxlen)
1040{
1041	int group = cdb0 >> 5;
1042	switch (group) {
1043	case 0:
1044		return (6);
1045	case 1:
1046		return (10);
1047	case 4:
1048	case 5:
1049		return (12);
1050	default:
1051		return (16);
1052	}
1053}
1054#ifdef	INVARIANTS
1055static __inline request_t * mpt_tag_2_req(struct mpt_softc *, uint32_t);
1056static __inline request_t *
1057mpt_tag_2_req(struct mpt_softc *mpt, uint32_t tag)
1058{
1059	uint16_t rtg = (tag >> 18);
1060	KASSERT(rtg < mpt->tgt_cmds_allocated, ("bad tag %d\n", tag));
1061	KASSERT(mpt->tgt_cmd_ptrs, ("no cmd backpointer array"));
1062	KASSERT(mpt->tgt_cmd_ptrs[rtg], ("no cmd backpointer"));
1063	return (mpt->tgt_cmd_ptrs[rtg]);
1064}
1065
1066
1067static __inline int
1068mpt_req_on_free_list(struct mpt_softc *, request_t *);
1069static __inline int
1070mpt_req_on_pending_list(struct mpt_softc *, request_t *);
1071
1072static __inline void
1073mpt_req_spcl(struct mpt_softc *, request_t *, const char *, int);
1074static __inline void
1075mpt_req_not_spcl(struct mpt_softc *, request_t *, const char *, int);
1076
1077
1078/*
1079 * Is request on freelist?
1080 */
1081static __inline int
1082mpt_req_on_free_list(struct mpt_softc *mpt, request_t *req)
1083{
1084	request_t *lrq;
1085
1086	TAILQ_FOREACH(lrq, &mpt->request_free_list, links) {
1087		if (lrq == req) {
1088			return (1);
1089		}
1090	}
1091	return (0);
1092}
1093
1094/*
1095 * Is request on pending list?
1096 */
1097static __inline int
1098mpt_req_on_pending_list(struct mpt_softc *mpt, request_t *req)
1099{
1100	request_t *lrq;
1101
1102	TAILQ_FOREACH(lrq, &mpt->request_pending_list, links) {
1103		if (lrq == req) {
1104			return (1);
1105		}
1106	}
1107	return (0);
1108}
1109
1110/*
1111 * Make sure that req *is* part of one of the special lists
1112 */
1113static __inline void
1114mpt_req_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line)
1115{
1116	int i;
1117	for (i = 0; i < mpt->els_cmds_allocated; i++) {
1118		if (req == mpt->els_cmd_ptrs[i]) {
1119			return;
1120		}
1121	}
1122	for (i = 0; i < mpt->tgt_cmds_allocated; i++) {
1123		if (req == mpt->tgt_cmd_ptrs[i]) {
1124			return;
1125		}
1126	}
1127	panic("%s(%d): req %p:%u function %x not in els or tgt ptrs\n",
1128	    s, line, req, req->serno,
1129	    ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function);
1130}
1131
1132/*
1133 * Make sure that req is *not* part of one of the special lists.
1134 */
1135static __inline void
1136mpt_req_not_spcl(struct mpt_softc *mpt, request_t *req, const char *s, int line)
1137{
1138	int i;
1139	for (i = 0; i < mpt->els_cmds_allocated; i++) {
1140		KASSERT(req != mpt->els_cmd_ptrs[i],
1141		    ("%s(%d): req %p:%u func %x in els ptrs at ioindex %d\n",
1142		    s, line, req, req->serno,
1143		    ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function, i));
1144	}
1145	for (i = 0; i < mpt->tgt_cmds_allocated; i++) {
1146		KASSERT(req != mpt->tgt_cmd_ptrs[i],
1147		    ("%s(%d): req %p:%u func %x in tgt ptrs at ioindex %d\n",
1148		    s, line, req, req->serno,
1149		    ((PTR_MSG_REQUEST_HEADER)req->req_vbuf)->Function, i));
1150	}
1151}
1152#endif
1153
1154/*
1155 * Task Management Types, purely for internal consumption
1156 */
1157typedef enum {
1158	MPT_ABORT_TASK_SET=1234,
1159	MPT_CLEAR_TASK_SET,
1160	MPT_TARGET_RESET,
1161	MPT_CLEAR_ACA,
1162	MPT_TERMINATE_TASK,
1163	MPT_NIL_TMT_VALUE=5678
1164} mpt_task_mgmt_t;
1165
1166/**************************** Unclassified Routines ***************************/
1167void		mpt_send_cmd(struct mpt_softc *mpt, request_t *req);
1168int		mpt_recv_handshake_reply(struct mpt_softc *mpt,
1169					 size_t reply_len, void *reply);
1170int		mpt_wait_req(struct mpt_softc *mpt, request_t *req,
1171			     mpt_req_state_t state, mpt_req_state_t mask,
1172			     int sleep_ok, int time_ms);
1173void		mpt_enable_ints(struct mpt_softc *mpt);
1174void		mpt_disable_ints(struct mpt_softc *mpt);
1175int		mpt_attach(struct mpt_softc *mpt);
1176int		mpt_shutdown(struct mpt_softc *mpt);
1177int		mpt_detach(struct mpt_softc *mpt);
1178int		mpt_send_handshake_cmd(struct mpt_softc *mpt,
1179				       size_t len, void *cmd);
1180request_t *	mpt_get_request(struct mpt_softc *mpt, int sleep_ok);
1181void		mpt_free_request(struct mpt_softc *mpt, request_t *req);
1182void		mpt_intr(void *arg);
1183void		mpt_check_doorbell(struct mpt_softc *mpt);
1184void		mpt_dump_reply_frame(struct mpt_softc *mpt,
1185				     MSG_DEFAULT_REPLY *reply_frame);
1186
1187void		mpt_set_config_regs(struct mpt_softc *);
1188int		mpt_issue_cfg_req(struct mpt_softc */*mpt*/, request_t */*req*/,
1189				  u_int /*Action*/, u_int /*PageVersion*/,
1190				  u_int /*PageLength*/, u_int /*PageNumber*/,
1191				  u_int /*PageType*/, uint32_t /*PageAddress*/,
1192				  bus_addr_t /*addr*/, bus_size_t/*len*/,
1193				  int /*sleep_ok*/, int /*timeout_ms*/);
1194int		mpt_read_cfg_header(struct mpt_softc *, int /*PageType*/,
1195				    int /*PageNumber*/,
1196				    uint32_t /*PageAddress*/,
1197				    CONFIG_PAGE_HEADER *,
1198				    int /*sleep_ok*/, int /*timeout_ms*/);
1199int		mpt_read_cfg_page(struct mpt_softc *t, int /*Action*/,
1200				  uint32_t /*PageAddress*/,
1201				  CONFIG_PAGE_HEADER *, size_t /*len*/,
1202				  int /*sleep_ok*/, int /*timeout_ms*/);
1203int		mpt_write_cfg_page(struct mpt_softc *, int /*Action*/,
1204				   uint32_t /*PageAddress*/,
1205				   CONFIG_PAGE_HEADER *, size_t /*len*/,
1206				   int /*sleep_ok*/, int /*timeout_ms*/);
1207static __inline int
1208mpt_read_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress,
1209		      CONFIG_PAGE_HEADER *hdr, size_t len,
1210		      int sleep_ok, int timeout_ms)
1211{
1212	return (mpt_read_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_READ_CURRENT,
1213				  PageAddress, hdr, len, sleep_ok, timeout_ms));
1214}
1215
1216static __inline int
1217mpt_write_cur_cfg_page(struct mpt_softc *mpt, uint32_t PageAddress,
1218		       CONFIG_PAGE_HEADER *hdr, size_t len, int sleep_ok,
1219		       int timeout_ms)
1220{
1221	return (mpt_write_cfg_page(mpt, MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT,
1222				   PageAddress, hdr, len, sleep_ok,
1223				   timeout_ms));
1224}
1225/* mpt_debug.c functions */
1226void mpt_print_reply(void *vmsg);
1227void mpt_print_db(uint32_t mb);
1228void mpt_print_config_reply(void *vmsg);
1229char *mpt_ioc_diag(uint32_t diag);
1230void mpt_req_state(mpt_req_state_t state);
1231void mpt_print_config_request(void *vmsg);
1232void mpt_print_request(void *vmsg);
1233void mpt_print_scsi_io_request(MSG_SCSI_IO_REQUEST *msg);
1234void mpt_dump_sgl(SGE_IO_UNION *se, int offset);
1235#endif /* _MPT_H_ */
1236