1/* $NetBSD: mpii.c,v 1.1 2012/04/19 17:50:51 bouyer Exp $ */
2/*	OpenBSD: mpii.c,v 1.51 2012/04/11 13:29:14 naddy Exp 	*/
3/*
4 * Copyright (c) 2010 Mike Belopuhov <mkb@crypt.org.ru>
5 * Copyright (c) 2009 James Giannoules
6 * Copyright (c) 2005 - 2010 David Gwynne <dlg@openbsd.org>
7 * Copyright (c) 2005 - 2010 Marco Peereboom <marco@openbsd.org>
8 *
9 * Permission to use, copy, modify, and distribute this software for any
10 * purpose with or without fee is hereby granted, provided that the above
11 * copyright notice and this permission notice appear in all copies.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
19 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20 */
21
22#include <sys/cdefs.h>
23__KERNEL_RCSID(0, "$NetBSD: mpii.c,v 1.1 2012/04/19 17:50:51 bouyer Exp $");
24
25#include "bio.h"
26
27#include <sys/param.h>
28#include <sys/systm.h>
29#include <sys/buf.h>
30#include <sys/device.h>
31#include <sys/ioctl.h>
32#include <sys/malloc.h>
33#include <sys/kernel.h>
34#include <sys/mutex.h>
35#include <sys/condvar.h>
36#include <sys/dkio.h>
37#include <sys/tree.h>
38
39#include <dev/pci/pcireg.h>
40#include <dev/pci/pcivar.h>
41#include <dev/pci/pcidevs.h>
42
43#include <dev/scsipi/scsipi_all.h>
44#include <dev/scsipi/scsi_all.h>
45#include <dev/scsipi/scsiconf.h>
46
47#include <dev/biovar.h>
48#include <dev/sysmon/sysmonvar.h>
49#include <sys/envsys.h>
50
51#define MPII_DOORBELL			(0x00)
52/* doorbell read bits */
53#define MPII_DOORBELL_STATE		(0xf<<28) /* ioc state */
54#define  MPII_DOORBELL_STATE_RESET	(0x0<<28)
55#define  MPII_DOORBELL_STATE_READY	(0x1<<28)
56#define  MPII_DOORBELL_STATE_OPER	(0x2<<28)
57#define  MPII_DOORBELL_STATE_FAULT	(0x4<<28)
58#define  MPII_DOORBELL_INUSE		(0x1<<27) /* doorbell used */
59#define MPII_DOORBELL_WHOINIT		(0x7<<24) /* last to reset ioc */
60#define  MPII_DOORBELL_WHOINIT_NOONE	(0x0<<24) /* not initialized */
61#define  MPII_DOORBELL_WHOINIT_SYSBIOS	(0x1<<24) /* system bios */
62#define  MPII_DOORBELL_WHOINIT_ROMBIOS	(0x2<<24) /* rom bios */
63#define  MPII_DOORBELL_WHOINIT_PCIPEER	(0x3<<24) /* pci peer */
64#define  MPII_DOORBELL_WHOINIT_DRIVER	(0x4<<24) /* host driver */
65#define  MPII_DOORBELL_WHOINIT_MANUFACT	(0x5<<24) /* manufacturing */
66#define MPII_DOORBELL_FAULT		(0xffff<<0) /* fault code */
67/* doorbell write bits */
68#define MPII_DOORBELL_FUNCTION_SHIFT	(24)
69#define MPII_DOORBELL_FUNCTION_MASK	(0xff << MPII_DOORBELL_FUNCTION_SHIFT)
70#define MPII_DOORBELL_FUNCTION(x)	\
71    (((x) << MPII_DOORBELL_FUNCTION_SHIFT) & MPII_DOORBELL_FUNCTION_MASK)
72#define MPII_DOORBELL_DWORDS_SHIFT	16
73#define MPII_DOORBELL_DWORDS_MASK	(0xff << MPII_DOORBELL_DWORDS_SHIFT)
74#define MPII_DOORBELL_DWORDS(x)		\
75    (((x) << MPII_DOORBELL_DWORDS_SHIFT) & MPII_DOORBELL_DWORDS_MASK)
76#define MPII_DOORBELL_DATA_MASK		(0xffff)
77
78#define MPII_WRITESEQ			(0x04)
79#define  MPII_WRITESEQ_KEY_VALUE_MASK	(0x0000000f) /* key value */
80#define  MPII_WRITESEQ_FLUSH		(0x00)
81#define  MPII_WRITESEQ_1		(0x0f)
82#define  MPII_WRITESEQ_2		(0x04)
83#define  MPII_WRITESEQ_3		(0x0b)
84#define  MPII_WRITESEQ_4		(0x02)
85#define  MPII_WRITESEQ_5		(0x07)
86#define  MPII_WRITESEQ_6		(0x0d)
87
88#define MPII_HOSTDIAG			(0x08)
89#define  MPII_HOSTDIAG_BDS_MASK		(0x00001800) /* boot device select */
90#define   MPII_HOSTDIAG_BDS_DEFAULT 	(0<<11)	/* default address map, flash */
91#define   MPII_HOSTDIAG_BDS_HCDW	(1<<11)	/* host code and data window */
92#define  MPII_HOSTDIAG_CLEARFBS		(1<<10) /* clear flash bad sig */
93#define  MPII_HOSTDIAG_FORCE_HCB_ONBOOT (1<<9)	/* force host controlled boot */
94#define  MPII_HOSTDIAG_HCB_MODE		(1<<8)	/* host controlled boot mode */
95#define  MPII_HOSTDIAG_DWRE		(1<<7) 	/* diag reg write enabled */
96#define  MPII_HOSTDIAG_FBS		(1<<6) 	/* flash bad sig */
97#define  MPII_HOSTDIAG_RESET_HIST	(1<<5) 	/* reset history */
98#define  MPII_HOSTDIAG_DIAGWR_EN	(1<<4) 	/* diagnostic write enabled */
99#define  MPII_HOSTDIAG_RESET_ADAPTER	(1<<2) 	/* reset adapter */
100#define  MPII_HOSTDIAG_HOLD_IOC_RESET	(1<<1) 	/* hold ioc in reset */
101#define  MPII_HOSTDIAG_DIAGMEM_EN	(1<<0) 	/* diag mem enable */
102
103#define MPII_DIAGRWDATA			(0x10)
104
105#define MPII_DIAGRWADDRLOW		(0x14)
106
107#define MPII_DIAGRWADDRHIGH		(0x18)
108
109#define MPII_INTR_STATUS		(0x30)
110#define  MPII_INTR_STATUS_SYS2IOCDB	(1<<31) /* ioc written to by host */
111#define  MPII_INTR_STATUS_RESET		(1<<30) /* physical ioc reset */
112#define  MPII_INTR_STATUS_REPLY		(1<<3)	/* reply message interrupt */
113#define  MPII_INTR_STATUS_IOC2SYSDB	(1<<0) 	/* ioc write to doorbell */
114
115#define MPII_INTR_MASK			(0x34)
116#define  MPII_INTR_MASK_RESET		(1<<30) /* ioc reset intr mask */
117#define  MPII_INTR_MASK_REPLY		(1<<3) 	/* reply message intr mask */
118#define  MPII_INTR_MASK_DOORBELL	(1<<0) 	/* doorbell interrupt mask */
119
120#define MPII_DCR_DATA			(0x38)
121
122#define MPII_DCR_ADDRESS		(0x3c)
123
124#define MPII_REPLY_FREE_HOST_INDEX	(0x48)
125
126#define MPII_REPLY_POST_HOST_INDEX	(0x6c)
127
128#define MPII_HCB_SIZE			(0x74)
129
130#define MPII_HCB_ADDRESS_LOW		(0x78)
131#define MPII_HCB_ADDRESS_HIGH		(0x7c)
132
133#define MPII_REQ_DESCR_POST_LOW		(0xc0)
134#define MPII_REQ_DESCR_POST_HIGH	(0xc4)
135
136/*
137 * Scatter Gather Lists
138 */
139
140#define MPII_SGE_FL_LAST		(0x1<<31) /* last element in segment */
141#define MPII_SGE_FL_EOB			(0x1<<30) /* last element of buffer */
142#define MPII_SGE_FL_TYPE		(0x3<<28) /* element type */
143 #define MPII_SGE_FL_TYPE_SIMPLE	(0x1<<28) /* simple element */
144 #define MPII_SGE_FL_TYPE_CHAIN		(0x3<<28) /* chain element */
145 #define MPII_SGE_FL_TYPE_XACTCTX	(0x0<<28) /* transaction context */
146#define MPII_SGE_FL_LOCAL		(0x1<<27) /* local address */
147#define MPII_SGE_FL_DIR			(0x1<<26) /* direction */
148 #define MPII_SGE_FL_DIR_OUT		(0x1<<26)
149 #define MPII_SGE_FL_DIR_IN		(0x0<<26)
150#define MPII_SGE_FL_SIZE		(0x1<<25) /* address size */
151 #define MPII_SGE_FL_SIZE_32		(0x0<<25)
152 #define MPII_SGE_FL_SIZE_64		(0x1<<25)
153#define MPII_SGE_FL_EOL			(0x1<<24) /* end of list */
154
155struct mpii_sge {
156	u_int32_t		sg_hdr;
157	u_int32_t		sg_lo_addr;
158	u_int32_t		sg_hi_addr;
159} __packed;
160
161struct mpii_fw_tce {
162	u_int8_t		reserved1;
163	u_int8_t		context_size;
164	u_int8_t		details_length;
165	u_int8_t		flags;
166
167	u_int32_t		reserved2;
168
169	u_int32_t		image_offset;
170
171	u_int32_t		image_size;
172} __packed;
173
174/*
175 * Messages
176 */
177
178/* functions */
179#define MPII_FUNCTION_SCSI_IO_REQUEST			(0x00)
180#define MPII_FUNCTION_SCSI_TASK_MGMT			(0x01)
181#define MPII_FUNCTION_IOC_INIT				(0x02)
182#define MPII_FUNCTION_IOC_FACTS				(0x03)
183#define MPII_FUNCTION_CONFIG				(0x04)
184#define MPII_FUNCTION_PORT_FACTS			(0x05)
185#define MPII_FUNCTION_PORT_ENABLE			(0x06)
186#define MPII_FUNCTION_EVENT_NOTIFICATION		(0x07)
187#define MPII_FUNCTION_EVENT_ACK				(0x08)
188#define MPII_FUNCTION_FW_DOWNLOAD			(0x09)
189#define MPII_FUNCTION_TARGET_CMD_BUFFER_POST		(0x0a)
190#define MPII_FUNCTION_TARGET_ASSIST			(0x0b)
191#define MPII_FUNCTION_TARGET_STATUS_SEND		(0x0c)
192#define MPII_FUNCTION_TARGET_MODE_ABORT			(0x0d)
193#define MPII_FUNCTION_FW_UPLOAD				(0x12)
194
195#define MPII_FUNCTION_RAID_ACTION			(0x15)
196#define MPII_FUNCTION_RAID_SCSI_IO_PASSTHROUGH		(0x16)
197
198#define MPII_FUNCTION_TOOLBOX				(0x17)
199
200#define MPII_FUNCTION_SCSI_ENCLOSURE_PROCESSOR		(0x18)
201
202#define MPII_FUNCTION_SMP_PASSTHROUGH			(0x1a)
203#define MPII_FUNCTION_SAS_IO_UNIT_CONTROL		(0x1b)
204#define MPII_FUNCTION_SATA_PASSTHROUGH			(0x1c)
205
206#define MPII_FUNCTION_DIAG_BUFFER_POST			(0x1d)
207#define MPII_FUNCTION_DIAG_RELEASE			(0x1e)
208
209#define MPII_FUNCTION_TARGET_CMD_BUF_BASE_POST		(0x24)
210#define MPII_FUNCTION_TARGET_CMD_BUF_LIST_POST		(0x25)
211
212#define MPII_FUNCTION_IOC_MESSAGE_UNIT_RESET		(0x40)
213#define MPII_FUNCTION_IO_UNIT_RESET			(0x41)
214#define MPII_FUNCTION_HANDSHAKE				(0x42)
215
216/* Common IOCStatus values for all replies */
217#define MPII_IOCSTATUS_MASK				(0x7fff)
218#define  MPII_IOCSTATUS_SUCCESS				(0x0000)
219#define  MPII_IOCSTATUS_INVALID_FUNCTION		(0x0001)
220#define  MPII_IOCSTATUS_BUSY				(0x0002)
221#define  MPII_IOCSTATUS_INVALID_SGL			(0x0003)
222#define  MPII_IOCSTATUS_INTERNAL_ERROR			(0x0004)
223#define  MPII_IOCSTATUS_INVALID_VPID			(0x0005)
224#define  MPII_IOCSTATUS_INSUFFICIENT_RESOURCES		(0x0006)
225#define  MPII_IOCSTATUS_INVALID_FIELD			(0x0007)
226#define  MPII_IOCSTATUS_INVALID_STATE			(0x0008)
227#define  MPII_IOCSTATUS_OP_STATE_NOT_SUPPORTED		(0x0009)
228/* Config IOCStatus values */
229#define  MPII_IOCSTATUS_CONFIG_INVALID_ACTION		(0x0020)
230#define  MPII_IOCSTATUS_CONFIG_INVALID_TYPE		(0x0021)
231#define  MPII_IOCSTATUS_CONFIG_INVALID_PAGE		(0x0022)
232#define  MPII_IOCSTATUS_CONFIG_INVALID_DATA		(0x0023)
233#define  MPII_IOCSTATUS_CONFIG_NO_DEFAULTS		(0x0024)
234#define  MPII_IOCSTATUS_CONFIG_CANT_COMMIT		(0x0025)
235/* SCSIIO Reply initiator values */
236#define  MPII_IOCSTATUS_SCSI_RECOVERED_ERROR		(0x0040)
237#define  MPII_IOCSTATUS_SCSI_INVALID_DEVHANDLE		(0x0042)
238#define  MPII_IOCSTATUS_SCSI_DEVICE_NOT_THERE		(0x0043)
239#define  MPII_IOCSTATUS_SCSI_DATA_OVERRUN		(0x0044)
240#define  MPII_IOCSTATUS_SCSI_DATA_UNDERRUN		(0x0045)
241#define  MPII_IOCSTATUS_SCSI_IO_DATA_ERROR		(0x0046)
242#define  MPII_IOCSTATUS_SCSI_PROTOCOL_ERROR		(0x0047)
243#define  MPII_IOCSTATUS_SCSI_TASK_TERMINATED		(0x0048)
244#define  MPII_IOCSTATUS_SCSI_RESIDUAL_MISMATCH		(0x0049)
245#define  MPII_IOCSTATUS_SCSI_TASK_MGMT_FAILED		(0x004a)
246#define  MPII_IOCSTATUS_SCSI_IOC_TERMINATED		(0x004b)
247#define  MPII_IOCSTATUS_SCSI_EXT_TERMINATED		(0x004c)
248/* For use by SCSI Initiator and SCSI Target end-to-end data protection */
249#define  MPII_IOCSTATUS_EEDP_GUARD_ERROR		(0x004d)
250#define  MPII_IOCSTATUS_EEDP_REF_TAG_ERROR		(0x004e)
251#define  MPII_IOCSTATUS_EEDP_APP_TAG_ERROR		(0x004f)
252/* SCSI (SPI & FCP) target values */
253#define  MPII_IOCSTATUS_TARGET_INVALID_IO_INDEX		(0x0062)
254#define  MPII_IOCSTATUS_TARGET_ABORTED			(0x0063)
255#define  MPII_IOCSTATUS_TARGET_NO_CONN_RETRYABLE	(0x0064)
256#define  MPII_IOCSTATUS_TARGET_NO_CONNECTION		(0x0065)
257#define  MPII_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH	(0x006a)
258#define  MPII_IOCSTATUS_TARGET_DATA_OFFSET_ERROR	(0x006d)
259#define  MPII_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA	(0x006e)
260#define  MPII_IOCSTATUS_TARGET_IU_TOO_SHORT		(0x006f)
261#define  MPII_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT		(0x0070)
262#define  MPII_IOCSTATUS_TARGET_NAK_RECEIVED		(0x0071)
263/* Serial Attached SCSI values */
264#define  MPII_IOCSTATUS_SAS_SMP_REQUEST_FAILED		(0x0090)
265#define  MPII_IOCSTATUS_SAS_SMP_DATA_OVERRUN		(0x0091)
266/* Diagnostic Tools values */
267#define  MPII_IOCSTATUS_DIAGNOSTIC_RELEASED		(0x00a0)
268
269#define MPII_REP_IOCLOGINFO_TYPE			(0xf<<28)
270#define MPII_REP_IOCLOGINFO_TYPE_NONE			(0x0<<28)
271#define MPII_REP_IOCLOGINFO_TYPE_SCSI			(0x1<<28)
272#define MPII_REP_IOCLOGINFO_TYPE_FC			(0x2<<28)
273#define MPII_REP_IOCLOGINFO_TYPE_SAS			(0x3<<28)
274#define MPII_REP_IOCLOGINFO_TYPE_ISCSI			(0x4<<28)
275#define MPII_REP_IOCLOGINFO_DATA			(0x0fffffff)
276
277/* event notification types */
278#define MPII_EVENT_NONE					(0x00)
279#define MPII_EVENT_LOG_DATA				(0x01)
280#define MPII_EVENT_STATE_CHANGE				(0x02)
281#define MPII_EVENT_HARD_RESET_RECEIVED			(0x05)
282#define MPII_EVENT_EVENT_CHANGE				(0x0a)
283#define MPII_EVENT_TASK_SET_FULL			(0x0e)
284#define MPII_EVENT_SAS_DEVICE_STATUS_CHANGE		(0x0f)
285#define MPII_EVENT_IR_OPERATION_STATUS			(0x14)
286#define MPII_EVENT_SAS_DISCOVERY			(0x16)
287#define MPII_EVENT_SAS_BROADCAST_PRIMITIVE		(0x17)
288#define MPII_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE	(0x18)
289#define MPII_EVENT_SAS_INIT_TABLE_OVERFLOW		(0x19)
290#define MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST		(0x1c)
291#define MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE	(0x1d)
292#define MPII_EVENT_IR_VOLUME				(0x1e)
293#define MPII_EVENT_IR_PHYSICAL_DISK			(0x1f)
294#define MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST		(0x20)
295#define MPII_EVENT_LOG_ENTRY_ADDED			(0x21)
296
297/* messages */
298
299#define MPII_WHOINIT_NOONE				(0x00)
300#define MPII_WHOINIT_SYSTEM_BIOS			(0x01)
301#define MPII_WHOINIT_ROM_BIOS				(0x02)
302#define MPII_WHOINIT_PCI_PEER				(0x03)
303#define MPII_WHOINIT_HOST_DRIVER			(0x04)
304#define MPII_WHOINIT_MANUFACTURER			(0x05)
305
306/* default messages */
307
308struct mpii_msg_request {
309	u_int8_t		reserved1;
310	u_int8_t		reserved2;
311	u_int8_t		chain_offset;
312	u_int8_t		function;
313
314	u_int8_t		reserved3;
315	u_int8_t		reserved4;
316	u_int8_t		reserved5;
317	u_int8_t		msg_flags;
318
319	u_int8_t		vp_id;
320	u_int8_t		vf_id;
321	u_int16_t		reserved6;
322} __packed;
323
324struct mpii_msg_reply {
325	u_int16_t		reserved1;
326	u_int8_t		msg_length;
327	u_int8_t		function;
328
329	u_int16_t		reserved2;
330	u_int8_t		reserved3;
331	u_int8_t		msg_flags;
332
333	u_int8_t		vp_id;
334	u_int8_t		vf_if;
335	u_int16_t		reserved4;
336
337	u_int16_t		reserved5;
338	u_int16_t		ioc_status;
339
340	u_int32_t		ioc_loginfo;
341} __packed;
342
343/* ioc init */
344
345struct mpii_msg_iocinit_request {
346	u_int8_t		whoinit;
347	u_int8_t		reserved1;
348	u_int8_t		chain_offset;
349	u_int8_t		function;
350
351	u_int16_t		reserved2;
352	u_int8_t		reserved3;
353	u_int8_t		msg_flags;
354
355	u_int8_t		vp_id;
356	u_int8_t		vf_id;
357	u_int16_t		reserved4;
358
359	u_int8_t		msg_version_min;
360	u_int8_t		msg_version_maj;
361	u_int8_t		hdr_version_unit;
362	u_int8_t		hdr_version_dev;
363
364	u_int32_t		reserved5;
365
366	u_int32_t		reserved6;
367
368	u_int16_t		reserved7;
369	u_int16_t		system_request_frame_size;
370
371	u_int16_t		reply_descriptor_post_queue_depth;
372	u_int16_t		reply_free_queue_depth;
373
374	u_int32_t		sense_buffer_address_high;
375
376	u_int32_t		system_reply_address_high;
377
378	u_int64_t		system_request_frame_base_address;
379
380	u_int64_t		reply_descriptor_post_queue_address;
381
382	u_int64_t		reply_free_queue_address;
383
384	u_int64_t		timestamp;
385} __packed;
386
387struct mpii_msg_iocinit_reply {
388	u_int8_t		whoinit;
389	u_int8_t		reserved1;
390	u_int8_t		msg_length;
391	u_int8_t		function;
392
393	u_int16_t		reserved2;
394	u_int8_t		reserved3;
395	u_int8_t		msg_flags;
396
397	u_int8_t		vp_id;
398	u_int8_t		vf_id;
399	u_int16_t		reserved4;
400
401	u_int16_t		reserved5;
402	u_int16_t		ioc_status;
403
404	u_int32_t		ioc_loginfo;
405} __packed;
406
407struct mpii_msg_iocfacts_request {
408	u_int16_t		reserved1;
409	u_int8_t		chain_offset;
410	u_int8_t		function;
411
412	u_int16_t		reserved2;
413	u_int8_t		reserved3;
414	u_int8_t		msg_flags;
415
416	u_int8_t		vp_id;
417	u_int8_t		vf_id;
418	u_int16_t		reserved4;
419} __packed;
420
421struct mpii_msg_iocfacts_reply {
422	u_int8_t		msg_version_min;
423	u_int8_t		msg_version_maj;
424	u_int8_t		msg_length;
425	u_int8_t		function;
426
427	u_int8_t		header_version_dev;
428	u_int8_t		header_version_unit;
429	u_int8_t		ioc_number;
430	u_int8_t		msg_flags;
431
432	u_int8_t		vp_id;
433	u_int8_t		vf_id;
434	u_int16_t		reserved1;
435
436	u_int16_t		ioc_exceptions;
437#define MPII_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL	(1<<0)
438#define MPII_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID	(1<<1)
439#define MPII_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL		(1<<2)
440#define MPII_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL	(1<<3)
441#define MPII_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED	(1<<4)
442#define MPII_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAC	(1<<8)
443	/* XXX JPG BOOT_STATUS in bits[7:5] */
444	/* XXX JPG all these #defines need to be fixed up */
445	u_int16_t		ioc_status;
446
447	u_int32_t		ioc_loginfo;
448
449	u_int8_t		max_chain_depth;
450	u_int8_t		whoinit;
451	u_int8_t		number_of_ports;
452	u_int8_t		reserved2;
453
454	u_int16_t		request_credit;
455	u_int16_t		product_id;
456
457	u_int32_t		ioc_capabilities;
458#define MPII_IOCFACTS_CAPABILITY_EVENT_REPLAY           (1<<13)
459#define MPII_IOCFACTS_CAPABILITY_INTEGRATED_RAID        (1<<12)
460#define MPII_IOCFACTS_CAPABILITY_TLR                    (1<<11)
461#define MPII_IOCFACTS_CAPABILITY_MULTICAST              (1<<8)
462#define MPII_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET   (1<<7)
463#define MPII_IOCFACTS_CAPABILITY_EEDP                   (1<<6)
464#define MPII_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER        (1<<4)
465#define MPII_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER      (1<<3)
466#define MPII_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (1<<2)
467
468	u_int8_t		fw_version_dev;
469	u_int8_t		fw_version_unit;
470	u_int8_t		fw_version_min;
471	u_int8_t		fw_version_maj;
472
473	u_int16_t		ioc_request_frame_size;
474	u_int16_t		reserved3;
475
476	u_int16_t		max_initiators;
477	u_int16_t		max_targets;
478
479	u_int16_t		max_sas_expanders;
480	u_int16_t		max_enclosures;
481
482	u_int16_t		protocol_flags;
483	u_int16_t		high_priority_credit;
484
485	u_int16_t		max_reply_descriptor_post_queue_depth;
486	u_int8_t		reply_frame_size;
487	u_int8_t		max_volumes;
488
489	u_int16_t		max_dev_handle;
490	u_int16_t		max_persistent_entries;
491
492	u_int32_t		reserved4;
493} __packed;
494
495struct mpii_msg_portfacts_request {
496	u_int16_t		reserved1;
497	u_int8_t		chain_offset;
498	u_int8_t		function;
499
500	u_int16_t		reserved2;
501	u_int8_t		port_number;
502	u_int8_t		msg_flags;
503
504	u_int8_t		vp_id;
505	u_int8_t		vf_id;
506	u_int16_t		reserved3;
507} __packed;
508
509struct mpii_msg_portfacts_reply {
510	u_int16_t		reserved1;
511	u_int8_t		msg_length;
512	u_int8_t		function;
513
514	u_int16_t		reserved2;
515	u_int8_t		port_number;
516	u_int8_t		msg_flags;
517
518	u_int8_t		vp_id;
519	u_int8_t		vf_id;
520	u_int16_t		reserved3;
521
522	u_int16_t		reserved4;
523	u_int16_t		ioc_status;
524
525	u_int32_t		ioc_loginfo;
526
527	u_int8_t		reserved5;
528	u_int8_t		port_type;
529#define MPII_PORTFACTS_PORTTYPE_INACTIVE		(0x00)
530#define MPII_PORTFACTS_PORTTYPE_FC			(0x10)
531#define MPII_PORTFACTS_PORTTYPE_ISCSI			(0x20)
532#define MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL		(0x30)
533#define MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL		(0x31)
534	u_int16_t		reserved6;
535
536	u_int16_t		max_posted_cmd_buffers;
537	u_int16_t		reserved7;
538} __packed;
539
540struct mpii_msg_portenable_request {
541	u_int16_t		reserved1;
542	u_int8_t		chain_offset;
543	u_int8_t		function;
544
545	u_int8_t		reserved2;
546	u_int8_t		port_flags;
547	u_int8_t		reserved3;
548	u_int8_t		msg_flags;
549
550	u_int8_t		vp_id;
551	u_int8_t		vf_id;
552	u_int16_t		reserved4;
553} __packed;
554
555struct mpii_msg_portenable_reply {
556	u_int16_t		reserved1;
557	u_int8_t		msg_length;
558	u_int8_t		function;
559
560	u_int8_t		reserved2;
561	u_int8_t		port_flags;
562	u_int8_t		reserved3;
563	u_int8_t		msg_flags;
564
565	u_int8_t		vp_id;
566	u_int8_t		vf_id;
567	u_int16_t		reserved4;
568
569	u_int16_t		reserved5;
570	u_int16_t		ioc_status;
571
572	u_int32_t		ioc_loginfo;
573} __packed;
574
575struct mpii_msg_event_request {
576	u_int16_t		reserved1;
577	u_int8_t		chain_offset;
578	u_int8_t		function;
579
580	u_int16_t		reserved2;
581	u_int8_t		reserved3;
582	u_int8_t		msg_flags;
583
584	u_int8_t		vp_id;
585	u_int8_t		vf_id;
586	u_int16_t		reserved4;
587
588	u_int32_t		reserved5;
589
590	u_int32_t		reserved6;
591
592	u_int32_t		event_masks[4];
593
594	u_int16_t		sas_broadcase_primitive_masks;
595	u_int16_t		reserved7;
596
597	u_int32_t		reserved8;
598} __packed;
599
600struct mpii_msg_event_reply {
601	u_int16_t		event_data_length;
602	u_int8_t		msg_length;
603	u_int8_t		function;
604
605	u_int16_t		reserved1;
606	u_int8_t		ack_required;
607#define MPII_EVENT_ACK_REQUIRED				(0x01)
608	u_int8_t		msg_flags;
609#define MPII_EVENT_FLAGS_REPLY_KEPT			(1<<7)
610
611	u_int8_t		vp_id;
612	u_int8_t		vf_id;
613	u_int16_t		reserved2;
614
615	u_int16_t		reserved3;
616	u_int16_t		ioc_status;
617
618	u_int32_t		ioc_loginfo;
619
620	u_int16_t		event;
621	u_int16_t		reserved4;
622
623	u_int32_t		event_context;
624
625	/* event data follows */
626} __packed;
627
628struct mpii_msg_eventack_request {
629	u_int16_t		reserved1;
630	u_int8_t		chain_offset;
631	u_int8_t		function;
632
633	u_int8_t		reserved2[3];
634	u_int8_t		msg_flags;
635
636	u_int8_t		vp_id;
637	u_int8_t		vf_id;
638	u_int16_t		reserved3;
639
640	u_int16_t		event;
641	u_int16_t		reserved4;
642
643	u_int32_t		event_context;
644} __packed;
645
646struct mpii_msg_eventack_reply {
647	u_int16_t		reserved1;
648	u_int8_t		msg_length;
649	u_int8_t		function;
650
651	u_int8_t		reserved2[3];
652	u_int8_t		msg_flags;
653
654	u_int8_t		vp_id;
655	u_int8_t		vf_id;
656	u_int16_t		reserved3;
657
658	u_int16_t		reserved4;
659	u_int16_t		ioc_status;
660
661	u_int32_t		ioc_loginfo;
662} __packed;
663
664struct mpii_msg_fwupload_request {
665	u_int8_t		image_type;
666#define MPII_FWUPLOAD_IMAGETYPE_IOC_FW			(0x00)
667#define MPII_FWUPLOAD_IMAGETYPE_NV_FW			(0x01)
668#define MPII_FWUPLOAD_IMAGETYPE_NV_BACKUP		(0x05)
669#define MPII_FWUPLOAD_IMAGETYPE_NV_MANUFACTURING	(0x06)
670#define MPII_FWUPLOAD_IMAGETYPE_NV_CONFIG_1		(0x07)
671#define MPII_FWUPLOAD_IMAGETYPE_NV_CONFIG_2		(0x08)
672#define MPII_FWUPLOAD_IMAGETYPE_NV_MEGARAID		(0x09)
673#define MPII_FWUPLOAD_IMAGETYPE_NV_COMPLETE		(0x0a)
674#define MPII_FWUPLOAD_IMAGETYPE_COMMON_BOOT_BLOCK	(0x0b)
675	u_int8_t		reserved1;
676	u_int8_t		chain_offset;
677	u_int8_t		function;
678
679	u_int8_t		reserved2[3];
680	u_int8_t		msg_flags;
681
682	u_int8_t		vp_id;
683	u_int8_t		vf_id;
684	u_int16_t		reserved3;
685
686	u_int32_t		reserved4;
687
688	u_int32_t		reserved5;
689
690	struct mpii_fw_tce	tce;
691
692	/* followed by an sgl */
693} __packed;
694
695struct mpii_msg_fwupload_reply {
696	u_int8_t		image_type;
697	u_int8_t		reserved1;
698	u_int8_t		msg_length;
699	u_int8_t		function;
700
701	u_int8_t		reserved2[3];
702	u_int8_t		msg_flags;
703
704	u_int8_t		vp_id;
705	u_int8_t		vf_id;
706	u_int16_t		reserved3;
707
708	u_int16_t		reserved4;
709	u_int16_t		ioc_status;
710
711	u_int32_t		ioc_loginfo;
712
713	u_int32_t		actual_image_size;
714} __packed;
715
716struct mpii_msg_scsi_io {
717	u_int16_t		dev_handle;
718	u_int8_t		chain_offset;
719	u_int8_t		function;
720
721	u_int16_t		reserved1;
722	u_int8_t		reserved2;
723	u_int8_t		msg_flags;
724
725	u_int8_t		vp_id;
726	u_int8_t		vf_id;
727	u_int16_t		reserved3;
728
729	u_int32_t		sense_buffer_low_address;
730
731	u_int16_t		sgl_flags;
732	u_int8_t		sense_buffer_length;
733	u_int8_t		reserved4;
734
735	u_int8_t		sgl_offset0;
736	u_int8_t		sgl_offset1;
737	u_int8_t		sgl_offset2;
738	u_int8_t		sgl_offset3;
739
740	u_int32_t		skip_count;
741
742	u_int32_t		data_length;
743
744	u_int32_t		bidirectional_data_length;
745
746	u_int16_t		io_flags;
747	u_int16_t		eedp_flags;
748
749	u_int32_t		eedp_block_size;
750
751	u_int32_t		secondary_reference_tag;
752
753	u_int16_t		secondary_application_tag;
754	u_int16_t		application_tag_translation_mask;
755
756	u_int16_t		lun[4];
757
758/* the following 16 bits are defined in MPI2 as the control field */
759	u_int8_t		reserved5;
760	u_int8_t		tagging;
761#define MPII_SCSIIO_ATTR_SIMPLE_Q			(0x0)
762#define MPII_SCSIIO_ATTR_HEAD_OF_Q			(0x1)
763#define MPII_SCSIIO_ATTR_ORDERED_Q			(0x2)
764#define MPII_SCSIIO_ATTR_ACA_Q				(0x4)
765#define MPII_SCSIIO_ATTR_UNTAGGED			(0x5)
766#define MPII_SCSIIO_ATTR_NO_DISCONNECT			(0x7)
767	u_int8_t		reserved6;
768	u_int8_t		direction;
769#define MPII_SCSIIO_DIR_NONE				(0x0)
770#define MPII_SCSIIO_DIR_WRITE				(0x1)
771#define MPII_SCSIIO_DIR_READ				(0x2)
772
773#define	MPII_CDB_LEN					(32)
774	u_int8_t		cdb[MPII_CDB_LEN];
775
776	/* followed by an sgl */
777} __packed;
778
779struct mpii_msg_scsi_io_error {
780	u_int16_t		dev_handle;
781	u_int8_t		msg_length;
782	u_int8_t		function;
783
784	u_int16_t		reserved1;
785	u_int8_t		reserved2;
786	u_int8_t		msg_flags;
787
788	u_int8_t		vp_id;
789	u_int8_t		vf_id;
790	u_int16_t		reserved3;
791
792	u_int8_t		scsi_status;
793	/* XXX JPG validate this */
794#if notyet
795#define MPII_SCSIIO_ERR_STATUS_SUCCESS
796#define MPII_SCSIIO_ERR_STATUS_CHECK_COND
797#define MPII_SCSIIO_ERR_STATUS_BUSY
798#define MPII_SCSIIO_ERR_STATUS_INTERMEDIATE
799#define MPII_SCSIIO_ERR_STATUS_INTERMEDIATE_CONDMET
800#define MPII_SCSIIO_ERR_STATUS_RESERVATION_CONFLICT
801#define MPII_SCSIIO_ERR_STATUS_CMD_TERM
802#define MPII_SCSIIO_ERR_STATUS_TASK_SET_FULL
803#define MPII_SCSIIO_ERR_STATUS_ACA_ACTIVE
804#endif
805	u_int8_t		scsi_state;
806#define MPII_SCSIIO_ERR_STATE_AUTOSENSE_VALID		(1<<0)
807#define MPII_SCSIIO_ERR_STATE_AUTOSENSE_FAILED		(1<<1)
808#define MPII_SCSIIO_ERR_STATE_NO_SCSI_STATUS		(1<<2)
809#define MPII_SCSIIO_ERR_STATE_TERMINATED		(1<<3)
810#define MPII_SCSIIO_ERR_STATE_RESPONSE_INFO_VALID	(1<<4)
811#define MPII_SCSIIO_ERR_STATE_QUEUE_TAG_REJECTED	(0xffff)
812	u_int16_t		ioc_status;
813
814	u_int32_t		ioc_loginfo;
815
816	u_int32_t		transfer_count;
817
818	u_int32_t		sense_count;
819
820	u_int32_t		response_info;
821
822	u_int16_t		task_tag;
823	u_int16_t		reserved4;
824
825	u_int32_t		bidirectional_transfer_count;
826
827	u_int32_t		reserved5;
828
829	u_int32_t		reserved6;
830} __packed;
831
832struct mpii_request_descr {
833	u_int8_t		request_flags;
834#define MPII_REQ_DESCR_TYPE_MASK			(0x0e)
835#define MPII_REQ_DESCR_SCSI_IO				(0x00)
836#define MPII_REQ_DESCR_SCSI_TARGET			(0x02)
837#define MPII_REQ_DESCR_HIGH_PRIORITY			(0x06)
838#define MPII_REQ_DESCR_DEFAULT				(0x08)
839	u_int8_t		vf_id;
840	u_int16_t		smid;
841
842	u_int16_t		lmid;
843	u_int16_t		dev_handle;
844} __packed;
845
846struct mpii_reply_descr {
847	u_int8_t		reply_flags;
848#define MPII_REPLY_DESCR_TYPE_MASK               	(0x0f)
849#define MPII_REPLY_DESCR_SCSI_IO_SUCCESS         	(0x00)
850#define MPII_REPLY_DESCR_ADDRESS_REPLY           	(0x01)
851#define MPII_REPLY_DESCR_TARGET_ASSIST_SUCCESS    	(0x02)
852#define MPII_REPLY_DESCR_TARGET_COMMAND_BUFFER   	(0x03)
853#define MPII_REPLY_DESCR_UNUSED                  	(0x0f)
854	u_int8_t		vf_id;
855	u_int16_t		smid;
856
857	union {
858		u_int32_t	data;
859		u_int32_t	frame_addr;	/* Address Reply */
860	};
861} __packed;
862
863struct mpii_request_header {
864	u_int16_t		function_dependent1;
865	u_int8_t		chain_offset;
866	u_int8_t		function;
867
868	u_int16_t		function_dependent2;
869	u_int8_t		function_dependent3;
870	u_int8_t		message_flags;
871
872	u_int8_t		vp_id;
873	u_int8_t		vf_id;
874	u_int16_t		reserved;
875} __packed;
876
877struct mpii_msg_scsi_task_request {
878	u_int16_t		dev_handle;
879	u_int8_t		chain_offset;
880	u_int8_t		function;
881
882	u_int8_t		reserved1;
883	u_int8_t		task_type;
884#define MPII_SCSI_TASK_ABORT_TASK			(0x01)
885#define MPII_SCSI_TASK_ABRT_TASK_SET			(0x02)
886#define MPII_SCSI_TASK_TARGET_RESET			(0x03)
887#define MPII_SCSI_TASK_RESET_BUS			(0x04)
888#define MPII_SCSI_TASK_LOGICAL_UNIT_RESET		(0x05)
889	u_int8_t		reserved2;
890	u_int8_t		msg_flags;
891
892	u_int8_t		vp_id;
893	u_int8_t		vf_id;
894	u_int16_t		reserved3;
895
896	u_int16_t		lun[4];
897
898	u_int32_t		reserved4[7];
899
900	u_int16_t		task_mid;
901	u_int16_t		reserved5;
902} __packed;
903
904struct mpii_msg_scsi_task_reply {
905	u_int16_t		dev_handle;
906	u_int8_t		msg_length;
907	u_int8_t		function;
908
909	u_int8_t		response_code;
910	u_int8_t		task_type;
911	u_int8_t		reserved1;
912	u_int8_t		msg_flags;
913
914	u_int8_t		vp_id;
915	u_int8_t		vf_id;
916	u_int16_t		reserved2;
917
918	u_int16_t		reserved3;
919	u_int16_t		ioc_status;
920
921	u_int32_t		ioc_loginfo;
922
923	u_int32_t		termination_count;
924} __packed;
925
926struct mpii_msg_sas_oper_request {
927	u_int8_t		operation;
928#define MPII_SAS_OP_CLEAR_PERSISTENT		(0x02)
929#define MPII_SAS_OP_PHY_LINK_RESET		(0x06)
930#define MPII_SAS_OP_PHY_HARD_RESET		(0x07)
931#define MPII_SAS_OP_PHY_CLEAR_ERROR_LOG		(0x08)
932#define MPII_SAS_OP_SEND_PRIMITIVE		(0x0a)
933#define MPII_SAS_OP_FORCE_FULL_DISCOVERY	(0x0b)
934#define MPII_SAS_OP_TRANSMIT_PORT_SELECT	(0x0c)
935#define MPII_SAS_OP_REMOVE_DEVICE		(0x0d)
936#define MPII_SAS_OP_LOOKUP_MAPPING		(0x0e)
937#define MPII_SAS_OP_SET_IOC_PARAM		(0x0f)
938	u_int8_t		reserved1;
939	u_int8_t		chain_offset;
940	u_int8_t		function;
941
942	u_int16_t		dev_handle;
943	u_int8_t		ioc_param;
944	u_int8_t		msg_flags;
945
946	u_int8_t		vp_id;
947	u_int8_t		vf_id;
948	u_int16_t		reserved2;
949
950	u_int16_t		reserved3;
951	u_int8_t		phy_num;
952	u_int8_t		prim_flags;
953
954	u_int32_t		primitive;
955
956	u_int8_t		lookup_method;
957#define MPII_SAS_LOOKUP_METHOD_SAS_ADDR		(0x01)
958#define MPII_SAS_LOOKUP_METHOD_SAS_ENCL		(0x02)
959#define MPII_SAS_LOOKUP_METHOD_SAS_DEVNAME	(0x03)
960	u_int8_t		reserved4;
961	u_int16_t		slot_num;
962
963	u_int64_t		lookup_addr;
964
965	u_int32_t		ioc_param_value;
966
967	u_int64_t		reserved5;
968} __packed;
969
970struct mpii_msg_sas_oper_reply {
971	u_int8_t		operation;
972	u_int8_t		reserved1;
973	u_int8_t		chain_offset;
974	u_int8_t		function;
975
976	u_int16_t		dev_handle;
977	u_int8_t		ioc_param;
978	u_int8_t		msg_flags;
979
980	u_int8_t		vp_id;
981	u_int8_t		vf_id;
982	u_int16_t		reserved2;
983
984	u_int16_t		reserved3;
985	u_int16_t		ioc_status;
986
987	u_int32_t		ioc_loginfo;
988} __packed;
989
990struct mpii_msg_raid_action_request {
991	u_int8_t	action;
992#define MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE	(0x17)
993	u_int8_t	reserved1;
994	u_int8_t	chain_offset;
995	u_int8_t	function;
996
997	u_int16_t	vol_dev_handle;
998	u_int8_t	phys_disk_num;
999	u_int8_t	msg_flags;
1000
1001	u_int8_t	vp_id;
1002	u_int8_t	vf_if;
1003	u_int16_t	reserved2;
1004
1005	u_int32_t	reserved3;
1006
1007	u_int32_t	action_data;
1008#define MPII_RAID_VOL_WRITE_CACHE_MASK			(0x03)
1009#define MPII_RAID_VOL_WRITE_CACHE_DISABLE		(0x01)
1010#define MPII_RAID_VOL_WRITE_CACHE_ENABLE		(0x02)
1011
1012	struct mpii_sge	action_sge;
1013} __packed;
1014
1015struct mpii_msg_raid_action_reply {
1016	u_int8_t	action;
1017	u_int8_t	reserved1;
1018	u_int8_t	chain_offset;
1019	u_int8_t	function;
1020
1021	u_int16_t	vol_dev_handle;
1022	u_int8_t	phys_disk_num;
1023	u_int8_t	msg_flags;
1024
1025	u_int8_t	vp_id;
1026	u_int8_t	vf_if;
1027	u_int16_t	reserved2;
1028
1029	u_int16_t	reserved3;
1030	u_int16_t	ioc_status;
1031
1032	u_int32_t	action_data[5];
1033} __packed;
1034
1035struct mpii_cfg_hdr {
1036	u_int8_t		page_version;
1037	u_int8_t		page_length;
1038	u_int8_t		page_number;
1039	u_int8_t		page_type;
1040#define MPII_CONFIG_REQ_PAGE_TYPE_ATTRIBUTE		(0xf0)
1041#define MPI2_CONFIG_PAGEATTR_READ_ONLY              	(0x00)
1042#define MPI2_CONFIG_PAGEATTR_CHANGEABLE             	(0x10)
1043#define MPI2_CONFIG_PAGEATTR_PERSISTENT             	(0x20)
1044
1045#define MPII_CONFIG_REQ_PAGE_TYPE_MASK			(0x0f)
1046#define MPII_CONFIG_REQ_PAGE_TYPE_IO_UNIT		(0x00)
1047#define MPII_CONFIG_REQ_PAGE_TYPE_IOC			(0x01)
1048#define MPII_CONFIG_REQ_PAGE_TYPE_BIOS			(0x02)
1049#define MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL		(0x08)
1050#define MPII_CONFIG_REQ_PAGE_TYPE_MANUFACTURING		(0x09)
1051#define MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD		(0x0a)
1052#define MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED		(0x0f)
1053} __packed;
1054
1055struct mpii_ecfg_hdr {
1056	u_int8_t		page_version;
1057	u_int8_t		reserved1;
1058	u_int8_t		page_number;
1059	u_int8_t		page_type;
1060
1061	u_int16_t		ext_page_length;
1062	u_int8_t		ext_page_type;
1063#define MPII_CONFIG_REQ_PAGE_TYPE_SAS_DEVICE		(0x12)
1064#define MPII_CONFIG_REQ_PAGE_TYPE_RAID_CONFIG		(0x16)
1065#define MPII_CONFIG_REQ_PAGE_TYPE_DRIVER_MAPPING	(0x17)
1066	u_int8_t		reserved2;
1067} __packed;
1068
1069struct mpii_msg_config_request {
1070	u_int8_t		action;
1071#define MPII_CONFIG_REQ_ACTION_PAGE_HEADER		(0x00)
1072#define MPII_CONFIG_REQ_ACTION_PAGE_READ_CURRENT	(0x01)
1073#define MPII_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT	(0x02)
1074#define MPII_CONFIG_REQ_ACTION_PAGE_DEFAULT		(0x03)
1075#define MPII_CONFIG_REQ_ACTION_PAGE_WRITE_NVRAM		(0x04)
1076#define MPII_CONFIG_REQ_ACTION_PAGE_READ_DEFAULT	(0x05)
1077#define MPII_CONFIG_REQ_ACTION_PAGE_READ_NVRAM		(0x06)
1078	u_int8_t		sgl_flags;
1079	u_int8_t		chain_offset;
1080	u_int8_t		function;
1081
1082	u_int16_t		ext_page_len;
1083	u_int8_t		ext_page_type;
1084#define MPII_CONFIG_REQ_EXTPAGE_TYPE_SAS_IO_UNIT	(0x10)
1085#define MPII_CONFIG_REQ_EXTPAGE_TYPE_SAS_EXPANDER	(0x11)
1086#define MPII_CONFIG_REQ_EXTPAGE_TYPE_SAS_DEVICE		(0x12)
1087#define MPII_CONFIG_REQ_EXTPAGE_TYPE_SAS_PHY		(0x13)
1088#define MPII_CONFIG_REQ_EXTPAGE_TYPE_LOG		(0x14)
1089#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE            	(0x15)
1090#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG         	(0x16)
1091#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING      	(0x17)
1092#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT            	(0x18)
1093	u_int8_t		msg_flags;
1094
1095	u_int8_t		vp_id;
1096	u_int8_t		vf_id;
1097	u_int16_t		reserved1;
1098
1099	u_int32_t		reserved2[2];
1100
1101	struct mpii_cfg_hdr	config_header;
1102
1103	u_int32_t		page_address;
1104/* XXX lots of defns here */
1105
1106	struct mpii_sge		page_buffer;
1107} __packed;
1108
1109struct mpii_msg_config_reply {
1110	u_int8_t		action;
1111	u_int8_t		sgl_flags;
1112	u_int8_t		msg_length;
1113	u_int8_t		function;
1114
1115	u_int16_t		ext_page_length;
1116	u_int8_t		ext_page_type;
1117	u_int8_t		msg_flags;
1118
1119	u_int8_t		vp_id;
1120	u_int8_t		vf_id;
1121	u_int16_t		reserved1;
1122
1123	u_int16_t		reserved2;
1124	u_int16_t		ioc_status;
1125
1126	u_int32_t		ioc_loginfo;
1127
1128	struct mpii_cfg_hdr	config_header;
1129} __packed;
1130
1131struct mpii_cfg_manufacturing_pg0 {
1132	struct mpii_cfg_hdr	config_header;
1133
1134	char			chip_name[16];
1135	char			chip_revision[8];
1136	char			board_name[16];
1137	char			board_assembly[16];
1138	char			board_tracer_number[16];
1139} __packed;
1140
1141struct mpii_cfg_ioc_pg1 {
1142	struct mpii_cfg_hdr     config_header;
1143
1144	u_int32_t       flags;
1145
1146	u_int32_t       coalescing_timeout;
1147#define	MPII_CFG_IOC_1_REPLY_COALESCING			(1<<0)
1148
1149	u_int8_t        coalescing_depth;
1150	u_int8_t        pci_slot_num;
1151	u_int8_t        pci_bus_num;
1152	u_int8_t        pci_domain_segment;
1153
1154	u_int32_t       reserved1;
1155
1156	u_int32_t       reserved2;
1157} __packed;
1158
1159struct mpii_cfg_ioc_pg3 {
1160	struct mpii_cfg_hdr	config_header;
1161
1162	u_int8_t		no_phys_disks;
1163	u_int8_t		reserved[3];
1164
1165	/* followed by a list of mpii_cfg_raid_physdisk structs */
1166} __packed;
1167
1168struct mpii_cfg_ioc_pg8 {
1169	struct mpii_cfg_hdr	config_header;
1170
1171	u_int8_t		num_devs_per_enclosure;
1172	u_int8_t		reserved1;
1173	u_int16_t		reserved2;
1174
1175	u_int16_t		max_persistent_entries;
1176	u_int16_t		max_num_physical_mapped_ids;
1177
1178	u_int16_t		flags;
1179#define	MPII_IOC_PG8_FLAGS_DA_START_SLOT_1		(1<<5)
1180#define MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0		(1<<4)
1181#define MPII_IOC_PG8_FLAGS_MAPPING_MODE_MASK		(0x0000000e)
1182#define MPII_IOC_PG8_FLAGS_DEVICE_PERSISTENCE_MAPPING	(0<<1)
1183#define MPII_IOC_PG8_FLAGS_ENCLOSURE_SLOT_MAPPING	(1<<1)
1184#define MPII_IOC_PG8_FLAGS_DISABLE_PERSISTENT_MAPPING	(1<<0)
1185#define	MPII_IOC_PG8_FLAGS_ENABLE_PERSISTENT_MAPPING	(0<<0)
1186	u_int16_t		reserved3;
1187
1188	u_int16_t		ir_volume_mapping_flags;
1189#define	MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK	(0x00000003)
1190#define	MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING		(0<<0)
1191#define	MPII_IOC_PG8_IRFLAGS_HIGH_VOLUME_MAPPING	(1<<0)
1192	u_int16_t		reserved4;
1193
1194	u_int32_t		reserved5;
1195} __packed;
1196
1197struct mpii_cfg_raid_physdisk {
1198	u_int8_t		phys_disk_id;
1199	u_int8_t		phys_disk_bus;
1200	u_int8_t		phys_disk_ioc;
1201	u_int8_t		phys_disk_num;
1202} __packed;
1203
1204struct mpii_cfg_fc_port_pg0 {
1205	struct mpii_cfg_hdr	config_header;
1206
1207	u_int32_t		flags;
1208
1209	u_int8_t		mpii_port_nr;
1210	u_int8_t		link_type;
1211	u_int8_t		port_state;
1212	u_int8_t		reserved1;
1213
1214	u_int32_t		port_id;
1215
1216	u_int64_t		wwnn;
1217
1218	u_int64_t		wwpn;
1219
1220	u_int32_t		supported_service_class;
1221
1222	u_int32_t		supported_speeds;
1223
1224	u_int32_t		current_speed;
1225
1226	u_int32_t		max_frame_size;
1227
1228	u_int64_t		fabric_wwnn;
1229
1230	u_int64_t		fabric_wwpn;
1231
1232	u_int32_t		discovered_port_count;
1233
1234	u_int32_t		max_initiators;
1235
1236	u_int8_t		max_aliases_supported;
1237	u_int8_t		max_hard_aliases_supported;
1238	u_int8_t		num_current_aliases;
1239	u_int8_t		reserved2;
1240} __packed;
1241
1242struct mpii_cfg_fc_port_pg1 {
1243	struct mpii_cfg_hdr	config_header;
1244
1245	u_int32_t		flags;
1246
1247	u_int64_t		noseepromwwnn;
1248
1249	u_int64_t		noseepromwwpn;
1250
1251	u_int8_t		hard_alpa;
1252	u_int8_t		link_config;
1253	u_int8_t		topology_config;
1254	u_int8_t		alt_connector;
1255
1256	u_int8_t		num_req_aliases;
1257	u_int8_t		rr_tov;
1258	u_int8_t		initiator_dev_to;
1259	u_int8_t		initiator_lo_pend_to;
1260} __packed;
1261
1262struct mpii_cfg_fc_device_pg0 {
1263	struct mpii_cfg_hdr	config_header;
1264
1265	u_int64_t		wwnn;
1266
1267	u_int64_t		wwpn;
1268
1269	u_int32_t		port_id;
1270
1271	u_int8_t		protocol;
1272	u_int8_t		flags;
1273	u_int16_t		bb_credit;
1274
1275	u_int16_t		max_rx_frame_size;
1276	u_int8_t		adisc_hard_alpa;
1277	u_int8_t		port_nr;
1278
1279	u_int8_t		fc_ph_low_version;
1280	u_int8_t		fc_ph_high_version;
1281	u_int8_t		current_target_id;
1282	u_int8_t		current_bus;
1283} __packed;
1284
1285#define MPII_CFG_RAID_VOL_ADDR_HANDLE		(1<<28)
1286
1287struct mpii_cfg_raid_vol_pg0 {
1288	struct mpii_cfg_hdr	config_header;
1289
1290	u_int16_t		volume_handle;
1291	u_int8_t		volume_state;
1292#define MPII_CFG_RAID_VOL_0_STATE_MISSING		(0x00)
1293#define MPII_CFG_RAID_VOL_0_STATE_FAILED		(0x01)
1294#define MPII_CFG_RAID_VOL_0_STATE_INITIALIZING		(0x02)
1295#define MPII_CFG_RAID_VOL_0_STATE_ONLINE		(0x03)
1296#define MPII_CFG_RAID_VOL_0_STATE_DEGRADED		(0x04)
1297#define MPII_CFG_RAID_VOL_0_STATE_OPTIMAL		(0x05)
1298	u_int8_t		volume_type;
1299#define MPII_CFG_RAID_VOL_0_TYPE_RAID0			(0x00)
1300#define MPII_CFG_RAID_VOL_0_TYPE_RAID1E			(0x01)
1301#define MPII_CFG_RAID_VOL_0_TYPE_RAID1			(0x02)
1302#define MPII_CFG_RAID_VOL_0_TYPE_RAID10			(0x05)
1303#define MPII_CFG_RAID_VOL_0_TYPE_UNKNOWN		(0xff)
1304
1305	u_int32_t		volume_status;
1306#define MPII_CFG_RAID_VOL_0_STATUS_SCRUB		(1<<20)
1307#define MPII_CFG_RAID_VOL_0_STATUS_RESYNC		(1<<16)
1308
1309	u_int16_t		volume_settings;
1310#define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK		(0x3<<0)
1311#define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_UNCHANGED	(0x0<<0)
1312#define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_DISABLED	(0x1<<0)
1313#define MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED	(0x2<<0)
1314
1315	u_int8_t		hot_spare_pool;
1316	u_int8_t		reserved1;
1317
1318	u_int64_t		max_lba;
1319
1320	u_int32_t		stripe_size;
1321
1322	u_int16_t		block_size;
1323	u_int16_t		reserved2;
1324
1325	u_int8_t		phys_disk_types;
1326	u_int8_t		resync_rate;
1327	u_int16_t		data_scrub_rate;
1328
1329	u_int8_t		num_phys_disks;
1330	u_int16_t		reserved3;
1331	u_int8_t		inactive_status;
1332#define MPII_CFG_RAID_VOL_0_INACTIVE_UNKNOWN		(0x00)
1333#define MPII_CFG_RAID_VOL_0_INACTIVE_STALE_META		(0x01)
1334#define MPII_CFG_RAID_VOL_0_INACTIVE_FOREIGN_VOL	(0x02)
1335#define MPII_CFG_RAID_VOL_0_INACTIVE_NO_RESOURCES	(0x03)
1336#define MPII_CFG_RAID_VOL_0_INACTIVE_CLONED_VOL		(0x04)
1337#define MPII_CFG_RAID_VOL_0_INACTIVE_INSUF_META		(0x05)
1338
1339	/* followed by a list of mpii_cfg_raid_vol_pg0_physdisk structs */
1340} __packed;
1341
1342struct mpii_cfg_raid_vol_pg0_physdisk {
1343	u_int8_t		raid_set_num;
1344	u_int8_t		phys_disk_map;
1345	u_int8_t		phys_disk_num;
1346	u_int8_t		reserved;
1347} __packed;
1348
1349struct mpii_cfg_raid_vol_pg1 {
1350	struct mpii_cfg_hdr	config_header;
1351
1352	u_int8_t		volume_id;
1353	u_int8_t		volume_bus;
1354	u_int8_t		volume_ioc;
1355	u_int8_t		reserved1;
1356
1357	u_int8_t		guid[24];
1358
1359	u_int8_t		name[32];
1360
1361	u_int64_t		wwid;
1362
1363	u_int32_t		reserved2;
1364
1365	u_int32_t		reserved3;
1366} __packed;
1367
1368#define MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER		(1<<28)
1369
1370struct mpii_cfg_raid_physdisk_pg0 {
1371	struct mpii_cfg_hdr	config_header;
1372
1373	u_int16_t		dev_handle;
1374	u_int8_t		reserved1;
1375	u_int8_t		phys_disk_num;
1376
1377	u_int8_t		enc_id;
1378	u_int8_t		enc_bus;
1379	u_int8_t		hot_spare_pool;
1380	u_int8_t		enc_type;
1381#define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_NONE		(0x0)
1382#define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_SAFTE		(0x1)
1383#define MPII_CFG_RAID_PHYDISK_0_ENCTYPE_SES		(0x2)
1384
1385	u_int32_t		reserved2;
1386
1387	u_int8_t		vendor_id[8];
1388
1389	u_int8_t		product_id[16];
1390
1391	u_int8_t		product_rev[4];
1392
1393	u_int8_t		serial[32];
1394
1395	u_int32_t		reserved3;
1396
1397	u_int8_t		phys_disk_state;
1398#define MPII_CFG_RAID_PHYDISK_0_STATE_NOTCONFIGURED	(0x00)
1399#define MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE	(0x01)
1400#define MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE		(0x02)
1401#define MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE		(0x03)
1402#define MPII_CFG_RAID_PHYDISK_0_STATE_HOTSPARE		(0x04)
1403#define MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED		(0x05)
1404#define MPII_CFG_RAID_PHYDISK_0_STATE_REBUILDING	(0x06)
1405#define MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL		(0x07)
1406	u_int8_t		offline_reason;
1407#define MPII_CFG_RAID_PHYDISK_0_OFFLINE_MISSING		(0x01)
1408#define MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILED		(0x03)
1409#define MPII_CFG_RAID_PHYDISK_0_OFFLINE_INITIALIZING	(0x04)
1410#define MPII_CFG_RAID_PHYDISK_0_OFFLINE_REQUESTED	(0x05)
1411#define MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILEDREQ	(0x06)
1412#define MPII_CFG_RAID_PHYDISK_0_OFFLINE_OTHER		(0xff)
1413
1414	u_int8_t		incompat_reason;
1415	u_int8_t		phys_disk_attrs;
1416
1417	u_int32_t		phys_disk_status;
1418#define MPII_CFG_RAID_PHYDISK_0_STATUS_OUTOFSYNC	(1<<0)
1419#define MPII_CFG_RAID_PHYDISK_0_STATUS_QUIESCED		(1<<1)
1420
1421	u_int64_t		dev_max_lba;
1422
1423	u_int64_t		host_max_lba;
1424
1425	u_int64_t		coerced_max_lba;
1426
1427	u_int16_t		block_size;
1428	u_int16_t		reserved4;
1429
1430	u_int32_t		reserved5;
1431} __packed;
1432
1433struct mpii_cfg_raid_physdisk_pg1 {
1434	struct mpii_cfg_hdr	config_header;
1435
1436	u_int8_t		num_phys_disk_paths;
1437	u_int8_t		phys_disk_num;
1438	u_int16_t		reserved1;
1439
1440	u_int32_t		reserved2;
1441
1442	/* followed by mpii_cfg_raid_physdisk_path structs */
1443} __packed;
1444
1445struct mpii_cfg_raid_physdisk_path {
1446	u_int8_t		phys_disk_id;
1447	u_int8_t		phys_disk_bus;
1448	u_int16_t		reserved1;
1449
1450	u_int64_t		wwwid;
1451
1452	u_int64_t		owner_wwid;
1453
1454	u_int8_t		ownder_id;
1455	u_int8_t		reserved2;
1456	u_int16_t		flags;
1457#define MPII_CFG_RAID_PHYDISK_PATH_INVALID	(1<<0)
1458#define MPII_CFG_RAID_PHYDISK_PATH_BROKEN	(1<<1)
1459} __packed;
1460
1461#define MPII_CFG_SAS_DEV_ADDR_NEXT		(0<<28)
1462#define MPII_CFG_SAS_DEV_ADDR_BUS		(1<<28)
1463#define MPII_CFG_SAS_DEV_ADDR_HANDLE		(2<<28)
1464
1465struct mpii_cfg_sas_dev_pg0 {
1466	struct mpii_ecfg_hdr	config_header;
1467
1468	u_int16_t		slot;
1469	u_int16_t		enc_handle;
1470
1471	u_int64_t		sas_addr;
1472
1473	u_int16_t		parent_dev_handle;
1474	u_int8_t		phy_num;
1475	u_int8_t		access_status;
1476
1477	u_int16_t		dev_handle;
1478	u_int8_t		target;
1479	u_int8_t		bus;
1480
1481	u_int32_t		device_info;
1482#define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE			(0x7)
1483#define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE_NONE		(0x0)
1484#define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE_END		(0x1)
1485#define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE_EDGE_EXPANDER	(0x2)
1486#define MPII_CFG_SAS_DEV_0_DEVINFO_TYPE_FANOUT_EXPANDER	(0x3)
1487#define MPII_CFG_SAS_DEV_0_DEVINFO_SATA_HOST		(1<<3)
1488#define MPII_CFG_SAS_DEV_0_DEVINFO_SMP_INITIATOR	(1<<4)
1489#define MPII_CFG_SAS_DEV_0_DEVINFO_STP_INITIATOR	(1<<5)
1490#define MPII_CFG_SAS_DEV_0_DEVINFO_SSP_INITIATOR	(1<<6)
1491#define MPII_CFG_SAS_DEV_0_DEVINFO_SATA_DEVICE		(1<<7)
1492#define MPII_CFG_SAS_DEV_0_DEVINFO_SMP_TARGET		(1<<8)
1493#define MPII_CFG_SAS_DEV_0_DEVINFO_STP_TARGET		(1<<9)
1494#define MPII_CFG_SAS_DEV_0_DEVINFO_SSP_TARGET		(1<<10)
1495#define MPII_CFG_SAS_DEV_0_DEVINFO_DIRECT_ATTACHED	(1<<11)
1496#define MPII_CFG_SAS_DEV_0_DEVINFO_LSI_DEVICE		(1<<12)
1497#define MPII_CFG_SAS_DEV_0_DEVINFO_ATAPI_DEVICE		(1<<13)
1498#define MPII_CFG_SAS_DEV_0_DEVINFO_SEP_DEVICE		(1<<14)
1499
1500	u_int16_t		flags;
1501#define MPII_CFG_SAS_DEV_0_FLAGS_DEV_PRESENT		(1<<0)
1502#define MPII_CFG_SAS_DEV_0_FLAGS_DEV_MAPPED		(1<<1)
1503#define MPII_CFG_SAS_DEV_0_FLAGS_DEV_MAPPED_PERSISTENT	(1<<2)
1504#define MPII_CFG_SAS_DEV_0_FLAGS_SATA_PORT_SELECTOR	(1<<3)
1505#define MPII_CFG_SAS_DEV_0_FLAGS_SATA_FUA		(1<<4)
1506#define MPII_CFG_SAS_DEV_0_FLAGS_SATA_NCQ		(1<<5)
1507#define MPII_CFG_SAS_DEV_0_FLAGS_SATA_SMART		(1<<6)
1508#define MPII_CFG_SAS_DEV_0_FLAGS_SATA_LBA48		(1<<7)
1509#define MPII_CFG_SAS_DEV_0_FLAGS_UNSUPPORTED		(1<<8)
1510#define MPII_CFG_SAS_DEV_0_FLAGS_SATA_SETTINGS		(1<<9)
1511	u_int8_t		physical_port;
1512	u_int8_t		max_port_conn;
1513
1514	u_int64_t		device_name;
1515
1516	u_int8_t		port_groups;
1517	u_int8_t		dma_group;
1518	u_int8_t		ctrl_group;
1519	u_int8_t		reserved1;
1520
1521	u_int64_t		reserved2;
1522} __packed;
1523
1524#define MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG		(2<<28)
1525
1526struct mpii_cfg_raid_config_pg0 {
1527	struct	mpii_ecfg_hdr	config_header;
1528
1529	u_int8_t		num_hot_spares;
1530	u_int8_t		num_phys_disks;
1531	u_int8_t		num_volumes;
1532	u_int8_t		config_num;
1533
1534	u_int32_t		flags;
1535#define MPII_CFG_RAID_CONFIG_0_FLAGS_NATIVE		(0<<0)
1536#define MPII_CFG_RAID_CONFIG_0_FLAGS_FOREIGN		(1<<0)
1537
1538	u_int32_t		config_guid[6];
1539
1540	u_int32_t		reserved1;
1541
1542	u_int8_t		num_elements;
1543	u_int8_t		reserved2[3];
1544
1545	/* followed by struct mpii_raid_config_element structs */
1546} __packed;
1547
1548struct mpii_raid_config_element {
1549	u_int16_t		element_flags;
1550#define MPII_RAID_CONFIG_ELEMENT_FLAG_VOLUME		(0x0)
1551#define MPII_RAID_CONFIG_ELEMENT_FLAG_VOLUME_PHYS_DISK	(0x1)
1552#define	MPII_RAID_CONFIG_ELEMENT_FLAG_HSP_PHYS_DISK	(0x2)
1553#define MPII_RAID_CONFIG_ELEMENT_ONLINE_CE_PHYS_DISK	(0x3)
1554	u_int16_t		vol_dev_handle;
1555
1556	u_int8_t		hot_spare_pool;
1557	u_int8_t		phys_disk_num;
1558	u_int16_t		phys_disk_dev_handle;
1559} __packed;
1560
1561struct mpii_cfg_dpm_pg0 {
1562	struct mpii_ecfg_hdr	config_header;
1563#define MPII_DPM_ADDRESS_FORM_MASK			(0xf0000000)
1564#define MPII_DPM_ADDRESS_FORM_ENTRY_RANGE		(0x00000000)
1565#define MPII_DPM_ADDRESS_ENTRY_COUNT_MASK		(0x0fff0000)
1566#define MPII_DPM_ADDRESS_ENTRY_COUNT_SHIFT		(16)
1567#define MPII_DPM_ADDRESS_START_ENTRY_MASK		(0x0000ffff)
1568
1569	/* followed by struct mpii_dpm_entry structs */
1570} __packed;
1571
1572struct mpii_dpm_entry {
1573	u_int64_t		physical_identifier;
1574
1575	u_int16_t		mapping_information;
1576	u_int16_t		device_index;
1577
1578	u_int32_t		physical_bits_mapping;
1579
1580	u_int32_t		reserved1;
1581} __packed;
1582
1583struct mpii_evt_sas_discovery {
1584	u_int8_t		flags;
1585#define	MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_MASK	(1<<1)
1586#define MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_NO_CHANGE	(0<<1)
1587#define MPII_EVENT_SAS_DISC_FLAGS_DEV_CHANGE_CHANGE	(1<<1)
1588#define MPII_EVENT_SAS_DISC_FLAGS_DISC_IN_PROG_MASK	(1<<0)
1589#define MPII_EVENT_SAS_DISC_FLAGS_DISC_NOT_IN_PROGRESS	(1<<0)
1590#define MPII_EVENT_SAS_DISC_FLAGS_DISC_IN_PROGRESS	(0<<0)
1591	u_int8_t		reason_code;
1592#define MPII_EVENT_SAS_DISC_REASON_CODE_STARTED		(0x01)
1593#define	MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED	(0x02)
1594	u_int8_t		physical_port;
1595	u_int8_t		reserved1;
1596
1597	u_int32_t		discovery_status;
1598} __packed;
1599
1600struct mpii_evt_ir_status {
1601	u_int16_t		vol_dev_handle;
1602	u_int16_t		reserved1;
1603
1604	u_int8_t		operation;
1605#define MPII_EVENT_IR_RAIDOP_RESYNC			(0x00)
1606#define MPII_EVENT_IR_RAIDOP_OCE			(0x01)
1607#define MPII_EVENT_IR_RAIDOP_CONS_CHECK			(0x02)
1608#define MPII_EVENT_IR_RAIDOP_BG_INIT			(0x03)
1609#define MPII_EVENT_IR_RAIDOP_MAKE_CONS			(0x04)
1610	u_int8_t		percent;
1611	u_int16_t		reserved2;
1612
1613	u_int32_t		reserved3;
1614};
1615
1616struct mpii_evt_ir_volume {
1617	u_int16_t		vol_dev_handle;
1618	u_int8_t		reason_code;
1619#define MPII_EVENT_IR_VOL_RC_SETTINGS_CHANGED		(0x01)
1620#define MPII_EVENT_IR_VOL_RC_STATUS_CHANGED		(0x02)
1621#define MPII_EVENT_IR_VOL_RC_STATE_CHANGED		(0x03)
1622	u_int8_t		reserved1;
1623
1624	u_int32_t		new_value;
1625	u_int32_t		prev_value;
1626} __packed;
1627
1628struct mpii_evt_ir_physical_disk {
1629	u_int16_t		reserved1;
1630	u_int8_t		reason_code;
1631#define MPII_EVENT_IR_PD_RC_SETTINGS_CHANGED		(0x01)
1632#define MPII_EVENT_IR_PD_RC_STATUS_FLAGS_CHANGED	(0x02)
1633#define MPII_EVENT_IR_PD_RC_STATUS_CHANGED		(0x03)
1634	u_int8_t		phys_disk_num;
1635
1636	u_int16_t		phys_disk_dev_handle;
1637	u_int16_t		reserved2;
1638
1639	u_int16_t		slot;
1640	u_int16_t		enclosure_handle;
1641
1642	u_int32_t		new_value;
1643	u_int32_t		previous_value;
1644} __packed;
1645
1646struct mpii_evt_sas_tcl {
1647	u_int16_t		enclosure_handle;
1648	u_int16_t		expander_handle;
1649
1650	u_int8_t		num_phys;
1651	u_int8_t		reserved1[3];
1652
1653	u_int8_t		num_entries;
1654	u_int8_t		start_phy_num;
1655	u_int8_t		expn_status;
1656#define	MPII_EVENT_SAS_TOPO_ES_ADDED			(0x01)
1657#define MPII_EVENT_SAS_TOPO_ES_NOT_RESPONDING		(0x02)
1658#define MPII_EVENT_SAS_TOPO_ES_RESPONDING		(0x03)
1659#define MPII_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING	(0x04)
1660	u_int8_t		physical_port;
1661
1662	/* followed by num_entries number of struct mpii_evt_phy_entry */
1663} __packed;
1664
1665struct mpii_evt_phy_entry {
1666	u_int16_t		dev_handle;
1667	u_int8_t		link_rate;
1668	u_int8_t		phy_status;
1669#define MPII_EVENT_SAS_TOPO_PS_RC_MASK			(0x0f)
1670#define MPII_EVENT_SAS_TOPO_PS_RC_ADDED			(0x01)
1671#define MPII_EVENT_SAS_TOPO_PS_RC_MISSING		(0x02)
1672} __packed;
1673
1674struct mpii_evt_ir_cfg_change_list {
1675	u_int8_t		num_elements;
1676	u_int16_t		reserved;
1677	u_int8_t		config_num;
1678
1679	u_int32_t		flags;
1680#define MPII_EVT_IR_CFG_CHANGE_LIST_FOREIGN		(0x1)
1681
1682	/* followed by num_elements struct mpii_evt_ir_cfg_elements */
1683} __packed;
1684
1685struct mpii_evt_ir_cfg_element {
1686	u_int16_t		element_flags;
1687#define MPII_EVT_IR_CFG_ELEMENT_TYPE_MASK		(0xf)
1688#define MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME		(0x0)
1689#define MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME_DISK	(0x1)
1690#define MPII_EVT_IR_CFG_ELEMENT_TYPE_HOT_SPARE		(0x2)
1691	u_int16_t		vol_dev_handle;
1692
1693	u_int8_t		reason_code;
1694#define MPII_EVT_IR_CFG_ELEMENT_RC_ADDED		(0x01)
1695#define MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED		(0x02)
1696#define MPII_EVT_IR_CFG_ELEMENT_RC_NO_CHANGE		(0x03)
1697#define MPII_EVT_IR_CFG_ELEMENT_RC_HIDE			(0x04)
1698#define MPII_EVT_IR_CFG_ELEMENT_RC_UNHIDE		(0x05)
1699#define MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED	(0x06)
1700#define MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED	(0x07)
1701#define MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED		(0x08)
1702#define MPII_EVT_IR_CFG_ELEMENT_RC_PD_DELETED		(0x09)
1703	u_int8_t		phys_disk_num;
1704	u_int16_t		phys_disk_dev_handle;
1705} __packed;
1706
1707/* #define MPII_DEBUG */
1708#ifdef MPII_DEBUG
1709#define DPRINTF(x...)		do { if (mpii_debug) printf(x); } while(0)
1710#define DNPRINTF(n,x...)	do { if (mpii_debug & (n)) printf(x); } while(0)
1711#define	MPII_D_CMD		(0x0001)
1712#define	MPII_D_INTR		(0x0002)
1713#define	MPII_D_MISC		(0x0004)
1714#define	MPII_D_DMA		(0x0008)
1715#define	MPII_D_IOCTL		(0x0010)
1716#define	MPII_D_RW		(0x0020)
1717#define	MPII_D_MEM		(0x0040)
1718#define	MPII_D_CCB		(0x0080)
1719#define	MPII_D_PPR		(0x0100)
1720#define	MPII_D_RAID		(0x0200)
1721#define	MPII_D_EVT		(0x0400)
1722#define MPII_D_CFG		(0x0800)
1723#define MPII_D_MAP		(0x1000)
1724
1725#if 0
1726u_int32_t  mpii_debug = 0
1727		| MPII_D_CMD
1728		| MPII_D_INTR
1729		| MPII_D_MISC
1730		| MPII_D_DMA
1731		| MPII_D_IOCTL
1732		| MPII_D_RW
1733		| MPII_D_MEM
1734		| MPII_D_CCB
1735		| MPII_D_PPR
1736		| MPII_D_RAID
1737		| MPII_D_EVT
1738		| MPII_D_CFG
1739		| MPII_D_MAP
1740	;
1741#endif
1742u_int32_t  mpii_debug = MPII_D_MISC;
1743#else
1744#define DPRINTF(x...)
1745#define DNPRINTF(n,x...)
1746#endif
1747
1748#define MPII_REQUEST_SIZE	(512)
1749#define MPII_REPLY_SIZE		(128)
1750#define MPII_REPLY_COUNT	PAGE_SIZE / MPII_REPLY_SIZE
1751
1752/*
1753 * this is the max number of sge's we can stuff in a request frame:
1754 * sizeof(scsi_io) + sizeof(sense) + sizeof(sge) * 32 = MPII_REQUEST_SIZE
1755 */
1756#define MPII_MAX_SGL			(32)
1757
1758#define MPII_MAX_REQUEST_CREDIT		(128)
1759
1760#define MPII_MAXFER MAXPHYS /* XXX bogus */
1761
1762struct mpii_dmamem {
1763	bus_dmamap_t		mdm_map;
1764	bus_dma_segment_t	mdm_seg;
1765	size_t			mdm_size;
1766	void 			*mdm_kva;
1767};
1768#define MPII_DMA_MAP(_mdm)	(_mdm)->mdm_map
1769#define MPII_DMA_DVA(_mdm)	(_mdm)->mdm_map->dm_segs[0].ds_addr
1770#define MPII_DMA_KVA(_mdm)	(void *)(_mdm)->mdm_kva
1771
1772struct mpii_ccb_bundle {
1773	struct mpii_msg_scsi_io	mcb_io; /* sgl must follow */
1774	struct mpii_sge		mcb_sgl[MPII_MAX_SGL];
1775	struct scsi_sense_data	mcb_sense;
1776} __packed;
1777
1778struct mpii_softc;
1779
1780struct mpii_rcb {
1781	union {
1782		struct work	rcb_wk; /* has to be first in struct */
1783		SIMPLEQ_ENTRY(mpii_rcb)	rcb_link;
1784	} u;
1785	void			*rcb_reply;
1786	u_int32_t		rcb_reply_dva;
1787};
1788
1789SIMPLEQ_HEAD(mpii_rcb_list, mpii_rcb);
1790
1791struct mpii_device {
1792	int			flags;
1793#define MPII_DF_ATTACH		(0x0001)
1794#define MPII_DF_DETACH		(0x0002)
1795#define MPII_DF_HIDDEN		(0x0004)
1796#define MPII_DF_UNUSED		(0x0008)
1797#define MPII_DF_VOLUME		(0x0010)
1798#define MPII_DF_VOLUME_DISK	(0x0020)
1799#define MPII_DF_HOT_SPARE	(0x0040)
1800	short			slot;
1801	short			percent;
1802	u_int16_t		dev_handle;
1803	u_int16_t		enclosure;
1804	u_int16_t		expander;
1805	u_int8_t		phy_num;
1806	u_int8_t		physical_port;
1807};
1808
1809struct mpii_ccb {
1810	union {
1811		struct work	ccb_wk; /* has to be first in struct */
1812		SIMPLEQ_ENTRY(mpii_ccb)	ccb_link;
1813	} u;
1814	struct mpii_softc	*ccb_sc;
1815	int			ccb_smid;
1816
1817	void *			ccb_cookie;
1818	bus_dmamap_t		ccb_dmamap;
1819
1820	bus_addr_t		ccb_offset;
1821	void			*ccb_cmd;
1822	bus_addr_t		ccb_cmd_dva;
1823	u_int16_t		ccb_dev_handle;
1824
1825	volatile enum {
1826		MPII_CCB_FREE,
1827		MPII_CCB_READY,
1828		MPII_CCB_QUEUED,
1829		MPII_CCB_TIMEOUT
1830	}			ccb_state;
1831
1832	void			(*ccb_done)(struct mpii_ccb *);
1833	struct mpii_rcb		*ccb_rcb;
1834
1835};
1836
1837struct mpii_ccb_wait {
1838	kmutex_t	mpii_ccbw_mtx;
1839	kcondvar_t	mpii_ccbw_cv;
1840};
1841
1842SIMPLEQ_HEAD(mpii_ccb_list, mpii_ccb);
1843
1844struct mpii_softc {
1845	device_t		sc_dev;
1846
1847	pci_chipset_tag_t	sc_pc;
1848	pcitag_t		sc_tag;
1849
1850	void			*sc_ih;
1851
1852	int			sc_flags;
1853#define MPII_F_RAID		(1<<1)
1854
1855	struct scsipi_adapter	sc_adapt;
1856	struct scsipi_channel	sc_chan;
1857	device_t		sc_child; /* our scsibus */
1858
1859	struct mpii_device	**sc_devs;
1860
1861	bus_space_tag_t		sc_iot;
1862	bus_space_handle_t	sc_ioh;
1863	bus_size_t		sc_ios;
1864	bus_dma_tag_t		sc_dmat;
1865
1866	kmutex_t		sc_req_mtx;
1867	kmutex_t		sc_rep_mtx;
1868
1869	u_int8_t		sc_porttype;
1870	int			sc_request_depth;
1871	int			sc_num_reply_frames;
1872	int			sc_reply_free_qdepth;
1873	int			sc_reply_post_qdepth;
1874	int			sc_maxchdepth;
1875	int			sc_first_sgl_len;
1876	int			sc_chain_len;
1877	int			sc_max_sgl_len;
1878
1879	u_int8_t		sc_ioc_event_replay;
1880	u_int16_t		sc_max_enclosures;
1881	u_int16_t		sc_max_expanders;
1882	u_int8_t		sc_max_volumes;
1883	u_int16_t		sc_max_devices;
1884	u_int16_t		sc_max_dpm_entries;
1885	u_int16_t		sc_vd_count;
1886	u_int16_t		sc_vd_id_low;
1887	u_int16_t		sc_pd_id_start;
1888	u_int8_t		sc_num_channels;
1889	int			sc_ioc_number;
1890	u_int8_t		sc_vf_id;
1891	u_int8_t		sc_num_ports;
1892
1893	struct mpii_ccb		*sc_ccbs;
1894	struct mpii_ccb_list	sc_ccb_free;
1895	kmutex_t		sc_ccb_free_mtx;
1896	kcondvar_t		sc_ccb_free_cv;
1897
1898	kmutex_t		sc_ccb_mtx;
1899				/*
1900				 * this protects the ccb state and list entry
1901				 * between mpii_scsi_cmd and scsidone.
1902				 */
1903
1904	struct workqueue	*sc_ssb_tmowk;
1905
1906	struct mpii_dmamem	*sc_requests;
1907
1908	struct mpii_dmamem	*sc_replies;
1909	struct mpii_rcb		*sc_rcbs;
1910
1911	struct mpii_dmamem	*sc_reply_postq;
1912	struct mpii_reply_descr	*sc_reply_postq_kva;
1913	int			sc_reply_post_host_index;
1914
1915	struct mpii_dmamem	*sc_reply_freeq;
1916	int			sc_reply_free_host_index;
1917
1918	struct workqueue	*sc_ssb_evt_ackwk;
1919
1920	struct sysmon_envsys	*sc_sme;
1921	envsys_data_t		*sc_sensors;
1922};
1923
1924static int	mpii_match(device_t, cfdata_t, void *);
1925static void	mpii_attach(device_t, device_t, void *);
1926static int	mpii_detach(device_t, int);
1927static void	mpii_childdetached(device_t, device_t);
1928static int	mpii_rescan(device_t, const char *, const int *);
1929
1930static int	mpii_intr(void *);
1931
1932CFATTACH_DECL3_NEW(mpii, sizeof(struct mpii_softc),
1933    mpii_match, mpii_attach, mpii_detach, NULL, mpii_rescan,
1934    mpii_childdetached, DVF_DETACH_SHUTDOWN);
1935
1936#define PREAD(s, r)	pci_conf_read((s)->sc_pc, (s)->sc_tag, (r))
1937#define PWRITE(s, r, v)	pci_conf_write((s)->sc_pc, (s)->sc_tag, (r), (v))
1938
1939static void	mpii_scsipi_request(struct scsipi_channel *,
1940		    scsipi_adapter_req_t, void *);
1941static void	mpii_scsi_cmd_done(struct mpii_ccb *);
1942static void	mpii_minphys(struct buf *bp);
1943
1944static struct mpii_dmamem *mpii_dmamem_alloc(struct mpii_softc *, size_t);
1945static void	mpii_dmamem_free(struct mpii_softc *, struct mpii_dmamem *);
1946static int	mpii_alloc_ccbs(struct mpii_softc *);
1947static struct mpii_ccb *mpii_get_ccb(struct mpii_softc *, int);
1948#define MPII_NOSLEEP 0x0001
1949static void	mpii_put_ccb(struct mpii_softc *, struct mpii_ccb *);
1950static int	mpii_alloc_replies(struct mpii_softc *);
1951static int	mpii_alloc_queues(struct mpii_softc *);
1952static void	mpii_push_reply(struct mpii_softc *, struct mpii_rcb *);
1953static void	mpii_push_replies(struct mpii_softc *);
1954
1955static void	mpii_scsi_cmd_tmo(void *);
1956static void	mpii_scsi_cmd_tmo_handler(struct work *, void *);
1957static void	mpii_scsi_cmd_tmo_done(struct mpii_ccb *);
1958
1959static int	mpii_alloc_dev(struct mpii_softc *);
1960static int	mpii_insert_dev(struct mpii_softc *, struct mpii_device *);
1961static int	mpii_remove_dev(struct mpii_softc *, struct mpii_device *);
1962static struct mpii_device *mpii_find_dev(struct mpii_softc *, u_int16_t);
1963
1964static void	mpii_start(struct mpii_softc *, struct mpii_ccb *);
1965static int	mpii_poll(struct mpii_softc *, struct mpii_ccb *);
1966static void	mpii_poll_done(struct mpii_ccb *);
1967static struct mpii_rcb *mpii_reply(struct mpii_softc *,
1968			struct mpii_reply_descr *);
1969
1970static void	mpii_wait(struct mpii_softc *, struct mpii_ccb *);
1971static void	mpii_wait_done(struct mpii_ccb *);
1972
1973static void	mpii_init_queues(struct mpii_softc *);
1974
1975static int	mpii_load_xs(struct mpii_ccb *);
1976
1977static u_int32_t mpii_read(struct mpii_softc *, bus_size_t);
1978static void	mpii_write(struct mpii_softc *, bus_size_t, u_int32_t);
1979static int	mpii_wait_eq(struct mpii_softc *, bus_size_t, u_int32_t,
1980		    u_int32_t);
1981static int	mpii_wait_ne(struct mpii_softc *, bus_size_t, u_int32_t,
1982		    u_int32_t);
1983
1984static int	mpii_init(struct mpii_softc *);
1985static int	mpii_reset_soft(struct mpii_softc *);
1986static int	mpii_reset_hard(struct mpii_softc *);
1987
1988static int	mpii_handshake_send(struct mpii_softc *, void *, size_t);
1989static int	mpii_handshake_recv_dword(struct mpii_softc *,
1990		    u_int32_t *);
1991static int	mpii_handshake_recv(struct mpii_softc *, void *, size_t);
1992
1993static void	mpii_empty_done(struct mpii_ccb *);
1994
1995static int	mpii_iocinit(struct mpii_softc *);
1996static int	mpii_iocfacts(struct mpii_softc *);
1997static int	mpii_portfacts(struct mpii_softc *);
1998static int	mpii_portenable(struct mpii_softc *);
1999static int	mpii_cfg_coalescing(struct mpii_softc *);
2000
2001static int	mpii_eventnotify(struct mpii_softc *);
2002static void	mpii_eventnotify_done(struct mpii_ccb *);
2003static void	mpii_eventack(struct work *, void *);
2004static void	mpii_eventack_done(struct mpii_ccb *);
2005static void	mpii_event_process(struct mpii_softc *, struct mpii_rcb *);
2006static void	mpii_event_sas(struct mpii_softc *,
2007		    struct mpii_msg_event_reply *);
2008static void	mpii_event_raid(struct mpii_softc *,
2009		    struct mpii_msg_event_reply *);
2010static void	mpii_event_defer(void *, void *);
2011
2012static void	mpii_sas_remove_device(struct mpii_softc *, u_int16_t);
2013
2014static int	mpii_req_cfg_header(struct mpii_softc *, u_int8_t,
2015		    u_int8_t, u_int32_t, int, void *);
2016static int	mpii_req_cfg_page(struct mpii_softc *, u_int32_t, int,
2017		    void *, int, void *, size_t);
2018
2019static int	mpii_get_ioc_pg8(struct mpii_softc *);
2020
2021#if 0
2022static int	mpii_ioctl_cache(struct scsi_link *, u_long, struct dk_cache *);
2023#endif
2024static int	mpii_cache_enable(struct mpii_softc *, struct mpii_device *);
2025
2026#if NBIO > 0
2027static int	mpii_ioctl(device_t, u_long, void *);
2028static int	mpii_ioctl_inq(struct mpii_softc *, struct bioc_inq *);
2029static int	mpii_ioctl_vol(struct mpii_softc *, struct bioc_vol *);
2030static int	mpii_ioctl_disk(struct mpii_softc *, struct bioc_disk *);
2031static int	mpii_bio_hs(struct mpii_softc *, struct bioc_disk *, int,
2032		    int, int *);
2033static int	mpii_bio_disk(struct mpii_softc *, struct bioc_disk *,
2034		    u_int8_t);
2035static struct mpii_device *mpii_find_vol(struct mpii_softc *, int);
2036static int	mpii_bio_volstate(struct mpii_softc *, struct bioc_vol *);
2037static int	mpii_create_sensors(struct mpii_softc *);
2038static int	mpii_destroy_sensors(struct mpii_softc *);
2039static void	mpii_refresh_sensors(struct sysmon_envsys *, envsys_data_t *);
2040#endif /* NBIO > 0 */
2041
2042#define DEVNAME(_s)		(device_xname((_s)->sc_dev))
2043
2044#define dwordsof(s)		(sizeof(s) / sizeof(u_int32_t))
2045#define dwordn(p, n)		(((u_int32_t *)(p))[(n)])
2046
2047#define mpii_read_db(s)		mpii_read((s), MPII_DOORBELL)
2048#define mpii_write_db(s, v)	mpii_write((s), MPII_DOORBELL, (v))
2049#define mpii_read_intr(s)	mpii_read((s), MPII_INTR_STATUS)
2050#define mpii_write_intr(s, v)	mpii_write((s), MPII_INTR_STATUS, (v))
2051#define mpii_reply_waiting(s)	((mpii_read_intr((s)) & MPII_INTR_STATUS_REPLY)\
2052				    == MPII_INTR_STATUS_REPLY)
2053
2054#define mpii_read_reply_free(s)		mpii_read((s), \
2055						MPII_REPLY_FREE_HOST_INDEX)
2056#define mpii_write_reply_free(s, v)	mpii_write((s), \
2057						MPII_REPLY_FREE_HOST_INDEX, (v))
2058#define mpii_read_reply_post(s)		mpii_read((s), \
2059						MPII_REPLY_POST_HOST_INDEX)
2060#define mpii_write_reply_post(s, v)	mpii_write((s), \
2061						MPII_REPLY_POST_HOST_INDEX, (v))
2062
2063#define mpii_wait_db_int(s)	mpii_wait_ne((s), MPII_INTR_STATUS, \
2064				    MPII_INTR_STATUS_IOC2SYSDB, 0)
2065#define mpii_wait_db_ack(s)	mpii_wait_eq((s), MPII_INTR_STATUS, \
2066				    MPII_INTR_STATUS_SYS2IOCDB, 0)
2067
2068#define MPII_PG_EXTENDED	(1<<0)
2069#define MPII_PG_POLL		(1<<1)
2070#define MPII_PG_FMT		"\020" "\002POLL" "\001EXTENDED"
2071
2072#define mpii_cfg_header(_s, _t, _n, _a, _h) \
2073	mpii_req_cfg_header((_s), (_t), (_n), (_a), \
2074	    MPII_PG_POLL, (_h))
2075#define mpii_ecfg_header(_s, _t, _n, _a, _h) \
2076	mpii_req_cfg_header((_s), (_t), (_n), (_a), \
2077	    MPII_PG_POLL|MPII_PG_EXTENDED, (_h))
2078
2079#define mpii_cfg_page(_s, _a, _h, _r, _p, _l) \
2080	mpii_req_cfg_page((_s), (_a), MPII_PG_POLL, \
2081	    (_h), (_r), (_p), (_l))
2082#define mpii_ecfg_page(_s, _a, _h, _r, _p, _l) \
2083	mpii_req_cfg_page((_s), (_a), MPII_PG_POLL|MPII_PG_EXTENDED, \
2084	    (_h), (_r), (_p), (_l))
2085
2086
2087static const struct mpii_pci_product {
2088	pci_vendor_id_t         mpii_vendor;
2089	pci_product_id_t        mpii_product;
2090} mpii_devices[] = {
2091	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2004 },
2092	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2008 },
2093	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_3 },
2094	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_4 },
2095	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2108_5 },
2096	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2116_1 },
2097	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2116_2 },
2098	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_1 },
2099	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_2 },
2100	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_3 },
2101	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_4 },
2102	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_5 },
2103	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2208_6 },
2104	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_1 },
2105	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_2 },
2106	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_SAS2308_3 },
2107	{ 0,	0 }
2108};
2109
2110static int
2111mpii_match(device_t parent, cfdata_t match, void *aux)
2112{
2113	struct pci_attach_args *pa = aux;
2114	const struct mpii_pci_product *mpii;
2115
2116	for (mpii = mpii_devices; mpii->mpii_vendor != 0; mpii++) {
2117		if (PCI_VENDOR(pa->pa_id) == mpii->mpii_vendor &&
2118		    PCI_PRODUCT(pa->pa_id) == mpii->mpii_product)
2119			return (1);
2120	}
2121	return (0);
2122}
2123
2124static void
2125mpii_attach(device_t parent, device_t self, void *aux)
2126{
2127	struct mpii_softc		*sc = device_private(self);
2128	struct pci_attach_args		*pa = aux;
2129	pcireg_t			memtype;
2130	int				r;
2131	pci_intr_handle_t		ih;
2132	const char			*intrstr;
2133	struct mpii_ccb			*ccb;
2134	struct scsipi_adapter *adapt = &sc->sc_adapt;
2135	struct scsipi_channel *chan = &sc->sc_chan;
2136	char wkname[15];
2137
2138	pci_aprint_devinfo(pa, NULL);
2139
2140	sc->sc_pc = pa->pa_pc;
2141	sc->sc_tag = pa->pa_tag;
2142	sc->sc_dmat = pa->pa_dmat;
2143	sc->sc_dev = self;
2144
2145	mutex_init(&sc->sc_req_mtx, MUTEX_DEFAULT, IPL_BIO);
2146	mutex_init(&sc->sc_rep_mtx, MUTEX_DEFAULT, IPL_BIO);
2147	mutex_init(&sc->sc_ccb_free_mtx, MUTEX_DEFAULT, IPL_BIO);
2148	cv_init(&sc->sc_ccb_free_cv, "mpii_ccbs");
2149	mutex_init(&sc->sc_ccb_mtx, MUTEX_DEFAULT, IPL_BIO);
2150
2151	snprintf(wkname, sizeof(wkname), "%s_tmo", DEVNAME(sc));
2152	if (workqueue_create(&sc->sc_ssb_tmowk, wkname,
2153	    mpii_scsi_cmd_tmo_handler, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) {
2154		aprint_error_dev(self, "can't create %s workqueue\n", wkname);
2155		return;
2156	}
2157
2158	snprintf(wkname, sizeof(wkname), "%s_evt", DEVNAME(sc));
2159	if (workqueue_create(&sc->sc_ssb_evt_ackwk, wkname,
2160	    mpii_eventack, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) {
2161		aprint_error_dev(self, "can't create %s workqueue\n", wkname);
2162		return;
2163	}
2164
2165	/* find the appropriate memory base */
2166	for (r = PCI_MAPREG_START; r < PCI_MAPREG_END; r += sizeof(memtype)) {
2167		memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, r);
2168		if ((memtype & PCI_MAPREG_TYPE_MASK) == PCI_MAPREG_TYPE_MEM)
2169			break;
2170	}
2171	if (r >= PCI_MAPREG_END) {
2172		aprint_error_dev(self,
2173		    "unable to locate system interface registers\n");
2174		return;
2175	}
2176
2177	if (pci_mapreg_map(pa, r, memtype, 0, &sc->sc_iot, &sc->sc_ioh,
2178	    NULL, &sc->sc_ios) != 0) {
2179		aprint_error_dev(self,
2180		    "unable to map system interface registers\n");
2181		return;
2182	}
2183
2184	/* disable the expansion rom */
2185	PWRITE(sc, PCI_MAPREG_ROM,
2186	    PREAD(sc, PCI_MAPREG_ROM) & ~PCI_MAPREG_ROM_ENABLE);
2187
2188	/* disable interrupts */
2189	mpii_write(sc, MPII_INTR_MASK,
2190	    MPII_INTR_MASK_RESET | MPII_INTR_MASK_REPLY |
2191	    MPII_INTR_MASK_DOORBELL);
2192
2193	/* hook up the interrupt */
2194	if (pci_intr_map(pa, &ih) != 0) {
2195		aprint_error_dev(self, "unable to map interrupt\n");
2196		goto unmap;
2197	}
2198	intrstr = pci_intr_string(pa->pa_pc, ih);
2199
2200	if (mpii_init(sc) != 0) {
2201		aprint_error_dev(self, "unable to initialize ioc\n");
2202		goto unmap;
2203	}
2204
2205	if (mpii_iocfacts(sc) != 0) {
2206		aprint_error_dev(self, "unable to get iocfacts\n");
2207		goto unmap;
2208	}
2209
2210	if (mpii_alloc_ccbs(sc) != 0) {
2211		/* error already printed */
2212		goto unmap;
2213	}
2214
2215	if (mpii_alloc_replies(sc) != 0) {
2216		aprint_error_dev(self, "unable to allocated reply space\n");
2217		goto free_ccbs;
2218	}
2219
2220	if (mpii_alloc_queues(sc) != 0) {
2221		aprint_error_dev(self, "unable to allocate reply queues\n");
2222		goto free_replies;
2223	}
2224
2225	if (mpii_iocinit(sc) != 0) {
2226		aprint_error_dev(self, "unable to send iocinit\n");
2227		goto free_queues;
2228	}
2229
2230	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
2231	    MPII_DOORBELL_STATE_OPER) != 0) {
2232		aprint_error_dev(self, "state: 0x%08x\n",
2233			mpii_read_db(sc) & MPII_DOORBELL_STATE);
2234		aprint_error_dev(self, "operational state timeout\n");
2235		goto free_queues;
2236	}
2237
2238	mpii_push_replies(sc);
2239	mpii_init_queues(sc);
2240
2241	if (mpii_portfacts(sc) != 0) {
2242		aprint_error_dev(self, "unable to get portfacts\n");
2243		goto free_queues;
2244	}
2245
2246	if (mpii_get_ioc_pg8(sc) != 0) {
2247		aprint_error_dev(self, "unable to get ioc page 8\n");
2248		goto free_queues;
2249	}
2250
2251	if (mpii_cfg_coalescing(sc) != 0) {
2252		aprint_error_dev(self, "unable to configure coalescing\n");
2253		goto free_queues;
2254	}
2255
2256	/* XXX bail on unsupported porttype? */
2257	if ((sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL) ||
2258	    (sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL)) {
2259		if (mpii_eventnotify(sc) != 0) {
2260			aprint_error_dev(self, "unable to enable events\n");
2261			goto free_queues;
2262		}
2263	}
2264
2265	if (mpii_alloc_dev(sc) != 0) {
2266		aprint_error_dev(self,
2267		    "unable to allocate memory for mpii_device\n");
2268		goto free_queues;
2269	}
2270
2271	if (mpii_portenable(sc) != 0) {
2272		aprint_error_dev(self, "unable to enable port\n");
2273		goto free_dev;
2274	}
2275
2276	sc->sc_ih = pci_intr_establish(sc->sc_pc, ih, IPL_BIO,
2277	    mpii_intr, sc);
2278	if (sc->sc_ih == NULL) {
2279		aprint_error_dev(self, "can't establish interrupt");
2280		if (intrstr)
2281			aprint_error(" at %s", intrstr);
2282		aprint_error("\n");
2283		goto free_dev;
2284	}
2285
2286	memset(adapt, 0, sizeof(*adapt));
2287	adapt->adapt_dev = sc->sc_dev;
2288	adapt->adapt_nchannels = 1;
2289	adapt->adapt_openings = sc->sc_request_depth - 1;
2290	adapt->adapt_max_periph = adapt->adapt_openings;
2291	adapt->adapt_request = mpii_scsipi_request;
2292	adapt->adapt_minphys = mpii_minphys;
2293
2294	memset(chan, 0, sizeof(*chan));
2295	chan->chan_adapter = adapt;
2296	chan->chan_bustype = &scsi_sas_bustype;
2297	chan->chan_channel = 0;
2298	chan->chan_flags = 0;
2299	chan->chan_nluns = 1;
2300	chan->chan_ntargets = sc->sc_max_devices;
2301	chan->chan_id = -1;
2302
2303	mpii_rescan(self, "scsi", NULL);
2304
2305	/* enable interrupts */
2306	mpii_write(sc, MPII_INTR_MASK, MPII_INTR_MASK_DOORBELL
2307	    | MPII_INTR_MASK_RESET);
2308
2309#if NBIO > 0
2310	if (ISSET(sc->sc_flags, MPII_F_RAID)) {
2311		if (bio_register(sc->sc_dev, mpii_ioctl) != 0)
2312			panic("%s: controller registration failed",
2313			    DEVNAME(sc));
2314
2315		if (mpii_create_sensors(sc) != 0)
2316			aprint_error_dev(self, "unable to create sensors\n");
2317	}
2318#endif
2319
2320	return;
2321
2322free_dev:
2323	if (sc->sc_devs)
2324		free(sc->sc_devs, M_DEVBUF);
2325
2326free_queues:
2327	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq),
2328     	    0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD);
2329	mpii_dmamem_free(sc, sc->sc_reply_freeq);
2330
2331	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
2332	    0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD);
2333	mpii_dmamem_free(sc, sc->sc_reply_postq);
2334
2335free_replies:
2336	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
2337		0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
2338	mpii_dmamem_free(sc, sc->sc_replies);
2339
2340free_ccbs:
2341	while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
2342		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
2343	mpii_dmamem_free(sc, sc->sc_requests);
2344	free(sc->sc_ccbs, M_DEVBUF);
2345
2346unmap:
2347	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
2348	sc->sc_ios = 0;
2349}
2350
2351static int
2352mpii_detach(device_t self, int flags)
2353{
2354	struct mpii_softc		*sc = device_private(self);
2355	int error;
2356	struct mpii_ccb *ccb;
2357
2358	if ((error = config_detach_children(sc->sc_dev, flags)) != 0)
2359		return error;
2360
2361#if NBIO > 0
2362	mpii_destroy_sensors(sc);
2363	bio_unregister(sc->sc_dev);
2364#endif /* NBIO > 0 */
2365
2366	if (sc->sc_ih != NULL) {
2367		if (sc->sc_devs)
2368			free(sc->sc_devs, M_DEVBUF);
2369
2370		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq),
2371		    0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD);
2372		mpii_dmamem_free(sc, sc->sc_reply_freeq);
2373
2374		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
2375		    0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD);
2376		mpii_dmamem_free(sc, sc->sc_reply_postq);
2377
2378		bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
2379			0, PAGE_SIZE, BUS_DMASYNC_POSTREAD);
2380		mpii_dmamem_free(sc, sc->sc_replies);
2381
2382		while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
2383			bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
2384		mpii_dmamem_free(sc, sc->sc_requests);
2385		free(sc->sc_ccbs, M_DEVBUF);
2386
2387		pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
2388		sc->sc_ih = NULL;
2389	}
2390	if (sc->sc_ios != 0) {
2391		bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
2392		sc->sc_ios = 0;
2393	}
2394
2395	return (0);
2396}
2397
2398static int
2399mpii_rescan(device_t self, const char *ifattr, const int *locators)
2400{
2401	struct mpii_softc *sc = device_private(self);
2402
2403	if (sc->sc_child != NULL)
2404		return 0;
2405
2406	sc->sc_child = config_found_sm_loc(self, ifattr, locators, &sc->sc_chan,
2407	    scsiprint, NULL);
2408
2409	return 0;
2410}
2411
2412static void
2413mpii_childdetached(device_t self, device_t child)
2414{
2415        struct mpii_softc *sc = device_private(self);
2416
2417        KASSERT(self == sc->sc_dev);
2418        KASSERT(child == sc->sc_child);
2419
2420        if (child == sc->sc_child)
2421                sc->sc_child = NULL;
2422}
2423
2424static int
2425mpii_intr(void *arg)
2426{
2427	struct mpii_rcb_list		evts = SIMPLEQ_HEAD_INITIALIZER(evts);
2428	struct mpii_ccb_list		ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs);
2429	struct mpii_softc		*sc = arg;
2430	struct mpii_reply_descr		*postq = sc->sc_reply_postq_kva, *rdp;
2431	struct mpii_ccb			*ccb;
2432	struct mpii_rcb			*rcb;
2433	int				smid;
2434	int				rv = 0;
2435
2436	mutex_enter(&sc->sc_rep_mtx);
2437	bus_dmamap_sync(sc->sc_dmat,
2438	    MPII_DMA_MAP(sc->sc_reply_postq),
2439	    0, 8 * sc->sc_reply_post_qdepth,
2440	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
2441
2442	for (;;) {
2443		rdp = &postq[sc->sc_reply_post_host_index];
2444		if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
2445		    MPII_REPLY_DESCR_UNUSED)
2446			break;
2447		if (rdp->data == 0xffffffff) {
2448			/*
2449			 * ioc is still writing to the reply post queue
2450			 * race condition - bail!
2451			 */
2452			break;
2453		}
2454
2455		smid = le16toh(rdp->smid);
2456		rcb = mpii_reply(sc, rdp);
2457
2458		if (smid) {
2459			ccb = &sc->sc_ccbs[smid - 1];
2460			ccb->ccb_state = MPII_CCB_READY;
2461			ccb->ccb_rcb = rcb;
2462			SIMPLEQ_INSERT_TAIL(&ccbs, ccb, u.ccb_link);
2463		} else
2464			SIMPLEQ_INSERT_TAIL(&evts, rcb, u.rcb_link);
2465
2466		sc->sc_reply_post_host_index++;
2467		sc->sc_reply_post_host_index %= sc->sc_reply_post_qdepth;
2468		rv = 1;
2469	}
2470
2471	bus_dmamap_sync(sc->sc_dmat,
2472	    MPII_DMA_MAP(sc->sc_reply_postq),
2473	    0, 8 * sc->sc_reply_post_qdepth,
2474	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
2475
2476	if (rv)
2477		mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
2478
2479	mutex_exit(&sc->sc_rep_mtx);
2480
2481	if (rv == 0)
2482		return (0);
2483
2484	while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) {
2485		SIMPLEQ_REMOVE_HEAD(&ccbs, u.ccb_link);
2486		ccb->ccb_done(ccb);
2487	}
2488	while ((rcb = SIMPLEQ_FIRST(&evts)) != NULL) {
2489		SIMPLEQ_REMOVE_HEAD(&evts, u.rcb_link);
2490		mpii_event_process(sc, rcb);
2491	}
2492
2493	return (1);
2494}
2495
2496static int
2497mpii_load_xs(struct mpii_ccb *ccb)
2498{
2499	struct mpii_softc	*sc = ccb->ccb_sc;
2500	struct scsipi_xfer	*xs = ccb->ccb_cookie;
2501	struct mpii_ccb_bundle	*mcb = ccb->ccb_cmd;
2502	struct mpii_msg_scsi_io	*io = &mcb->mcb_io;
2503	struct mpii_sge		*sge = NULL, *nsge = &mcb->mcb_sgl[0];
2504	struct mpii_sge		*ce = NULL, *nce = NULL;
2505	u_int64_t		ce_dva;
2506	bus_dmamap_t		dmap = ccb->ccb_dmamap;
2507	u_int32_t		addr, flags;
2508	int			i, error;
2509
2510	/* zero length transfer still requires an SGE */
2511	if (xs->datalen == 0) {
2512		nsge->sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
2513		    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL);
2514		return (0);
2515	}
2516
2517	error = bus_dmamap_load(sc->sc_dmat, dmap,
2518	    xs->data, xs->datalen, NULL, (xs->xs_control & XS_CTL_NOSLEEP) ?
2519	      BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
2520	if (error) {
2521		aprint_error_dev(sc->sc_dev, "error %d loading dmamap\n",
2522		    error);
2523		return (1);
2524	}
2525
2526	/* safe default staring flags */
2527	flags = MPII_SGE_FL_TYPE_SIMPLE | MPII_SGE_FL_SIZE_64;
2528	/* if data out */
2529	if (xs->xs_control & XS_CTL_DATA_OUT)
2530		flags |= MPII_SGE_FL_DIR_OUT;
2531
2532	/* we will have to exceed the SGEs we can cram into the request frame */
2533	if (dmap->dm_nsegs > sc->sc_first_sgl_len) {
2534		ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1];
2535		io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4;
2536	}
2537
2538	for (i = 0; i < dmap->dm_nsegs; i++) {
2539		if (nsge == ce) {
2540			nsge++;
2541			sge->sg_hdr |= htole32(MPII_SGE_FL_LAST);
2542
2543			DNPRINTF(MPII_D_DMA, "%s:   - 0x%08x 0x%08x 0x%08x\n",
2544			    DEVNAME(sc), sge->sg_hdr,
2545			    sge->sg_hi_addr, sge->sg_lo_addr);
2546
2547			if ((dmap->dm_nsegs - i) > sc->sc_chain_len) {
2548				nce = &nsge[sc->sc_chain_len - 1];
2549				addr = ((u_int8_t *)nce - (u_int8_t *)nsge) / 4;
2550				addr = addr << 16 |
2551				    sizeof(struct mpii_sge) * sc->sc_chain_len;
2552			} else {
2553				nce = NULL;
2554				addr = sizeof(struct mpii_sge) *
2555				    (dmap->dm_nsegs - i);
2556			}
2557
2558			ce->sg_hdr = htole32(MPII_SGE_FL_TYPE_CHAIN |
2559			    MPII_SGE_FL_SIZE_64 | addr);
2560
2561			ce_dva = ccb->ccb_cmd_dva +
2562			    ((u_int8_t *)nsge - (u_int8_t *)mcb);
2563
2564			addr = (u_int32_t)(ce_dva >> 32);
2565			ce->sg_hi_addr = htole32(addr);
2566			addr = (u_int32_t)ce_dva;
2567			ce->sg_lo_addr = htole32(addr);
2568
2569			DNPRINTF(MPII_D_DMA, "%s:  ce: 0x%08x 0x%08x 0x%08x\n",
2570			    DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr,
2571			    ce->sg_lo_addr);
2572
2573			ce = nce;
2574		}
2575
2576		DNPRINTF(MPII_D_DMA, "%s:  %d: %" PRId64 " 0x%016" PRIx64 "\n",
2577		    DEVNAME(sc), i, (int64_t)dmap->dm_segs[i].ds_len,
2578		    (u_int64_t)dmap->dm_segs[i].ds_addr);
2579
2580		sge = nsge;
2581
2582		sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len);
2583		addr = (u_int32_t)((u_int64_t)dmap->dm_segs[i].ds_addr >> 32);
2584		sge->sg_hi_addr = htole32(addr);
2585		addr = (u_int32_t)dmap->dm_segs[i].ds_addr;
2586		sge->sg_lo_addr = htole32(addr);
2587
2588		DNPRINTF(MPII_D_DMA, "%s:  %d: 0x%08x 0x%08x 0x%08x\n",
2589		    DEVNAME(sc), i, sge->sg_hdr, sge->sg_hi_addr,
2590		    sge->sg_lo_addr);
2591
2592		nsge = sge + 1;
2593	}
2594
2595	/* terminate list */
2596	sge->sg_hdr |= htole32(MPII_SGE_FL_LAST | MPII_SGE_FL_EOB |
2597	    MPII_SGE_FL_EOL);
2598
2599	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
2600	    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD :
2601	    BUS_DMASYNC_PREWRITE);
2602
2603	return (0);
2604}
2605
2606static u_int32_t
2607mpii_read(struct mpii_softc *sc, bus_size_t r)
2608{
2609	u_int32_t			rv;
2610
2611	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
2612	    BUS_SPACE_BARRIER_READ);
2613	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
2614
2615	DNPRINTF(MPII_D_RW, "%s: mpii_read %#" PRIx64 " %#x\n", DEVNAME(sc),
2616	    (uint64_t)r, rv);
2617
2618	return (rv);
2619}
2620
2621static void
2622mpii_write(struct mpii_softc *sc, bus_size_t r, u_int32_t v)
2623{
2624	DNPRINTF(MPII_D_RW, "%s: mpii_write %#" PRIx64 " %#x\n", DEVNAME(sc),
2625	    (uint64_t)r, v);
2626
2627	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
2628	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
2629	    BUS_SPACE_BARRIER_WRITE);
2630}
2631
2632
2633static int
2634mpii_wait_eq(struct mpii_softc *sc, bus_size_t r, u_int32_t mask,
2635    u_int32_t target)
2636{
2637	int			i;
2638
2639	DNPRINTF(MPII_D_RW, "%s: mpii_wait_eq %#" PRIx64 " %#x %#x\n",
2640	    DEVNAME(sc), (uint64_t)r, mask, target);
2641
2642	for (i = 0; i < 15000; i++) {
2643		if ((mpii_read(sc, r) & mask) == target)
2644			return (0);
2645		delay(1000);
2646	}
2647
2648	return (1);
2649}
2650
2651static int
2652mpii_wait_ne(struct mpii_softc *sc, bus_size_t r, u_int32_t mask,
2653    u_int32_t target)
2654{
2655	int			i;
2656
2657	DNPRINTF(MPII_D_RW, "%s: mpii_wait_ne %#" PRIx64 " %#x %#x\n",
2658	    DEVNAME(sc), (uint64_t)r, mask, target);
2659
2660	for (i = 0; i < 15000; i++) {
2661		if ((mpii_read(sc, r) & mask) != target)
2662			return (0);
2663		delay(1000);
2664	}
2665
2666	return (1);
2667}
2668
2669
2670static int
2671mpii_init(struct mpii_softc *sc)
2672{
2673	u_int32_t		db;
2674	int			i;
2675
2676	/* spin until the ioc leaves the reset state */
2677	if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
2678	    MPII_DOORBELL_STATE_RESET) != 0) {
2679		DNPRINTF(MPII_D_MISC, "%s: mpii_init timeout waiting to leave "
2680		    "reset state\n", DEVNAME(sc));
2681		return (1);
2682	}
2683
2684	/* check current ownership */
2685	db = mpii_read_db(sc);
2686	if ((db & MPII_DOORBELL_WHOINIT) == MPII_DOORBELL_WHOINIT_PCIPEER) {
2687		DNPRINTF(MPII_D_MISC, "%s: mpii_init initialised by pci peer\n",
2688		    DEVNAME(sc));
2689		return (0);
2690	}
2691
2692	for (i = 0; i < 5; i++) {
2693		switch (db & MPII_DOORBELL_STATE) {
2694		case MPII_DOORBELL_STATE_READY:
2695			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is ready\n",
2696			    DEVNAME(sc));
2697			return (0);
2698
2699		case MPII_DOORBELL_STATE_OPER:
2700			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is oper\n",
2701			    DEVNAME(sc));
2702			if (sc->sc_ioc_event_replay)
2703				mpii_reset_soft(sc);
2704			else
2705				mpii_reset_hard(sc);
2706			break;
2707
2708		case MPII_DOORBELL_STATE_FAULT:
2709			DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is being "
2710			    "reset hard\n" , DEVNAME(sc));
2711			mpii_reset_hard(sc);
2712			break;
2713
2714		case MPII_DOORBELL_STATE_RESET:
2715			DNPRINTF(MPII_D_MISC, "%s: mpii_init waiting to come "
2716			    "out of reset\n", DEVNAME(sc));
2717			if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
2718			    MPII_DOORBELL_STATE_RESET) != 0)
2719				return (1);
2720			break;
2721		}
2722		db = mpii_read_db(sc);
2723	}
2724
2725	return (1);
2726}
2727
2728static int
2729mpii_reset_soft(struct mpii_softc *sc)
2730{
2731	DNPRINTF(MPII_D_MISC, "%s: mpii_reset_soft\n", DEVNAME(sc));
2732
2733	if (mpii_read_db(sc) & MPII_DOORBELL_INUSE) {
2734		return (1);
2735	}
2736
2737	mpii_write_db(sc,
2738	    MPII_DOORBELL_FUNCTION(MPII_FUNCTION_IOC_MESSAGE_UNIT_RESET));
2739
2740	/* XXX LSI waits 15 sec */
2741	if (mpii_wait_db_ack(sc) != 0)
2742		return (1);
2743
2744	/* XXX LSI waits 15 sec */
2745	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE,
2746	    MPII_DOORBELL_STATE_READY) != 0)
2747		return (1);
2748
2749	/* XXX wait for Sys2IOCDB bit to clear in HIS?? */
2750
2751	return (0);
2752}
2753
2754static int
2755mpii_reset_hard(struct mpii_softc *sc)
2756{
2757	u_int16_t		i;
2758
2759	DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard\n", DEVNAME(sc));
2760
2761	mpii_write_intr(sc, 0);
2762
2763	/* enable diagnostic register */
2764	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_FLUSH);
2765	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_1);
2766	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_2);
2767	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_3);
2768	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_4);
2769	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_5);
2770	mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_6);
2771
2772	delay(100);
2773
2774	if ((mpii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) {
2775		DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard failure to enable "
2776		    "diagnostic read/write\n", DEVNAME(sc));
2777		return(1);
2778	}
2779
2780	/* reset ioc */
2781	mpii_write(sc, MPII_HOSTDIAG, MPII_HOSTDIAG_RESET_ADAPTER);
2782
2783	/* 240 milliseconds */
2784	delay(240000);
2785
2786
2787	/* XXX this whole function should be more robust */
2788
2789	/* XXX  read the host diagnostic reg until reset adapter bit clears ? */
2790	for (i = 0; i < 30000; i++) {
2791		if ((mpii_read(sc, MPII_HOSTDIAG) &
2792		    MPII_HOSTDIAG_RESET_ADAPTER) == 0)
2793			break;
2794		delay(10000);
2795	}
2796
2797	/* disable diagnostic register */
2798	mpii_write(sc, MPII_WRITESEQ, 0xff);
2799
2800	/* XXX what else? */
2801
2802	DNPRINTF(MPII_D_MISC, "%s: done with mpii_reset_hard\n", DEVNAME(sc));
2803
2804	return(0);
2805}
2806
2807static int
2808mpii_handshake_send(struct mpii_softc *sc, void *buf, size_t dwords)
2809{
2810	u_int32_t		*query = buf;
2811	int			i;
2812
2813	/* make sure the doorbell is not in use. */
2814	if (mpii_read_db(sc) & MPII_DOORBELL_INUSE)
2815		return (1);
2816
2817	/* clear pending doorbell interrupts */
2818	if (mpii_read_intr(sc) & MPII_INTR_STATUS_IOC2SYSDB)
2819		mpii_write_intr(sc, 0);
2820
2821	/*
2822	 * first write the doorbell with the handshake function and the
2823	 * dword count.
2824	 */
2825	mpii_write_db(sc, MPII_DOORBELL_FUNCTION(MPII_FUNCTION_HANDSHAKE) |
2826	    MPII_DOORBELL_DWORDS(dwords));
2827
2828	/*
2829	 * the doorbell used bit will be set because a doorbell function has
2830	 * started. wait for the interrupt and then ack it.
2831	 */
2832	if (mpii_wait_db_int(sc) != 0)
2833		return (1);
2834	mpii_write_intr(sc, 0);
2835
2836	/* poll for the acknowledgement. */
2837	if (mpii_wait_db_ack(sc) != 0)
2838		return (1);
2839
2840	/* write the query through the doorbell. */
2841	for (i = 0; i < dwords; i++) {
2842		mpii_write_db(sc, htole32(query[i]));
2843		if (mpii_wait_db_ack(sc) != 0)
2844			return (1);
2845	}
2846
2847	return (0);
2848}
2849
2850static int
2851mpii_handshake_recv_dword(struct mpii_softc *sc, u_int32_t *dword)
2852{
2853	u_int16_t		*words = (u_int16_t *)dword;
2854	int			i;
2855
2856	for (i = 0; i < 2; i++) {
2857		if (mpii_wait_db_int(sc) != 0)
2858			return (1);
2859		words[i] = le16toh(mpii_read_db(sc) & MPII_DOORBELL_DATA_MASK);
2860		mpii_write_intr(sc, 0);
2861	}
2862
2863	return (0);
2864}
2865
2866static int
2867mpii_handshake_recv(struct mpii_softc *sc, void *buf, size_t dwords)
2868{
2869	struct mpii_msg_reply	*reply = buf;
2870	u_int32_t		*dbuf = buf, dummy;
2871	int			i;
2872
2873	/* get the first dword so we can read the length out of the header. */
2874	if (mpii_handshake_recv_dword(sc, &dbuf[0]) != 0)
2875		return (1);
2876
2877	DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dwords: %zd reply: %d\n",
2878	    DEVNAME(sc), dwords, reply->msg_length);
2879
2880	/*
2881	 * the total length, in dwords, is in the message length field of the
2882	 * reply header.
2883	 */
2884	for (i = 1; i < MIN(dwords, reply->msg_length); i++) {
2885		if (mpii_handshake_recv_dword(sc, &dbuf[i]) != 0)
2886			return (1);
2887	}
2888
2889	/* if there's extra stuff to come off the ioc, discard it */
2890	while (i++ < reply->msg_length) {
2891		if (mpii_handshake_recv_dword(sc, &dummy) != 0)
2892			return (1);
2893		DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dummy read: "
2894		    "0x%08x\n", DEVNAME(sc), dummy);
2895	}
2896
2897	/* wait for the doorbell used bit to be reset and clear the intr */
2898	if (mpii_wait_db_int(sc) != 0)
2899		return (1);
2900
2901	if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_INUSE, 0) != 0)
2902		return (1);
2903
2904	mpii_write_intr(sc, 0);
2905
2906	return (0);
2907}
2908
2909static void
2910mpii_empty_done(struct mpii_ccb *ccb)
2911{
2912	/* nothing to do */
2913}
2914
2915static int
2916mpii_iocfacts(struct mpii_softc *sc)
2917{
2918	struct mpii_msg_iocfacts_request	ifq;
2919	struct mpii_msg_iocfacts_reply		ifp;
2920
2921	DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts\n", DEVNAME(sc));
2922
2923	bzero(&ifq, sizeof(ifq));
2924	bzero(&ifp, sizeof(ifp));
2925
2926	ifq.function = MPII_FUNCTION_IOC_FACTS;
2927
2928	if (mpii_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) {
2929		DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts send failed\n",
2930		    DEVNAME(sc));
2931		return (1);
2932	}
2933
2934	if (mpii_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) {
2935		DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts recv failed\n",
2936		    DEVNAME(sc));
2937		return (1);
2938	}
2939
2940	DNPRINTF(MPII_D_MISC, "%s:  func: 0x%02x length: %d msgver: %d.%d\n",
2941	    DEVNAME(sc), ifp.function, ifp.msg_length,
2942	    ifp.msg_version_maj, ifp.msg_version_min);
2943	DNPRINTF(MPII_D_MISC, "%s:  msgflags: 0x%02x iocnumber: 0x%02x "
2944	    "headerver: %d.%d\n", DEVNAME(sc), ifp.msg_flags,
2945	    ifp.ioc_number, ifp.header_version_unit,
2946	    ifp.header_version_dev);
2947	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
2948	    ifp.vp_id, ifp.vf_id);
2949	DNPRINTF(MPII_D_MISC, "%s:  iocstatus: 0x%04x ioexceptions: 0x%04x\n",
2950	    DEVNAME(sc), le16toh(ifp.ioc_status),
2951	    le16toh(ifp.ioc_exceptions));
2952	DNPRINTF(MPII_D_MISC, "%s:  iocloginfo: 0x%08x\n", DEVNAME(sc),
2953	    le32toh(ifp.ioc_loginfo));
2954	DNPRINTF(MPII_D_MISC, "%s:  numberofports: 0x%02x whoinit: 0x%02x "
2955	    "maxchaindepth: %d\n", DEVNAME(sc), ifp.number_of_ports,
2956	    ifp.whoinit, ifp.max_chain_depth);
2957	DNPRINTF(MPII_D_MISC, "%s:  productid: 0x%04x requestcredit: 0x%04x\n",
2958	    DEVNAME(sc), le16toh(ifp.product_id), le16toh(ifp.request_credit));
2959	DNPRINTF(MPII_D_MISC, "%s:  ioc_capabilities: 0x%08x\n", DEVNAME(sc),
2960	    le32toh(ifp.ioc_capabilities));
2961	DNPRINTF(MPII_D_MISC, "%s:  fw_version: %d.%d fw_version_unit: 0x%02x "
2962	    "fw_version_dev: 0x%02x\n", DEVNAME(sc),
2963	    ifp.fw_version_maj, ifp.fw_version_min,
2964	    ifp.fw_version_unit, ifp.fw_version_dev);
2965	DNPRINTF(MPII_D_MISC, "%s:  iocrequestframesize: 0x%04x\n",
2966	    DEVNAME(sc), le16toh(ifp.ioc_request_frame_size));
2967	DNPRINTF(MPII_D_MISC, "%s:  maxtargets: 0x%04x "
2968	    "maxinitiators: 0x%04x\n", DEVNAME(sc),
2969	    le16toh(ifp.max_targets), le16toh(ifp.max_initiators));
2970	DNPRINTF(MPII_D_MISC, "%s:  maxenclosures: 0x%04x "
2971	    "maxsasexpanders: 0x%04x\n", DEVNAME(sc),
2972	    le16toh(ifp.max_enclosures), le16toh(ifp.max_sas_expanders));
2973	DNPRINTF(MPII_D_MISC, "%s:  highprioritycredit: 0x%04x "
2974	    "protocolflags: 0x%02x\n", DEVNAME(sc),
2975	    le16toh(ifp.high_priority_credit), le16toh(ifp.protocol_flags));
2976	DNPRINTF(MPII_D_MISC, "%s:  maxvolumes: 0x%02x replyframesize: 0x%02x "
2977	    "mrdpqd: 0x%04x\n", DEVNAME(sc), ifp.max_volumes,
2978	    ifp.reply_frame_size,
2979	    le16toh(ifp.max_reply_descriptor_post_queue_depth));
2980	DNPRINTF(MPII_D_MISC, "%s:  maxpersistententries: 0x%04x "
2981	    "maxdevhandle: 0x%02x\n", DEVNAME(sc),
2982	    le16toh(ifp.max_persistent_entries), le16toh(ifp.max_dev_handle));
2983
2984	sc->sc_maxchdepth = ifp.max_chain_depth;
2985	sc->sc_ioc_number = ifp.ioc_number;
2986	sc->sc_vf_id = ifp.vf_id;
2987
2988	sc->sc_num_ports = ifp.number_of_ports;
2989	sc->sc_ioc_event_replay = (le32toh(ifp.ioc_capabilities) &
2990	    MPII_IOCFACTS_CAPABILITY_EVENT_REPLAY) ? 1 : 0;
2991	sc->sc_max_enclosures = le16toh(ifp.max_enclosures);
2992	sc->sc_max_expanders = le16toh(ifp.max_sas_expanders);
2993	sc->sc_max_volumes = ifp.max_volumes;
2994	sc->sc_max_devices = ifp.max_volumes + le16toh(ifp.max_targets);
2995	sc->sc_num_channels = 1;
2996
2997	if (ISSET(le32toh(ifp.ioc_capabilities),
2998	    MPII_IOCFACTS_CAPABILITY_INTEGRATED_RAID))
2999		SET(sc->sc_flags, MPII_F_RAID);
3000
3001	sc->sc_request_depth = MIN(le16toh(ifp.request_credit),
3002	    MPII_MAX_REQUEST_CREDIT);
3003
3004	/* should not be multiple of 16 */
3005	sc->sc_num_reply_frames = sc->sc_request_depth + 32;
3006	if (!(sc->sc_num_reply_frames % 16))
3007		sc->sc_num_reply_frames--;
3008
3009	/* must be multiple of 16 */
3010	sc->sc_reply_free_qdepth = sc->sc_num_reply_frames +
3011	    (16 - (sc->sc_num_reply_frames % 16));
3012	sc->sc_reply_post_qdepth = ((sc->sc_request_depth +
3013	    sc->sc_num_reply_frames + 1 + 15) / 16) * 16;
3014
3015	if (sc->sc_reply_post_qdepth >
3016	    ifp.max_reply_descriptor_post_queue_depth)
3017		sc->sc_reply_post_qdepth =
3018		    ifp.max_reply_descriptor_post_queue_depth;
3019
3020	DNPRINTF(MPII_D_MISC, "%s: sc_request_depth: %d "
3021	    "sc_num_reply_frames: %d sc_reply_free_qdepth: %d "
3022	    "sc_reply_post_qdepth: %d\n", DEVNAME(sc), sc->sc_request_depth,
3023	    sc->sc_num_reply_frames, sc->sc_reply_free_qdepth,
3024	    sc->sc_reply_post_qdepth);
3025
3026	/*
3027	 * you can fit sg elements on the end of the io cmd if they fit in the
3028	 * request frame size.
3029	 */
3030
3031	sc->sc_first_sgl_len = ((le16toh(ifp.ioc_request_frame_size) * 4) -
3032	    sizeof(struct mpii_msg_scsi_io)) / sizeof(struct mpii_sge);
3033	DNPRINTF(MPII_D_MISC, "%s:   first sgl len: %d\n", DEVNAME(sc),
3034	    sc->sc_first_sgl_len);
3035
3036	sc->sc_chain_len = (le16toh(ifp.ioc_request_frame_size) * 4) /
3037	    sizeof(struct mpii_sge);
3038	DNPRINTF(MPII_D_MISC, "%s:   chain len: %d\n", DEVNAME(sc),
3039	    sc->sc_chain_len);
3040
3041	/* the sgl tailing the io cmd loses an entry to the chain element. */
3042	sc->sc_max_sgl_len = MPII_MAX_SGL - 1;
3043	/* the sgl chains lose an entry for each chain element */
3044	sc->sc_max_sgl_len -= (MPII_MAX_SGL - sc->sc_first_sgl_len) /
3045	    sc->sc_chain_len;
3046	DNPRINTF(MPII_D_MISC, "%s:   max sgl len: %d\n", DEVNAME(sc),
3047	    sc->sc_max_sgl_len);
3048
3049	/* XXX we're ignoring the max chain depth */
3050
3051	return(0);
3052
3053}
3054
3055static int
3056mpii_iocinit(struct mpii_softc *sc)
3057{
3058	struct mpii_msg_iocinit_request		iiq;
3059	struct mpii_msg_iocinit_reply		iip;
3060	u_int32_t				hi_addr;
3061
3062	DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit\n", DEVNAME(sc));
3063
3064	bzero(&iiq, sizeof(iiq));
3065	bzero(&iip, sizeof(iip));
3066
3067	iiq.function = MPII_FUNCTION_IOC_INIT;
3068	iiq.whoinit = MPII_WHOINIT_HOST_DRIVER;
3069
3070	/* XXX JPG do something about vf_id */
3071	iiq.vf_id = 0;
3072
3073	iiq.msg_version_maj = 0x02;
3074	iiq.msg_version_min = 0x00;
3075
3076	/* XXX JPG ensure compliance with some level and hard-code? */
3077	iiq.hdr_version_unit = 0x00;
3078	iiq.hdr_version_dev = 0x00;
3079
3080	iiq.system_request_frame_size = htole16(MPII_REQUEST_SIZE / 4);
3081
3082	iiq.reply_descriptor_post_queue_depth =
3083	    htole16(sc->sc_reply_post_qdepth);
3084
3085	iiq.reply_free_queue_depth = htole16(sc->sc_reply_free_qdepth);
3086
3087	hi_addr = (u_int32_t)((u_int64_t)MPII_DMA_DVA(sc->sc_requests) >> 32);
3088	iiq.sense_buffer_address_high = htole32(hi_addr);
3089
3090	hi_addr = (u_int32_t)
3091	    ((u_int64_t)MPII_DMA_DVA(sc->sc_replies) >> 32);
3092	iiq.system_reply_address_high = htole32(hi_addr);
3093
3094	iiq.system_request_frame_base_address =
3095	    (u_int64_t)MPII_DMA_DVA(sc->sc_requests);
3096
3097	iiq.reply_descriptor_post_queue_address =
3098	    (u_int64_t)MPII_DMA_DVA(sc->sc_reply_postq);
3099
3100	iiq.reply_free_queue_address =
3101	    (u_int64_t)MPII_DMA_DVA(sc->sc_reply_freeq);
3102
3103	if (mpii_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) {
3104		DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit send failed\n",
3105		    DEVNAME(sc));
3106		return (1);
3107	}
3108
3109	if (mpii_handshake_recv(sc, &iip, dwordsof(iip)) != 0) {
3110		DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit recv failed\n",
3111		    DEVNAME(sc));
3112		return (1);
3113	}
3114
3115	DNPRINTF(MPII_D_MISC, "%s:  function: 0x%02x msg_length: %d "
3116	    "whoinit: 0x%02x\n", DEVNAME(sc), iip.function,
3117	    iip.msg_length, iip.whoinit);
3118	DNPRINTF(MPII_D_MISC, "%s:  msg_flags: 0x%02x\n", DEVNAME(sc),
3119	    iip.msg_flags);
3120	DNPRINTF(MPII_D_MISC, "%s:  vf_id: 0x%02x vp_id: 0x%02x\n", DEVNAME(sc),
3121	    iip.vf_id, iip.vp_id);
3122	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
3123	    le16toh(iip.ioc_status));
3124	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
3125	    le32toh(iip.ioc_loginfo));
3126
3127	if ((iip.ioc_status != MPII_IOCSTATUS_SUCCESS) || (iip.ioc_loginfo))
3128		return (1);
3129
3130	return (0);
3131}
3132
3133static void
3134mpii_push_reply(struct mpii_softc *sc, struct mpii_rcb *rcb)
3135{
3136	u_int32_t		*rfp;
3137
3138	if (rcb == NULL)
3139		return;
3140
3141	rfp = MPII_DMA_KVA(sc->sc_reply_freeq);
3142	rfp[sc->sc_reply_free_host_index] = rcb->rcb_reply_dva;
3143
3144	sc->sc_reply_free_host_index = (sc->sc_reply_free_host_index + 1) %
3145	    sc->sc_reply_free_qdepth;
3146
3147	mpii_write_reply_free(sc, sc->sc_reply_free_host_index);
3148}
3149
3150static int
3151mpii_portfacts(struct mpii_softc *sc)
3152{
3153	struct mpii_msg_portfacts_request	*pfq;
3154	struct mpii_msg_portfacts_reply		*pfp;
3155	struct mpii_ccb				*ccb;
3156	int					rv = 1;
3157
3158	DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts\n", DEVNAME(sc));
3159
3160	ccb = mpii_get_ccb(sc, 0);
3161	if (ccb == NULL) {
3162		DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts mpii_get_ccb fail\n",
3163		    DEVNAME(sc));
3164		return (rv);
3165	}
3166
3167	ccb->ccb_done = mpii_empty_done;
3168	pfq = ccb->ccb_cmd;
3169
3170	bzero(pfq, sizeof(*pfq));
3171
3172	pfq->function = MPII_FUNCTION_PORT_FACTS;
3173	pfq->chain_offset = 0;
3174	pfq->msg_flags = 0;
3175	pfq->port_number = 0;
3176	pfq->vp_id = 0;
3177	pfq->vf_id = 0;
3178
3179	if (mpii_poll(sc, ccb) != 0) {
3180		DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts poll\n",
3181		    DEVNAME(sc));
3182		goto err;
3183	}
3184
3185	if (ccb->ccb_rcb == NULL) {
3186		DNPRINTF(MPII_D_MISC, "%s: empty portfacts reply\n",
3187		    DEVNAME(sc));
3188		goto err;
3189	}
3190
3191	pfp = ccb->ccb_rcb->rcb_reply;
3192	DNPRINTF(MPII_D_MISC, "%s   pfp: %p\n", DEVNAME(sc), pfp);
3193
3194	DNPRINTF(MPII_D_MISC, "%s:  function: 0x%02x msg_length: %d\n",
3195	    DEVNAME(sc), pfp->function, pfp->msg_length);
3196	DNPRINTF(MPII_D_MISC, "%s:  msg_flags: 0x%02x port_number: %d\n",
3197	    DEVNAME(sc), pfp->msg_flags, pfp->port_number);
3198	DNPRINTF(MPII_D_MISC, "%s:  vf_id: 0x%02x vp_id: 0x%02x\n",
3199	    DEVNAME(sc), pfp->vf_id, pfp->vp_id);
3200	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
3201	    le16toh(pfp->ioc_status));
3202	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
3203	    le32toh(pfp->ioc_loginfo));
3204	DNPRINTF(MPII_D_MISC, "%s:  port_type: 0x%02x\n", DEVNAME(sc),
3205	    pfp->port_type);
3206	DNPRINTF(MPII_D_MISC, "%s:  max_posted_cmd_buffers: %d\n", DEVNAME(sc),
3207	    le16toh(pfp->max_posted_cmd_buffers));
3208
3209	sc->sc_porttype = pfp->port_type;
3210
3211	mpii_push_reply(sc, ccb->ccb_rcb);
3212	rv = 0;
3213err:
3214	mpii_put_ccb(sc, ccb);
3215
3216	return (rv);
3217}
3218
3219static void
3220mpii_eventack(struct work *wk, void *cookie)
3221{
3222	struct mpii_softc			*sc = cookie;
3223	struct mpii_ccb				*ccb;
3224	struct mpii_rcb				*rcb = (void *)wk;
3225	struct mpii_msg_event_reply		*enp;
3226	struct mpii_msg_eventack_request	*eaq;
3227
3228	ccb = mpii_get_ccb(sc, 0);
3229
3230	enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
3231
3232	ccb->ccb_done = mpii_eventack_done;
3233	eaq = ccb->ccb_cmd;
3234
3235	eaq->function = MPII_FUNCTION_EVENT_ACK;
3236
3237	eaq->event = enp->event;
3238	eaq->event_context = enp->event_context;
3239
3240	mpii_push_reply(sc, rcb);
3241
3242	mpii_start(sc, ccb);
3243
3244}
3245
3246static void
3247mpii_eventack_done(struct mpii_ccb *ccb)
3248{
3249	struct mpii_softc			*sc = ccb->ccb_sc;
3250
3251	DNPRINTF(MPII_D_EVT, "%s: event ack done\n", DEVNAME(sc));
3252
3253	mpii_push_reply(sc, ccb->ccb_rcb);
3254	mpii_put_ccb(sc, ccb);
3255}
3256
3257static int
3258mpii_portenable(struct mpii_softc *sc)
3259{
3260	struct mpii_msg_portenable_request	*peq;
3261	struct mpii_msg_portenable_repy		*pep;
3262	struct mpii_ccb				*ccb;
3263
3264	DNPRINTF(MPII_D_MISC, "%s: mpii_portenable\n", DEVNAME(sc));
3265
3266	ccb = mpii_get_ccb(sc, 0);
3267	if (ccb == NULL) {
3268		DNPRINTF(MPII_D_MISC, "%s: mpii_portenable ccb_get\n",
3269		    DEVNAME(sc));
3270		return (1);
3271	}
3272
3273	ccb->ccb_done = mpii_empty_done;
3274	peq = ccb->ccb_cmd;
3275
3276	peq->function = MPII_FUNCTION_PORT_ENABLE;
3277	peq->vf_id = sc->sc_vf_id;
3278
3279	if (mpii_poll(sc, ccb) != 0) {
3280		DNPRINTF(MPII_D_MISC, "%s: mpii_portenable poll\n",
3281		    DEVNAME(sc));
3282		return (1);
3283	}
3284
3285	if (ccb->ccb_rcb == NULL) {
3286		DNPRINTF(MPII_D_MISC, "%s: empty portenable reply\n",
3287		    DEVNAME(sc));
3288		return (1);
3289	}
3290	pep = ccb->ccb_rcb->rcb_reply;
3291
3292	mpii_push_reply(sc, ccb->ccb_rcb);
3293	mpii_put_ccb(sc, ccb);
3294
3295	return (0);
3296}
3297
3298static int
3299mpii_cfg_coalescing(struct mpii_softc *sc)
3300{
3301	struct mpii_cfg_hdr		hdr;
3302	struct mpii_cfg_ioc_pg1		pg;
3303
3304	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_IOC, 1, 0,
3305	    &hdr) != 0) {
3306		DNPRINTF(MPII_D_MISC, "%s: unable to fetch IOC page 1 "
3307		    "header\n", DEVNAME(sc));
3308		return (1);
3309	}
3310
3311	if (mpii_cfg_page(sc, 0, &hdr, 1, &pg, sizeof(pg)) != 0) {
3312		DNPRINTF(MPII_D_MISC, "%s: unable to fetch IOC page 1\n"
3313		    "page 1\n", DEVNAME(sc));
3314		return (1);
3315	}
3316
3317	DNPRINTF(MPII_D_MISC, "%s: IOC page 1\n", DEVNAME(sc));
3318	DNPRINTF(MPII_D_MISC, "%s:  flags: 0x08%x\n", DEVNAME(sc),
3319	    le32toh(pg.flags));
3320	DNPRINTF(MPII_D_MISC, "%s:  coalescing_timeout: %d\n", DEVNAME(sc),
3321	    le32toh(pg.coalescing_timeout));
3322	DNPRINTF(MPII_D_MISC, "%s:  coalescing_depth: %d pci_slot_num: %d\n",
3323	    DEVNAME(sc), pg.coalescing_timeout, pg.pci_slot_num);
3324
3325	if (!ISSET(le32toh(pg.flags), MPII_CFG_IOC_1_REPLY_COALESCING))
3326		return (0);
3327
3328	CLR(pg.flags, htole32(MPII_CFG_IOC_1_REPLY_COALESCING));
3329	if (mpii_cfg_page(sc, 0, &hdr, 0, &pg, sizeof(pg)) != 0) {
3330		DNPRINTF(MPII_D_MISC, "%s: unable to clear coalescing\n",
3331		    DEVNAME(sc));
3332		return (1);
3333	}
3334
3335	return (0);
3336}
3337
3338#define MPII_EVENT_MASKALL(enq)		do {			\
3339		enq->event_masks[0] = 0xffffffff;		\
3340		enq->event_masks[1] = 0xffffffff;		\
3341		enq->event_masks[2] = 0xffffffff;		\
3342		enq->event_masks[3] = 0xffffffff;		\
3343	} while (0)
3344
3345#define MPII_EVENT_UNMASK(enq, evt)	do {			\
3346		enq->event_masks[evt / 32] &=			\
3347		    htole32(~(1 << (evt % 32)));		\
3348	} while (0)
3349
3350static int
3351mpii_eventnotify(struct mpii_softc *sc)
3352{
3353	struct mpii_msg_event_request		*enq;
3354	struct mpii_ccb				*ccb;
3355
3356	ccb = mpii_get_ccb(sc, 0);
3357	if (ccb == NULL) {
3358		DNPRINTF(MPII_D_MISC, "%s: mpii_eventnotify ccb_get\n",
3359		    DEVNAME(sc));
3360		return (1);
3361	}
3362
3363	ccb->ccb_done = mpii_eventnotify_done;
3364	enq = ccb->ccb_cmd;
3365
3366	enq->function = MPII_FUNCTION_EVENT_NOTIFICATION;
3367
3368	/*
3369	 * Enable reporting of the following events:
3370	 *
3371	 * MPII_EVENT_SAS_DISCOVERY
3372	 * MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST
3373	 * MPII_EVENT_SAS_DEVICE_STATUS_CHANGE
3374	 * MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE
3375	 * MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST
3376	 * MPII_EVENT_IR_VOLUME
3377	 * MPII_EVENT_IR_PHYSICAL_DISK
3378	 * MPII_EVENT_IR_OPERATION_STATUS
3379	 */
3380
3381	MPII_EVENT_MASKALL(enq);
3382	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DISCOVERY);
3383	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST);
3384	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DEVICE_STATUS_CHANGE);
3385	MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE);
3386	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST);
3387	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_VOLUME);
3388	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_PHYSICAL_DISK);
3389	MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_OPERATION_STATUS);
3390
3391	mpii_start(sc, ccb);
3392
3393	return (0);
3394}
3395
3396static void
3397mpii_eventnotify_done(struct mpii_ccb *ccb)
3398{
3399	struct mpii_softc			*sc = ccb->ccb_sc;
3400	struct mpii_rcb				*rcb = ccb->ccb_rcb;
3401
3402	DNPRINTF(MPII_D_EVT, "%s: mpii_eventnotify_done\n", DEVNAME(sc));
3403
3404	mpii_put_ccb(sc, ccb);
3405	mpii_event_process(sc, rcb);
3406}
3407
3408static void
3409mpii_event_raid(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
3410{
3411	struct mpii_evt_ir_cfg_change_list	*ccl;
3412	struct mpii_evt_ir_cfg_element		*ce;
3413	struct mpii_device			*dev;
3414	u_int16_t				type;
3415	int					i;
3416
3417	ccl = (struct mpii_evt_ir_cfg_change_list *)(enp + 1);
3418
3419	if (ccl->num_elements == 0)
3420		return;
3421	if (ISSET(le32toh(ccl->flags), MPII_EVT_IR_CFG_CHANGE_LIST_FOREIGN))
3422		/* bail on foreign configurations */
3423		return;
3424
3425	ce = (struct mpii_evt_ir_cfg_element *)(ccl + 1);
3426
3427	for (i = 0; i < ccl->num_elements; i++, ce++) {
3428		type = (le16toh(ce->element_flags) &
3429		    MPII_EVT_IR_CFG_ELEMENT_TYPE_MASK);
3430
3431		switch (type) {
3432		case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME:
3433			switch (ce->reason_code) {
3434			case MPII_EVT_IR_CFG_ELEMENT_RC_ADDED:
3435			case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED:
3436				if (mpii_find_dev(sc,
3437				    le16toh(ce->vol_dev_handle))) {
3438					printf("%s: device %#x is already "
3439					    "configured\n", DEVNAME(sc),
3440					    le16toh(ce->vol_dev_handle));
3441					break;
3442				}
3443				dev = malloc(sizeof(*dev), M_DEVBUF,
3444				    M_NOWAIT | M_ZERO);
3445				if (!dev) {
3446					printf("%s: failed to allocate a "
3447				    	    "device structure\n", DEVNAME(sc));
3448					break;
3449				}
3450				SET(dev->flags, MPII_DF_VOLUME);
3451				dev->slot = sc->sc_vd_id_low;
3452				dev->dev_handle = le16toh(ce->vol_dev_handle);
3453				if (mpii_insert_dev(sc, dev)) {
3454					free(dev, M_DEVBUF);
3455					break;
3456				}
3457				mpii_cache_enable(sc, dev);
3458				sc->sc_vd_count++;
3459				break;
3460			case MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED:
3461			case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED:
3462				if (!(dev = mpii_find_dev(sc,
3463				    le16toh(ce->vol_dev_handle))))
3464					break;
3465				mpii_remove_dev(sc, dev);
3466				sc->sc_vd_count--;
3467				break;
3468			}
3469			break;
3470		case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME_DISK:
3471			if (ce->reason_code ==
3472			    MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED ||
3473			    ce->reason_code ==
3474			    MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) {
3475				/* there should be an underlying sas drive */
3476				if (!(dev = mpii_find_dev(sc,
3477				    le16toh(ce->phys_disk_dev_handle))))
3478					break;
3479				/* promoted from a hot spare? */
3480				CLR(dev->flags, MPII_DF_HOT_SPARE);
3481				SET(dev->flags, MPII_DF_VOLUME_DISK |
3482				    MPII_DF_HIDDEN);
3483			}
3484			break;
3485		case MPII_EVT_IR_CFG_ELEMENT_TYPE_HOT_SPARE:
3486			if (ce->reason_code ==
3487			    MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) {
3488				/* there should be an underlying sas drive */
3489				if (!(dev = mpii_find_dev(sc,
3490				    le16toh(ce->phys_disk_dev_handle))))
3491					break;
3492				SET(dev->flags, MPII_DF_HOT_SPARE |
3493				    MPII_DF_HIDDEN);
3494			}
3495			break;
3496		}
3497	}
3498}
3499
3500static void
3501mpii_event_sas(struct mpii_softc *sc, struct mpii_msg_event_reply *enp)
3502{
3503	struct mpii_evt_sas_tcl		*tcl;
3504	struct mpii_evt_phy_entry	*pe;
3505	struct mpii_device		*dev;
3506	int				i;
3507
3508	tcl = (struct mpii_evt_sas_tcl *)(enp + 1);
3509
3510	if (tcl->num_entries == 0)
3511		return;
3512
3513	pe = (struct mpii_evt_phy_entry *)(tcl + 1);
3514
3515	for (i = 0; i < tcl->num_entries; i++, pe++) {
3516		switch (pe->phy_status & MPII_EVENT_SAS_TOPO_PS_RC_MASK) {
3517		case MPII_EVENT_SAS_TOPO_PS_RC_ADDED:
3518			if (mpii_find_dev(sc, le16toh(pe->dev_handle))) {
3519				printf("%s: device %#x is already "
3520				    "configured\n", DEVNAME(sc),
3521				    le16toh(pe->dev_handle));
3522				break;
3523			}
3524			dev = malloc(sizeof(*dev), M_DEVBUF, M_NOWAIT | M_ZERO);
3525			if (!dev) {
3526				printf("%s: failed to allocate a "
3527				    "device structure\n", DEVNAME(sc));
3528				break;
3529			}
3530			dev->slot = sc->sc_pd_id_start + tcl->start_phy_num + i;
3531			dev->dev_handle = le16toh(pe->dev_handle);
3532			dev->phy_num = tcl->start_phy_num + i;
3533			if (tcl->enclosure_handle)
3534				dev->physical_port = tcl->physical_port;
3535			dev->enclosure = le16toh(tcl->enclosure_handle);
3536			dev->expander = le16toh(tcl->expander_handle);
3537			if (mpii_insert_dev(sc, dev)) {
3538				free(dev, M_DEVBUF);
3539				break;
3540			}
3541			break;
3542		case MPII_EVENT_SAS_TOPO_PS_RC_MISSING:
3543			if (!(dev = mpii_find_dev(sc,
3544			    le16toh(pe->dev_handle))))
3545				break;
3546			mpii_remove_dev(sc, dev);
3547#if 0
3548			if (sc->sc_scsibus) {
3549				SET(dev->flags, MPII_DF_DETACH);
3550				scsi_activate(sc->sc_scsibus, dev->slot, -1,
3551				    DVACT_DEACTIVATE);
3552				if (scsi_task(mpii_event_defer, sc,
3553				    dev, 0) != 0)
3554					printf("%s: unable to run device "
3555					    "detachment routine\n",
3556					    DEVNAME(sc));
3557			}
3558#else
3559			mpii_event_defer(sc, dev);
3560#endif /* XXX */
3561			break;
3562		}
3563	}
3564}
3565
3566static void
3567mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb)
3568{
3569	struct mpii_msg_event_reply		*enp;
3570
3571	enp = (struct mpii_msg_event_reply *)rcb->rcb_reply;
3572
3573	DNPRINTF(MPII_D_EVT, "%s: mpii_event_process: %#x\n", DEVNAME(sc),
3574	    le32toh(enp->event));
3575
3576	switch (le32toh(enp->event)) {
3577	case MPII_EVENT_EVENT_CHANGE:
3578		/* should be properly ignored */
3579		break;
3580	case MPII_EVENT_SAS_DISCOVERY: {
3581		struct mpii_evt_sas_discovery	*esd =
3582		    (struct mpii_evt_sas_discovery *)(enp + 1);
3583
3584		if (esd->reason_code ==
3585		    MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED &&
3586		    esd->discovery_status != 0)
3587			printf("%s: sas discovery completed with status %#x\n",
3588			    DEVNAME(sc), esd->discovery_status);
3589		}
3590		break;
3591	case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST:
3592		mpii_event_sas(sc, enp);
3593		break;
3594	case MPII_EVENT_SAS_DEVICE_STATUS_CHANGE:
3595		break;
3596	case MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE:
3597		break;
3598	case MPII_EVENT_IR_VOLUME: {
3599		struct mpii_evt_ir_volume	*evd =
3600		    (struct mpii_evt_ir_volume *)(enp + 1);
3601		struct mpii_device		*dev;
3602#if NBIO > 0
3603		const char *vol_states[] = {
3604			BIOC_SVINVALID_S,
3605			BIOC_SVOFFLINE_S,
3606			BIOC_SVBUILDING_S,
3607			BIOC_SVONLINE_S,
3608			BIOC_SVDEGRADED_S,
3609			BIOC_SVONLINE_S,
3610		};
3611#endif
3612
3613		if (cold)
3614			break;
3615		if (!(dev = mpii_find_dev(sc, le16toh(evd->vol_dev_handle))))
3616			break;
3617#if NBIO > 0
3618		if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATE_CHANGED)
3619			printf("%s: volume %d state changed from %s to %s\n",
3620			    DEVNAME(sc), dev->slot - sc->sc_vd_id_low,
3621			    vol_states[evd->prev_value],
3622			    vol_states[evd->new_value]);
3623#endif
3624		if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATUS_CHANGED &&
3625		    ISSET(evd->new_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC) &&
3626		    !ISSET(evd->prev_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC))
3627			printf("%s: started resync on a volume %d\n",
3628			    DEVNAME(sc), dev->slot - sc->sc_vd_id_low);
3629		}
3630		break;
3631	case MPII_EVENT_IR_PHYSICAL_DISK:
3632		break;
3633	case MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST:
3634		mpii_event_raid(sc, enp);
3635		break;
3636	case MPII_EVENT_IR_OPERATION_STATUS: {
3637		struct mpii_evt_ir_status	*evs =
3638		    (struct mpii_evt_ir_status *)(enp + 1);
3639		struct mpii_device		*dev;
3640
3641		if (!(dev = mpii_find_dev(sc, le16toh(evs->vol_dev_handle))))
3642			break;
3643		if (evs->operation == MPII_EVENT_IR_RAIDOP_RESYNC)
3644			dev->percent = evs->percent;
3645		break;
3646		}
3647	default:
3648		DNPRINTF(MPII_D_EVT, "%s:  unhandled event 0x%02x\n",
3649		    DEVNAME(sc), le32toh(enp->event));
3650	}
3651
3652	if (enp->ack_required)
3653		workqueue_enqueue(sc->sc_ssb_evt_ackwk, &rcb->u.rcb_wk, NULL);
3654	else
3655		mpii_push_reply(sc, rcb);
3656}
3657
3658static void
3659mpii_event_defer(void *xsc, void *arg)
3660{
3661	struct mpii_softc	*sc = xsc;
3662	struct mpii_device	*dev = arg;
3663
3664	if (ISSET(dev->flags, MPII_DF_DETACH)) {
3665		mpii_sas_remove_device(sc, dev->dev_handle);
3666#if 0
3667		if (!ISSET(dev->flags, MPII_DF_HIDDEN)) {
3668			scsi_detach_target(sc->sc_scsibus, dev->slot,
3669			    DETACH_FORCE);
3670		}
3671#endif /* XXX */
3672		free(dev, M_DEVBUF);
3673
3674	} else if (ISSET(dev->flags, MPII_DF_ATTACH)) {
3675		CLR(dev->flags, MPII_DF_ATTACH);
3676#if 0
3677		if (!ISSET(dev->flags, MPII_DF_HIDDEN))
3678			scsi_probe_target(sc->sc_scsibus, dev->slot);
3679#endif /* XXX */
3680	}
3681}
3682
3683static void
3684mpii_sas_remove_device(struct mpii_softc *sc, u_int16_t handle)
3685{
3686 	struct mpii_msg_scsi_task_request	*stq;
3687	struct mpii_msg_sas_oper_request	*soq;
3688	struct mpii_ccb				*ccb;
3689
3690	ccb = mpii_get_ccb(sc, 0);
3691	if (ccb == NULL)
3692		return;
3693
3694	stq = ccb->ccb_cmd;
3695	stq->function = MPII_FUNCTION_SCSI_TASK_MGMT;
3696	stq->task_type = MPII_SCSI_TASK_TARGET_RESET;
3697	stq->dev_handle = htole16(handle);
3698
3699	ccb->ccb_done = mpii_empty_done;
3700	mpii_wait(sc, ccb);
3701
3702	if (ccb->ccb_rcb != NULL)
3703		mpii_push_reply(sc, ccb->ccb_rcb);
3704
3705	/* reuse a ccb */
3706	ccb->ccb_state = MPII_CCB_READY;
3707	ccb->ccb_rcb = NULL;
3708
3709	soq = ccb->ccb_cmd;
3710	bzero(soq, sizeof(*soq));
3711	soq->function = MPII_FUNCTION_SAS_IO_UNIT_CONTROL;
3712	soq->operation = MPII_SAS_OP_REMOVE_DEVICE;
3713	soq->dev_handle = htole16(handle);
3714
3715	ccb->ccb_done = mpii_empty_done;
3716	mpii_wait(sc, ccb);
3717	if (ccb->ccb_rcb != NULL)
3718		mpii_push_reply(sc, ccb->ccb_rcb);
3719}
3720
3721static int
3722mpii_get_ioc_pg8(struct mpii_softc *sc)
3723{
3724	struct mpii_cfg_hdr	hdr;
3725	struct mpii_cfg_ioc_pg8	*page;
3726	size_t			pagelen;
3727	u_int16_t		flags;
3728	int			pad = 0, rv = 0;
3729
3730	DNPRINTF(MPII_D_RAID, "%s: mpii_get_ioc_pg8\n", DEVNAME(sc));
3731
3732	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_IOC, 8, 0,
3733	    &hdr) != 0) {
3734		DNPRINTF(MPII_D_CFG, "%s: mpii_get_ioc_pg8 unable to fetch "
3735		    "header for IOC page 8\n", DEVNAME(sc));
3736		return (1);
3737	}
3738
3739	pagelen = hdr.page_length * 4; /* dwords to bytes */
3740
3741	page = malloc(pagelen, M_TEMP, M_NOWAIT);
3742	if (page == NULL) {
3743		DNPRINTF(MPII_D_CFG, "%s: mpii_get_ioc_pg8 unable to allocate "
3744		    "space for ioc config page 8\n", DEVNAME(sc));
3745		return (1);
3746	}
3747
3748	if (mpii_cfg_page(sc, 0, &hdr, 1, page, pagelen) != 0) {
3749		DNPRINTF(MPII_D_CFG, "%s: mpii_get_raid unable to fetch IOC "
3750		    "page 8\n", DEVNAME(sc));
3751		rv = 1;
3752		goto out;
3753	}
3754
3755	DNPRINTF(MPII_D_CFG, "%s:  numdevsperenclosure: 0x%02x\n", DEVNAME(sc),
3756	    page->num_devs_per_enclosure);
3757	DNPRINTF(MPII_D_CFG, "%s:  maxpersistententries: 0x%04x "
3758	    "maxnumphysicalmappedids: 0x%04x\n", DEVNAME(sc),
3759	    le16toh(page->max_persistent_entries),
3760	    le16toh(page->max_num_physical_mapped_ids));
3761	DNPRINTF(MPII_D_CFG, "%s:  flags: 0x%04x\n", DEVNAME(sc),
3762	    le16toh(page->flags));
3763	DNPRINTF(MPII_D_CFG, "%s:  irvolumemappingflags: 0x%04x\n",
3764	    DEVNAME(sc), le16toh(page->ir_volume_mapping_flags));
3765
3766	if (page->flags & MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0)
3767		pad = 1;
3768
3769	flags = page->ir_volume_mapping_flags &
3770	    MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK;
3771	if (ISSET(sc->sc_flags, MPII_F_RAID)) {
3772		if (flags == MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING) {
3773			sc->sc_vd_id_low += pad;
3774			pad = sc->sc_max_volumes; /* for sc_pd_id_start */
3775		} else
3776			sc->sc_vd_id_low = sc->sc_max_devices -
3777			    sc->sc_max_volumes;
3778	}
3779
3780	sc->sc_pd_id_start += pad;
3781
3782	DNPRINTF(MPII_D_MAP, "%s: mpii_get_ioc_pg8 mapping: sc_pd_id_start: %d "
3783	    "sc_vd_id_low: %d sc_max_volumes: %d\n", DEVNAME(sc),
3784	    sc->sc_pd_id_start, sc->sc_vd_id_low, sc->sc_max_volumes);
3785
3786out:
3787	free(page, M_TEMP);
3788
3789	return(rv);
3790}
3791
3792static int
3793mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number,
3794    u_int32_t address, int flags, void *p)
3795{
3796	struct mpii_msg_config_request		*cq;
3797	struct mpii_msg_config_reply		*cp;
3798	struct mpii_cfg_hdr	*hdr = p;
3799	struct mpii_ccb		*ccb;
3800	struct mpii_ecfg_hdr	*ehdr = p;
3801	int			etype = 0;
3802	int			rv = 0;
3803
3804	DNPRINTF(MPII_D_MISC, "%s: mpii_req_cfg_header type: %#x number: %x "
3805	    "address: 0x%08x flags: 0x%x\n", DEVNAME(sc), type, number,
3806	    address, flags);
3807
3808	ccb = mpii_get_ccb(sc, ISSET(flags, MPII_PG_POLL) ? MPII_NOSLEEP : 0);
3809	if (ccb == NULL) {
3810		DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header ccb_get\n",
3811		    DEVNAME(sc));
3812		return (1);
3813	}
3814
3815	if (ISSET(flags, MPII_PG_EXTENDED)) {
3816		etype = type;
3817		type = MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED;
3818	}
3819
3820	cq = ccb->ccb_cmd;
3821
3822	cq->function = MPII_FUNCTION_CONFIG;
3823
3824	cq->action = MPII_CONFIG_REQ_ACTION_PAGE_HEADER;
3825
3826	cq->config_header.page_number = number;
3827	cq->config_header.page_type = type;
3828	cq->ext_page_type = etype;
3829	cq->page_address = htole32(address);
3830	cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
3831	    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL);
3832
3833	ccb->ccb_done = mpii_empty_done;
3834	if (ISSET(flags, MPII_PG_POLL)) {
3835		if (mpii_poll(sc, ccb) != 0) {
3836			DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
3837			    DEVNAME(sc));
3838			return (1);
3839		}
3840	} else
3841		mpii_wait(sc, ccb);
3842
3843	if (ccb->ccb_rcb == NULL) {
3844		mpii_put_ccb(sc, ccb);
3845		return (1);
3846	}
3847	cp = ccb->ccb_rcb->rcb_reply;
3848
3849	DNPRINTF(MPII_D_MISC, "%s:  action: 0x%02x sgl_flags: 0x%02x "
3850	    "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action,
3851	    cp->sgl_flags, cp->msg_length, cp->function);
3852	DNPRINTF(MPII_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
3853	    "msg_flags: 0x%02x\n", DEVNAME(sc),
3854	    le16toh(cp->ext_page_length), cp->ext_page_type,
3855	    cp->msg_flags);
3856	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
3857	    cp->vp_id, cp->vf_id);
3858	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
3859	    le16toh(cp->ioc_status));
3860	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
3861	    le32toh(cp->ioc_loginfo));
3862	DNPRINTF(MPII_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
3863	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
3864	    cp->config_header.page_version,
3865	    cp->config_header.page_length,
3866	    cp->config_header.page_number,
3867	    cp->config_header.page_type);
3868
3869	if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS)
3870		rv = 1;
3871	else if (ISSET(flags, MPII_PG_EXTENDED)) {
3872		bzero(ehdr, sizeof(*ehdr));
3873		ehdr->page_version = cp->config_header.page_version;
3874		ehdr->page_number = cp->config_header.page_number;
3875		ehdr->page_type = cp->config_header.page_type;
3876		ehdr->ext_page_length = cp->ext_page_length;
3877		ehdr->ext_page_type = cp->ext_page_type;
3878	} else
3879		*hdr = cp->config_header;
3880
3881	mpii_push_reply(sc, ccb->ccb_rcb);
3882	mpii_put_ccb(sc, ccb);
3883
3884	return (rv);
3885}
3886
3887static int
3888mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int flags,
3889    void *p, int read, void *page, size_t len)
3890{
3891	struct mpii_msg_config_request		*cq;
3892	struct mpii_msg_config_reply		*cp;
3893	struct mpii_cfg_hdr	*hdr = p;
3894	struct mpii_ccb		*ccb;
3895	struct mpii_ecfg_hdr	*ehdr = p;
3896	u_int64_t		dva;
3897	char			*kva;
3898	int			page_length;
3899	int			rv = 0;
3900
3901	DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page address: %d read: %d "
3902	    "type: %x\n", DEVNAME(sc), address, read, hdr->page_type);
3903
3904	page_length = ISSET(flags, MPII_PG_EXTENDED) ?
3905	    le16toh(ehdr->ext_page_length) : hdr->page_length;
3906
3907	if (len > MPII_REQUEST_SIZE - sizeof(struct mpii_msg_config_request) ||
3908    	    len < page_length * 4)
3909		return (1);
3910
3911	ccb = mpii_get_ccb(sc,
3912	    ISSET(flags, MPII_PG_POLL) ? MPII_NOSLEEP : 0);
3913	if (ccb == NULL) {
3914		DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page ccb_get\n",
3915		    DEVNAME(sc));
3916		return (1);
3917	}
3918
3919	cq = ccb->ccb_cmd;
3920
3921	cq->function = MPII_FUNCTION_CONFIG;
3922
3923	cq->action = (read ? MPII_CONFIG_REQ_ACTION_PAGE_READ_CURRENT :
3924	    MPII_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT);
3925
3926	if (ISSET(flags, MPII_PG_EXTENDED)) {
3927		cq->config_header.page_version = ehdr->page_version;
3928		cq->config_header.page_number = ehdr->page_number;
3929		cq->config_header.page_type = ehdr->page_type;
3930		cq->ext_page_len = ehdr->ext_page_length;
3931		cq->ext_page_type = ehdr->ext_page_type;
3932	} else
3933		cq->config_header = *hdr;
3934	cq->config_header.page_type &= MPII_CONFIG_REQ_PAGE_TYPE_MASK;
3935	cq->page_address = htole32(address);
3936	cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE |
3937	    MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL |
3938	    MPII_SGE_FL_SIZE_64 | (page_length * 4) |
3939	    (read ? MPII_SGE_FL_DIR_IN : MPII_SGE_FL_DIR_OUT));
3940
3941	/* bounce the page via the request space to avoid more bus_dma games */
3942	dva = ccb->ccb_cmd_dva + sizeof(struct mpii_msg_config_request);
3943
3944	cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32));
3945	cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva);
3946
3947	kva = ccb->ccb_cmd;
3948	kva += sizeof(struct mpii_msg_config_request);
3949
3950	if (!read)
3951		bcopy(page, kva, len);
3952
3953	ccb->ccb_done = mpii_empty_done;
3954	if (ISSET(flags, MPII_PG_POLL)) {
3955		if (mpii_poll(sc, ccb) != 0) {
3956			DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n",
3957			    DEVNAME(sc));
3958			return (1);
3959		}
3960	} else
3961		mpii_wait(sc, ccb);
3962
3963	if (ccb->ccb_rcb == NULL) {
3964		mpii_put_ccb(sc, ccb);
3965		return (1);
3966	}
3967	cp = ccb->ccb_rcb->rcb_reply;
3968
3969	DNPRINTF(MPII_D_MISC, "%s:  action: 0x%02x "
3970	    "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action,
3971	    cp->msg_length, cp->function);
3972	DNPRINTF(MPII_D_MISC, "%s:  ext_page_length: %d ext_page_type: 0x%02x "
3973	    "msg_flags: 0x%02x\n", DEVNAME(sc),
3974	    le16toh(cp->ext_page_length), cp->ext_page_type,
3975	    cp->msg_flags);
3976	DNPRINTF(MPII_D_MISC, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
3977	    cp->vp_id, cp->vf_id);
3978	DNPRINTF(MPII_D_MISC, "%s:  ioc_status: 0x%04x\n", DEVNAME(sc),
3979	    le16toh(cp->ioc_status));
3980	DNPRINTF(MPII_D_MISC, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
3981	    le32toh(cp->ioc_loginfo));
3982	DNPRINTF(MPII_D_MISC, "%s:  page_version: 0x%02x page_length: %d "
3983	    "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc),
3984	    cp->config_header.page_version,
3985	    cp->config_header.page_length,
3986	    cp->config_header.page_number,
3987	    cp->config_header.page_type);
3988
3989	if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS)
3990		rv = 1;
3991	else if (read)
3992		bcopy(kva, page, len);
3993
3994	mpii_push_reply(sc, ccb->ccb_rcb);
3995	mpii_put_ccb(sc, ccb);
3996
3997	return (rv);
3998}
3999
4000static struct mpii_rcb *
4001mpii_reply(struct mpii_softc *sc, struct mpii_reply_descr *rdp)
4002{
4003	struct mpii_rcb		*rcb = NULL;
4004	u_int32_t		rfid;
4005
4006	DNPRINTF(MPII_D_INTR, "%s: mpii_reply\n", DEVNAME(sc));
4007
4008	if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
4009	    MPII_REPLY_DESCR_ADDRESS_REPLY) {
4010		rfid = (le32toh(rdp->frame_addr) -
4011		    (u_int32_t)MPII_DMA_DVA(sc->sc_replies)) / MPII_REPLY_SIZE;
4012
4013		bus_dmamap_sync(sc->sc_dmat,
4014		    MPII_DMA_MAP(sc->sc_replies), MPII_REPLY_SIZE * rfid,
4015		    MPII_REPLY_SIZE, BUS_DMASYNC_POSTREAD);
4016
4017		rcb = &sc->sc_rcbs[rfid];
4018	}
4019
4020	memset(rdp, 0xff, sizeof(*rdp));
4021
4022	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq),
4023	    8 * sc->sc_reply_post_host_index, 8,
4024	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
4025
4026	return (rcb);
4027}
4028
4029static struct mpii_dmamem *
4030mpii_dmamem_alloc(struct mpii_softc *sc, size_t size)
4031{
4032	struct mpii_dmamem	*mdm;
4033	int			nsegs;
4034
4035	mdm = malloc(sizeof(*mdm), M_DEVBUF, M_NOWAIT | M_ZERO);
4036	if (mdm == NULL)
4037	return (NULL);
4038
4039	mdm->mdm_size = size;
4040
4041	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
4042	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0)
4043		goto mdmfree;
4044
4045	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg,
4046	    1, &nsegs, BUS_DMA_NOWAIT) != 0) goto destroy;
4047
4048	if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size,
4049	    &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0)
4050		goto free;
4051
4052	if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size,
4053	    NULL, BUS_DMA_NOWAIT) != 0)
4054		goto unmap;
4055
4056	DNPRINTF(MPII_D_MEM,
4057	    "  kva: %p  dva: 0x%" PRIx64 "  map: %p  size: %" PRId64 "\n",
4058	    mdm->mdm_kva, (uint64_t)mdm->mdm_map->dm_segs[0].ds_addr,
4059	    mdm->mdm_map, (uint64_t)size);
4060
4061	bzero(mdm->mdm_kva, size);
4062
4063	return (mdm);
4064
4065unmap:
4066	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size);
4067free:
4068	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
4069destroy:
4070	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
4071mdmfree:
4072	free(mdm, M_DEVBUF);
4073
4074	return (NULL);
4075}
4076
4077static void
4078mpii_dmamem_free(struct mpii_softc *sc, struct mpii_dmamem *mdm)
4079{
4080	DNPRINTF(MPII_D_MEM, "%s: mpii_dmamem_free %p\n", DEVNAME(sc), mdm);
4081
4082	bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map);
4083	bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size);
4084	bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1);
4085	bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map);
4086	free(mdm, M_DEVBUF);
4087}
4088
4089static int
4090mpii_alloc_dev(struct mpii_softc *sc)
4091{
4092	sc->sc_devs = malloc(sc->sc_max_devices *
4093	    sizeof(struct mpii_device *), M_DEVBUF, M_NOWAIT | M_ZERO);
4094	if (sc->sc_devs == NULL)
4095		return (1);
4096	return (0);
4097}
4098
4099static int
4100mpii_insert_dev(struct mpii_softc *sc, struct mpii_device *dev)
4101{
4102	int slot = dev->slot; 	/* initial hint */
4103
4104	if (!dev || slot < 0)
4105		return (1);
4106	while (slot < sc->sc_max_devices && sc->sc_devs[slot] != NULL)
4107		slot++;
4108	if (slot >= sc->sc_max_devices)
4109		return (1);
4110	dev->slot = slot;
4111	sc->sc_devs[slot] = dev;
4112	return (0);
4113}
4114
4115static int
4116mpii_remove_dev(struct mpii_softc *sc, struct mpii_device *dev)
4117{
4118	int			i;
4119
4120	if (!dev)
4121		return (1);
4122	for (i = 0; i < sc->sc_max_devices;  i++)
4123		if (sc->sc_devs[i] &&
4124		    sc->sc_devs[i]->dev_handle == dev->dev_handle) {
4125			sc->sc_devs[i] = NULL;
4126			return (0);
4127		}
4128	return (1);
4129}
4130
4131static struct mpii_device *
4132mpii_find_dev(struct mpii_softc *sc, u_int16_t handle)
4133{
4134	int			i;
4135
4136	for (i = 0; i < sc->sc_max_devices;  i++)
4137		if (sc->sc_devs[i] && sc->sc_devs[i]->dev_handle == handle)
4138			return (sc->sc_devs[i]);
4139	return (NULL);
4140}
4141
4142static int
4143mpii_alloc_ccbs(struct mpii_softc *sc)
4144{
4145	struct mpii_ccb		*ccb;
4146	u_int8_t		*cmd;
4147	int			i;
4148
4149	SIMPLEQ_INIT(&sc->sc_ccb_free);
4150
4151	sc->sc_ccbs = malloc(sizeof(*ccb) * (sc->sc_request_depth-1),
4152	    M_DEVBUF, M_NOWAIT | M_ZERO);
4153	if (sc->sc_ccbs == NULL) {
4154		printf("%s: unable to allocate ccbs\n", DEVNAME(sc));
4155		return (1);
4156	}
4157
4158	sc->sc_requests = mpii_dmamem_alloc(sc,
4159	    MPII_REQUEST_SIZE * sc->sc_request_depth);
4160	if (sc->sc_requests == NULL) {
4161		printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc));
4162		goto free_ccbs;
4163	}
4164	cmd = MPII_DMA_KVA(sc->sc_requests);
4165	bzero(cmd, MPII_REQUEST_SIZE * sc->sc_request_depth);
4166
4167	/*
4168	 * we have sc->sc_request_depth system request message
4169	 * frames, but smid zero cannot be used. so we then
4170	 * have (sc->sc_request_depth - 1) number of ccbs
4171	 */
4172	for (i = 1; i < sc->sc_request_depth; i++) {
4173		ccb = &sc->sc_ccbs[i - 1];
4174
4175		if (bus_dmamap_create(sc->sc_dmat, MAXPHYS,
4176		    sc->sc_max_sgl_len, MAXPHYS, 0,
4177		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
4178		    &ccb->ccb_dmamap) != 0) {
4179			printf("%s: unable to create dma map\n", DEVNAME(sc));
4180			goto free_maps;
4181		}
4182
4183		ccb->ccb_sc = sc;
4184		ccb->ccb_smid = i;
4185		ccb->ccb_offset = MPII_REQUEST_SIZE * i;
4186
4187		ccb->ccb_cmd = &cmd[ccb->ccb_offset];
4188		ccb->ccb_cmd_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_requests) +
4189		    ccb->ccb_offset;
4190
4191		DNPRINTF(MPII_D_CCB, "%s: mpii_alloc_ccbs(%d) ccb: %p map: %p "
4192		    "sc: %p smid: %#x offs: %#" PRIx64 " cmd: %#" PRIx64 " dva: %#" PRIx64 "\n",
4193		    DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc,
4194		    ccb->ccb_smid, (uint64_t)ccb->ccb_offset,
4195		    (uint64_t)ccb->ccb_cmd, (uint64_t)ccb->ccb_cmd_dva);
4196
4197		mpii_put_ccb(sc, ccb);
4198	}
4199
4200	return (0);
4201
4202free_maps:
4203	while ((ccb = mpii_get_ccb(sc, MPII_NOSLEEP)) != NULL)
4204		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
4205
4206	mpii_dmamem_free(sc, sc->sc_requests);
4207free_ccbs:
4208	free(sc->sc_ccbs, M_DEVBUF);
4209
4210	return (1);
4211}
4212
4213static void
4214mpii_put_ccb(struct mpii_softc *sc, struct mpii_ccb *ccb)
4215{
4216	KASSERT(ccb->ccb_sc == sc);
4217	DNPRINTF(MPII_D_CCB, "%s: mpii_put_ccb %p\n", DEVNAME(sc), ccb);
4218
4219	ccb->ccb_state = MPII_CCB_FREE;
4220	ccb->ccb_cookie = NULL;
4221	ccb->ccb_done = NULL;
4222	ccb->ccb_rcb = NULL;
4223	bzero(ccb->ccb_cmd, MPII_REQUEST_SIZE);
4224
4225	mutex_enter(&sc->sc_ccb_free_mtx);
4226	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, u.ccb_link);
4227	cv_signal(&sc->sc_ccb_free_cv);
4228	mutex_exit(&sc->sc_ccb_free_mtx);
4229}
4230
4231static struct mpii_ccb *
4232mpii_get_ccb(struct mpii_softc *sc, int flags)
4233{
4234	struct mpii_ccb		*ccb;
4235
4236	mutex_enter(&sc->sc_ccb_free_mtx);
4237	while ((ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free)) == NULL) {
4238		if (flags & MPII_NOSLEEP)
4239			break;
4240		cv_wait(&sc->sc_ccb_free_cv, &sc->sc_ccb_free_mtx);
4241	}
4242
4243	if (ccb != NULL) {
4244		SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, u.ccb_link);
4245		ccb->ccb_state = MPII_CCB_READY;
4246		KASSERT(ccb->ccb_sc == sc);
4247	}
4248	mutex_exit(&sc->sc_ccb_free_mtx);
4249
4250	DNPRINTF(MPII_D_CCB, "%s: mpii_get_ccb %p\n", DEVNAME(sc), ccb);
4251
4252	return (ccb);
4253}
4254
4255static int
4256mpii_alloc_replies(struct mpii_softc *sc)
4257{
4258	DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_replies\n", DEVNAME(sc));
4259
4260	sc->sc_rcbs = malloc(sc->sc_num_reply_frames * sizeof(struct mpii_rcb),
4261	    M_DEVBUF, M_NOWAIT);
4262	if (sc->sc_rcbs == NULL)
4263		return (1);
4264
4265	sc->sc_replies = mpii_dmamem_alloc(sc, MPII_REPLY_SIZE *
4266	    sc->sc_num_reply_frames);
4267	if (sc->sc_replies == NULL) {
4268		free(sc->sc_rcbs, M_DEVBUF);
4269		return (1);
4270	}
4271
4272	return (0);
4273}
4274
4275static void
4276mpii_push_replies(struct mpii_softc *sc)
4277{
4278	struct mpii_rcb		*rcb;
4279	char			*kva = MPII_DMA_KVA(sc->sc_replies);
4280	int			i;
4281
4282	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies),
4283	    0, MPII_REPLY_SIZE * sc->sc_num_reply_frames, BUS_DMASYNC_PREREAD);
4284
4285	for (i = 0; i < sc->sc_num_reply_frames; i++) {
4286		rcb = &sc->sc_rcbs[i];
4287
4288		rcb->rcb_reply = kva + MPII_REPLY_SIZE * i;
4289		rcb->rcb_reply_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) +
4290		    MPII_REPLY_SIZE * i;
4291		mpii_push_reply(sc, rcb);
4292	}
4293}
4294
4295static void
4296mpii_start(struct mpii_softc *sc, struct mpii_ccb *ccb)
4297{
4298	struct mpii_request_header	*rhp;
4299	struct mpii_request_descr	descr;
4300	u_int32_t			*rdp = (u_int32_t *)&descr;
4301
4302	DNPRINTF(MPII_D_RW, "%s: mpii_start %#" PRIx64 "\n", DEVNAME(sc),
4303	    (uint64_t)ccb->ccb_cmd_dva);
4304
4305	rhp = ccb->ccb_cmd;
4306
4307	bzero(&descr, sizeof(descr));
4308
4309	switch (rhp->function) {
4310	case MPII_FUNCTION_SCSI_IO_REQUEST:
4311		descr.request_flags = MPII_REQ_DESCR_SCSI_IO;
4312		descr.dev_handle = htole16(ccb->ccb_dev_handle);
4313		break;
4314	case MPII_FUNCTION_SCSI_TASK_MGMT:
4315		descr.request_flags = MPII_REQ_DESCR_HIGH_PRIORITY;
4316		break;
4317	default:
4318		descr.request_flags = MPII_REQ_DESCR_DEFAULT;
4319	}
4320
4321	descr.vf_id = sc->sc_vf_id;
4322	descr.smid = htole16(ccb->ccb_smid);
4323
4324	bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_requests),
4325	    ccb->ccb_offset, MPII_REQUEST_SIZE,
4326	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
4327
4328	ccb->ccb_state = MPII_CCB_QUEUED;
4329
4330	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_LOW (0x%08x) write "
4331	    "0x%08x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_LOW, *rdp);
4332
4333	DNPRINTF(MPII_D_RW, "%s:   MPII_REQ_DESCR_POST_HIGH (0x%08x) write "
4334	    "0x%08x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_HIGH, *(rdp+1));
4335
4336	mutex_enter(&sc->sc_req_mtx);
4337	mpii_write(sc, MPII_REQ_DESCR_POST_LOW, htole32(*rdp));
4338	mpii_write(sc, MPII_REQ_DESCR_POST_HIGH, htole32(*(rdp+1)));
4339	mutex_exit(&sc->sc_req_mtx);
4340}
4341
4342static int
4343mpii_poll(struct mpii_softc *sc, struct mpii_ccb *ccb)
4344{
4345	void				(*done)(struct mpii_ccb *);
4346	void				*cookie;
4347	int				rv = 1;
4348
4349	DNPRINTF(MPII_D_INTR, "%s: mpii_complete\n", DEVNAME(sc));
4350
4351	done = ccb->ccb_done;
4352	cookie = ccb->ccb_cookie;
4353
4354	ccb->ccb_done = mpii_poll_done;
4355	ccb->ccb_cookie = &rv;
4356
4357	mpii_start(sc, ccb);
4358
4359	while (rv == 1) {
4360		/* avoid excessive polling */
4361		if (mpii_reply_waiting(sc))
4362			mpii_intr(sc);
4363		else
4364			delay(10);
4365	}
4366
4367	ccb->ccb_cookie = cookie;
4368	done(ccb);
4369
4370	return (0);
4371}
4372
4373static void
4374mpii_poll_done(struct mpii_ccb *ccb)
4375{
4376	int				*rv = ccb->ccb_cookie;
4377
4378	*rv = 0;
4379}
4380
4381static int
4382mpii_alloc_queues(struct mpii_softc *sc)
4383{
4384	u_int32_t		*kva;
4385	u_int64_t		*kva64;
4386	int			i;
4387
4388	DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_queues\n", DEVNAME(sc));
4389
4390	sc->sc_reply_freeq = mpii_dmamem_alloc(sc,
4391	    sc->sc_reply_free_qdepth * 4);
4392	if (sc->sc_reply_freeq == NULL)
4393		return (1);
4394
4395	kva = MPII_DMA_KVA(sc->sc_reply_freeq);
4396	for (i = 0; i < sc->sc_num_reply_frames; i++) {
4397		kva[i] = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) +
4398		    MPII_REPLY_SIZE * i;
4399
4400		DNPRINTF(MPII_D_MISC, "%s:   %d:  %p = 0x%08x\n",
4401		    DEVNAME(sc), i,
4402		    &kva[i], (u_int)MPII_DMA_DVA(sc->sc_replies) +
4403		    MPII_REPLY_SIZE * i);
4404	}
4405
4406	sc->sc_reply_postq =
4407	    mpii_dmamem_alloc(sc, sc->sc_reply_post_qdepth * 8);
4408	if (sc->sc_reply_postq == NULL)
4409		goto free_reply_freeq;
4410	sc->sc_reply_postq_kva = MPII_DMA_KVA(sc->sc_reply_postq);
4411
4412	DNPRINTF(MPII_D_MISC, "%s:  populating reply post descriptor queue\n",
4413	    DEVNAME(sc));
4414	kva64 = (u_int64_t *)MPII_DMA_KVA(sc->sc_reply_postq);
4415	for (i = 0; i < sc->sc_reply_post_qdepth; i++) {
4416		kva64[i] = 0xffffffffffffffffllu;
4417		DNPRINTF(MPII_D_MISC, "%s:    %d:  %p = 0x%" PRIx64 "\n",
4418		    DEVNAME(sc), i, &kva64[i], kva64[i]);
4419	}
4420
4421	return (0);
4422
4423free_reply_freeq:
4424
4425	mpii_dmamem_free(sc, sc->sc_reply_freeq);
4426	return (1);
4427}
4428
4429static void
4430mpii_init_queues(struct mpii_softc *sc)
4431{
4432	DNPRINTF(MPII_D_MISC, "%s:  mpii_init_queues\n", DEVNAME(sc));
4433
4434	sc->sc_reply_free_host_index = sc->sc_reply_free_qdepth - 1;
4435	sc->sc_reply_post_host_index = 0;
4436	mpii_write_reply_free(sc, sc->sc_reply_free_host_index);
4437	mpii_write_reply_post(sc, sc->sc_reply_post_host_index);
4438}
4439
4440static void
4441mpii_wait(struct mpii_softc *sc, struct mpii_ccb *ccb)
4442{
4443	struct mpii_ccb_wait	mpii_ccb_wait;
4444	void			(*done)(struct mpii_ccb *);
4445	void			*cookie;
4446
4447	done = ccb->ccb_done;
4448	cookie = ccb->ccb_cookie;
4449
4450	ccb->ccb_done = mpii_wait_done;
4451	ccb->ccb_cookie = &mpii_ccb_wait;
4452
4453	mutex_init(&mpii_ccb_wait.mpii_ccbw_mtx, MUTEX_DEFAULT, IPL_BIO);
4454	cv_init(&mpii_ccb_wait.mpii_ccbw_cv, "mpii_wait");
4455
4456	/* XXX this will wait forever for the ccb to complete */
4457
4458	mpii_start(sc, ccb);
4459
4460	mutex_enter(&mpii_ccb_wait.mpii_ccbw_mtx);
4461	while (ccb->ccb_cookie != NULL) {
4462		cv_wait(&mpii_ccb_wait.mpii_ccbw_cv,
4463		    &mpii_ccb_wait.mpii_ccbw_mtx);
4464	}
4465	mutex_exit(&mpii_ccb_wait.mpii_ccbw_mtx);
4466	mutex_destroy(&mpii_ccb_wait.mpii_ccbw_mtx);
4467	cv_destroy(&mpii_ccb_wait.mpii_ccbw_cv);
4468
4469	ccb->ccb_cookie = cookie;
4470	done(ccb);
4471}
4472
4473static void
4474mpii_wait_done(struct mpii_ccb *ccb)
4475{
4476	struct mpii_ccb_wait	*mpii_ccb_waitp = ccb->ccb_cookie;
4477
4478	mutex_enter(&mpii_ccb_waitp->mpii_ccbw_mtx);
4479	ccb->ccb_cookie = NULL;
4480	cv_signal(&mpii_ccb_waitp->mpii_ccbw_cv);
4481	mutex_exit(&mpii_ccb_waitp->mpii_ccbw_mtx);
4482}
4483
4484static void
4485mpii_minphys(struct buf *bp)
4486{
4487	DNPRINTF(MPII_D_MISC, "mpii_minphys: %d\n", bp->b_bcount);
4488
4489	/* XXX currently using MPII_MAXFER = MAXPHYS */
4490	if (bp->b_bcount > MPII_MAXFER) {
4491		bp->b_bcount = MPII_MAXFER;
4492		minphys(bp);
4493	}
4494}
4495
4496static void
4497mpii_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
4498    void *arg)
4499{
4500	struct scsipi_periph	*periph;
4501	struct scsipi_xfer	*xs;
4502	struct scsipi_adapter	*adapt = chan->chan_adapter;
4503	struct mpii_softc	*sc = device_private(adapt->adapt_dev);
4504	struct mpii_ccb		*ccb;
4505	struct mpii_ccb_bundle	*mcb;
4506	struct mpii_msg_scsi_io	*io;
4507	struct mpii_device	*dev;
4508	int			target;
4509	int timeout;
4510
4511	DNPRINTF(MPII_D_CMD, "%s: mpii_scsipi_request\n", DEVNAME(sc));
4512	switch (req) {
4513	case ADAPTER_REQ_GROW_RESOURCES:
4514		/* Not supported. */
4515		return;
4516	case ADAPTER_REQ_SET_XFER_MODE:
4517	{
4518		struct scsipi_xfer_mode *xm = arg;
4519		xm->xm_mode = PERIPH_CAP_TQING;
4520		xm->xm_period = 0;
4521		xm->xm_offset = 0;
4522		scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm);
4523		return;
4524	}
4525	case ADAPTER_REQ_RUN_XFER:
4526		break;
4527	}
4528
4529	xs = arg;
4530	periph = xs->xs_periph;
4531	target = periph->periph_target;
4532
4533	if (xs->cmdlen > MPII_CDB_LEN) {
4534		DNPRINTF(MPII_D_CMD, "%s: CBD too big %d\n",
4535		    DEVNAME(sc), xs->cmdlen);
4536		bzero(&xs->sense, sizeof(xs->sense));
4537		xs->sense.scsi_sense.response_code =
4538		    SSD_RCODE_VALID | SSD_RCODE_CURRENT;
4539		xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST;
4540		xs->sense.scsi_sense.asc = 0x20;
4541		xs->error = XS_SENSE;
4542		scsipi_done(xs);
4543		return;
4544	}
4545
4546	if ((dev = sc->sc_devs[target]) == NULL) {
4547		/* device no longer exists */
4548		xs->error = XS_SELTIMEOUT;
4549		scsipi_done(xs);
4550		return;
4551	}
4552
4553	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
4554	if (ccb == NULL) {
4555		xs->error = XS_RESOURCE_SHORTAGE;
4556		scsipi_done(xs);
4557		return;
4558	}
4559
4560	DNPRINTF(MPII_D_CMD, "%s: ccb_smid: %d xs->xs_control: 0x%x\n",
4561	    DEVNAME(sc), ccb->ccb_smid, xs->xs_control);
4562
4563	ccb->ccb_cookie = xs;
4564	ccb->ccb_done = mpii_scsi_cmd_done;
4565	ccb->ccb_dev_handle = dev->dev_handle;
4566
4567	mcb = ccb->ccb_cmd;
4568	io = &mcb->mcb_io;
4569
4570	io->function = MPII_FUNCTION_SCSI_IO_REQUEST;
4571	io->sense_buffer_length = sizeof(xs->sense);
4572	io->sgl_offset0 = 24; /* XXX fix this */
4573	io->io_flags = htole16(xs->cmdlen);
4574	io->dev_handle = htole16(ccb->ccb_dev_handle);
4575	io->lun[0] = htobe16(periph->periph_lun);
4576
4577	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
4578	case XS_CTL_DATA_IN:
4579		io->direction = MPII_SCSIIO_DIR_READ;
4580		break;
4581	case XS_CTL_DATA_OUT:
4582		io->direction = MPII_SCSIIO_DIR_WRITE;
4583		break;
4584	default:
4585		io->direction = MPII_SCSIIO_DIR_NONE;
4586	}
4587
4588	io->tagging = MPII_SCSIIO_ATTR_SIMPLE_Q;
4589
4590	memcpy(io->cdb, xs->cmd, xs->cmdlen);
4591
4592	io->data_length = htole32(xs->datalen);
4593
4594	io->sense_buffer_low_address = htole32(ccb->ccb_cmd_dva +
4595	    ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb));
4596
4597	if (mpii_load_xs(ccb) != 0) {
4598		xs->error = XS_DRIVER_STUFFUP;
4599		mpii_put_ccb(sc, ccb);
4600		scsipi_done(xs);
4601		return;
4602	}
4603
4604	DNPRINTF(MPII_D_CMD, "%s:  sizeof(mpii_msg_scsi_io): %ld "
4605	    "sizeof(mpii_ccb_bundle): %ld sge offset: 0x%02lx\n",
4606	    DEVNAME(sc), sizeof(struct mpii_msg_scsi_io),
4607	    sizeof(struct mpii_ccb_bundle),
4608	    (u_int8_t *)&mcb->mcb_sgl[0] - (u_int8_t *)mcb);
4609
4610	DNPRINTF(MPII_D_CMD, "%s   sgl[0]: 0x%04x 0%04x 0x%04x\n",
4611	    DEVNAME(sc), mcb->mcb_sgl[0].sg_hdr, mcb->mcb_sgl[0].sg_lo_addr,
4612	    mcb->mcb_sgl[0].sg_hi_addr);
4613
4614	DNPRINTF(MPII_D_CMD, "%s:  Offset0: 0x%02x\n", DEVNAME(sc),
4615	    io->sgl_offset0);
4616
4617	if (xs->xs_control & XS_CTL_POLL) {
4618		if (mpii_poll(sc, ccb) != 0) {
4619			xs->error = XS_DRIVER_STUFFUP;
4620			mpii_put_ccb(sc, ccb);
4621			scsipi_done(xs);
4622		}
4623		return;
4624	}
4625	timeout = mstohz(xs->timeout);
4626	if (timeout == 0)
4627		timeout = 1;
4628	callout_reset(&xs->xs_callout, timeout, mpii_scsi_cmd_tmo, ccb);
4629
4630	DNPRINTF(MPII_D_CMD, "%s:    mpii_scsipi_request(): opcode: %02x "
4631	    "datalen: %d\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen);
4632
4633	mpii_start(sc, ccb);
4634}
4635
4636static void
4637mpii_scsi_cmd_tmo(void *xccb)
4638{
4639	struct mpii_ccb		*ccb = xccb;
4640	struct mpii_softc	*sc = ccb->ccb_sc;
4641
4642	printf("%s: mpii_scsi_cmd_tmo\n", DEVNAME(sc));
4643
4644	mutex_enter(&sc->sc_ccb_mtx);
4645	if (ccb->ccb_state == MPII_CCB_QUEUED) {
4646		ccb->ccb_state = MPII_CCB_TIMEOUT;
4647		workqueue_enqueue(sc->sc_ssb_tmowk, &ccb->u.ccb_wk, NULL);
4648	}
4649	mutex_exit(&sc->sc_ccb_mtx);
4650}
4651
4652static void
4653mpii_scsi_cmd_tmo_handler(struct work *wk, void *cookie)
4654{
4655	struct mpii_softc			*sc = cookie;
4656	struct mpii_ccb				*tccb;
4657	struct mpii_ccb				*ccb;
4658	struct mpii_msg_scsi_task_request	*stq;
4659
4660	ccb = (void *)wk;
4661	tccb = mpii_get_ccb(sc, 0);
4662
4663	mutex_enter(&sc->sc_ccb_mtx);
4664	if (ccb->ccb_state != MPII_CCB_TIMEOUT) {
4665		mpii_put_ccb(sc, tccb);
4666	}
4667	/* should remove any other ccbs for the same dev handle */
4668	mutex_exit(&sc->sc_ccb_mtx);
4669
4670	stq = tccb->ccb_cmd;
4671	stq->function = MPII_FUNCTION_SCSI_TASK_MGMT;
4672	stq->task_type = MPII_SCSI_TASK_TARGET_RESET;
4673	stq->dev_handle = htole16(ccb->ccb_dev_handle);
4674
4675	tccb->ccb_done = mpii_scsi_cmd_tmo_done;
4676	mpii_start(sc, tccb);
4677}
4678
4679static void
4680mpii_scsi_cmd_tmo_done(struct mpii_ccb *tccb)
4681{
4682        mpii_put_ccb(tccb->ccb_sc, tccb);
4683}
4684
4685
4686static void
4687mpii_scsi_cmd_done(struct mpii_ccb *ccb)
4688{
4689	struct mpii_msg_scsi_io_error	*sie;
4690	struct mpii_softc	*sc = ccb->ccb_sc;
4691	struct scsipi_xfer	*xs = ccb->ccb_cookie;
4692	struct mpii_ccb_bundle	*mcb = ccb->ccb_cmd;
4693	bus_dmamap_t		dmap = ccb->ccb_dmamap;
4694	bool			timeout = 0;
4695
4696	callout_stop(&xs->xs_callout);
4697	mutex_enter(&sc->sc_ccb_mtx);
4698	if (ccb->ccb_state == MPII_CCB_TIMEOUT)
4699		timeout = 1;
4700	ccb->ccb_state = MPII_CCB_READY;
4701	mutex_exit(&sc->sc_ccb_mtx);
4702
4703	if (xs->datalen != 0) {
4704		bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
4705		    (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD :
4706		    BUS_DMASYNC_POSTWRITE);
4707
4708		bus_dmamap_unload(sc->sc_dmat, dmap);
4709	}
4710
4711	xs->error = XS_NOERROR;
4712	xs->resid = 0;
4713
4714	if (ccb->ccb_rcb == NULL) {
4715		/* no scsi error, we're ok so drop out early */
4716		xs->status = SCSI_OK;
4717		mpii_put_ccb(sc, ccb);
4718		scsipi_done(xs);
4719		return;
4720	}
4721
4722	sie = ccb->ccb_rcb->rcb_reply;
4723
4724	DNPRINTF(MPII_D_CMD, "%s: mpii_scsi_cmd_done xs cmd: 0x%02x len: %d "
4725	    "xs_control 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen,
4726	    xs->xs_control);
4727	DNPRINTF(MPII_D_CMD, "%s:  dev_handle: %d msg_length: %d "
4728	    "function: 0x%02x\n", DEVNAME(sc), le16toh(sie->dev_handle),
4729	    sie->msg_length, sie->function);
4730	DNPRINTF(MPII_D_CMD, "%s:  vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc),
4731	    sie->vp_id, sie->vf_id);
4732	DNPRINTF(MPII_D_CMD, "%s:  scsi_status: 0x%02x scsi_state: 0x%02x "
4733	    "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status,
4734	    sie->scsi_state, le16toh(sie->ioc_status));
4735	DNPRINTF(MPII_D_CMD, "%s:  ioc_loginfo: 0x%08x\n", DEVNAME(sc),
4736	    le32toh(sie->ioc_loginfo));
4737	DNPRINTF(MPII_D_CMD, "%s:  transfer_count: %d\n", DEVNAME(sc),
4738	    le32toh(sie->transfer_count));
4739	DNPRINTF(MPII_D_CMD, "%s:  sense_count: %d\n", DEVNAME(sc),
4740	    le32toh(sie->sense_count));
4741	DNPRINTF(MPII_D_CMD, "%s:  response_info: 0x%08x\n", DEVNAME(sc),
4742	    le32toh(sie->response_info));
4743	DNPRINTF(MPII_D_CMD, "%s:  task_tag: 0x%04x\n", DEVNAME(sc),
4744	    le16toh(sie->task_tag));
4745	DNPRINTF(MPII_D_CMD, "%s:  bidirectional_transfer_count: 0x%08x\n",
4746	    DEVNAME(sc), le32toh(sie->bidirectional_transfer_count));
4747
4748	xs->status = sie->scsi_status;
4749	switch (le16toh(sie->ioc_status) & MPII_IOCSTATUS_MASK) {
4750	case MPII_IOCSTATUS_SCSI_DATA_UNDERRUN:
4751		switch (xs->status) {
4752		case SCSI_OK:
4753			xs->resid = xs->datalen - le32toh(sie->transfer_count);
4754			break;
4755		default:
4756			xs->error = XS_DRIVER_STUFFUP;
4757			break;
4758		}
4759		break;
4760	case MPII_IOCSTATUS_SUCCESS:
4761	case MPII_IOCSTATUS_SCSI_RECOVERED_ERROR:
4762		switch (xs->status) {
4763		case SCSI_OK:
4764			xs->resid = 0;
4765			break;
4766
4767		case SCSI_CHECK:
4768			xs->error = XS_SENSE;
4769			break;
4770
4771		case SCSI_BUSY:
4772		case SCSI_QUEUE_FULL:
4773			xs->error = XS_BUSY;
4774			break;
4775
4776		default:
4777			xs->error = XS_DRIVER_STUFFUP;
4778		}
4779		break;
4780
4781	case MPII_IOCSTATUS_BUSY:
4782	case MPII_IOCSTATUS_INSUFFICIENT_RESOURCES:
4783		xs->error = XS_BUSY;
4784		break;
4785
4786	case MPII_IOCSTATUS_SCSI_IOC_TERMINATED:
4787	case MPII_IOCSTATUS_SCSI_TASK_TERMINATED:
4788		xs->error = timeout ? XS_TIMEOUT : XS_RESET;
4789		break;
4790
4791	case MPII_IOCSTATUS_SCSI_INVALID_DEVHANDLE:
4792	case MPII_IOCSTATUS_SCSI_DEVICE_NOT_THERE:
4793		xs->error = XS_SELTIMEOUT;
4794		break;
4795
4796	default:
4797		xs->error = XS_DRIVER_STUFFUP;
4798		break;
4799	}
4800
4801	if (sie->scsi_state & MPII_SCSIIO_ERR_STATE_AUTOSENSE_VALID)
4802		memcpy(&xs->sense, &mcb->mcb_sense, sizeof(xs->sense));
4803
4804	DNPRINTF(MPII_D_CMD, "%s:  xs err: %d status: %#x\n", DEVNAME(sc),
4805	    xs->error, xs->status);
4806
4807	mpii_push_reply(sc, ccb->ccb_rcb);
4808	mpii_put_ccb(sc, ccb);
4809	scsipi_done(xs);
4810}
4811
4812#if 0
4813static int
4814mpii_ioctl_cache(struct scsi_link *link, u_long cmd, struct dk_cache *dc)
4815{
4816	struct mpii_softc *sc = (struct mpii_softc *)link->adapter_softc;
4817	struct mpii_device *dev = sc->sc_devs[link->target];
4818	struct mpii_cfg_raid_vol_pg0 *vpg;
4819	struct mpii_msg_raid_action_request *req;
4820 	struct mpii_msg_raid_action_reply *rep;
4821	struct mpii_cfg_hdr hdr;
4822	struct mpii_ccb	*ccb;
4823	u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle;
4824	size_t pagelen;
4825	int rv = 0;
4826	int enabled;
4827
4828	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
4829	    addr, MPII_PG_POLL, &hdr) != 0)
4830		return (EINVAL);
4831
4832	pagelen = hdr.page_length * 4;
4833	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
4834	if (vpg == NULL)
4835		return (ENOMEM);
4836
4837	if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1,
4838	    vpg, pagelen) != 0) {
4839		rv = EINVAL;
4840		goto done;
4841		free(vpg, M_TEMP);
4842		return (EINVAL);
4843	}
4844
4845	enabled = ((le16toh(vpg->volume_settings) &
4846	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) ==
4847	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0;
4848
4849	if (cmd == DIOCGCACHE) {
4850		dc->wrcache = enabled;
4851		dc->rdcache = 0;
4852		goto done;
4853	} /* else DIOCSCACHE */
4854
4855	if (dc->rdcache) {
4856		rv = EOPNOTSUPP;
4857		goto done;
4858	}
4859
4860	if (((dc->wrcache) ? 1 : 0) == enabled)
4861		goto done;
4862
4863	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
4864	if (ccb == NULL) {
4865		rv = ENOMEM;
4866		goto done;
4867	}
4868
4869	ccb->ccb_done = mpii_empty_done;
4870
4871	req = ccb->ccb_cmd;
4872	bzero(req, sizeof(*req));
4873	req->function = MPII_FUNCTION_RAID_ACTION;
4874	req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE;
4875	req->vol_dev_handle = htole16(dev->dev_handle);
4876	req->action_data = htole32(dc->wrcache ?
4877	    MPII_RAID_VOL_WRITE_CACHE_ENABLE :
4878	    MPII_RAID_VOL_WRITE_CACHE_DISABLE);
4879
4880	if (mpii_poll(sc, ccb) != 0) {
4881		rv = EIO;
4882		goto done;
4883	}
4884
4885	if (ccb->ccb_rcb != NULL) {
4886		rep = ccb->ccb_rcb->rcb_reply;
4887		if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) ||
4888		    ((rep->action_data[0] &
4889		     MPII_RAID_VOL_WRITE_CACHE_MASK) !=
4890		    (dc->wrcache ? MPII_RAID_VOL_WRITE_CACHE_ENABLE :
4891		     MPII_RAID_VOL_WRITE_CACHE_DISABLE)))
4892			rv = EINVAL;
4893		mpii_push_reply(sc, ccb->ccb_rcb);
4894	}
4895
4896	mpii_put_ccb(sc, ccb);
4897
4898done:
4899	free(vpg, M_TEMP);
4900	return (rv);
4901}
4902#endif
4903static int
4904mpii_cache_enable(struct mpii_softc *sc, struct mpii_device *dev)
4905{
4906	struct mpii_cfg_raid_vol_pg0 *vpg;
4907	struct mpii_msg_raid_action_request *req;
4908 	struct mpii_msg_raid_action_reply *rep;
4909	struct mpii_cfg_hdr hdr;
4910	struct mpii_ccb	*ccb;
4911	u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle;
4912	size_t pagelen;
4913	int rv = 0;
4914	int enabled;
4915
4916	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
4917	    addr, MPII_PG_POLL, &hdr) != 0)
4918		return (EINVAL);
4919
4920	pagelen = hdr.page_length * 4;
4921	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
4922	if (vpg == NULL)
4923		return (ENOMEM);
4924
4925	if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1,
4926	    vpg, pagelen) != 0) {
4927		rv = EINVAL;
4928		goto done;
4929		free(vpg, M_TEMP);
4930		return (EINVAL);
4931	}
4932
4933	enabled = ((le16toh(vpg->volume_settings) &
4934	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) ==
4935	    MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0;
4936	aprint_normal_dev(sc->sc_dev, "target %d cache %s", dev->slot,
4937	    enabled ? "enabled" : "disabled, enabling");
4938	aprint_normal("\n");
4939
4940	if (enabled == 0)
4941		goto done;
4942
4943	ccb = mpii_get_ccb(sc, MPII_NOSLEEP);
4944	if (ccb == NULL) {
4945		rv = ENOMEM;
4946		goto done;
4947	}
4948
4949	ccb->ccb_done = mpii_empty_done;
4950
4951	req = ccb->ccb_cmd;
4952	bzero(req, sizeof(*req));
4953	req->function = MPII_FUNCTION_RAID_ACTION;
4954	req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE;
4955	req->vol_dev_handle = htole16(dev->dev_handle);
4956	req->action_data = htole32(
4957	    MPII_RAID_VOL_WRITE_CACHE_ENABLE);
4958
4959	if (mpii_poll(sc, ccb) != 0) {
4960		rv = EIO;
4961		goto done;
4962	}
4963
4964	if (ccb->ccb_rcb != NULL) {
4965		rep = ccb->ccb_rcb->rcb_reply;
4966		if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) ||
4967		    ((rep->action_data[0] &
4968		     MPII_RAID_VOL_WRITE_CACHE_MASK) !=
4969		     MPII_RAID_VOL_WRITE_CACHE_ENABLE))
4970			rv = EINVAL;
4971		mpii_push_reply(sc, ccb->ccb_rcb);
4972	}
4973
4974	mpii_put_ccb(sc, ccb);
4975
4976done:
4977	free(vpg, M_TEMP);
4978	if (rv) {
4979		aprint_error_dev(sc->sc_dev,
4980		    "enabling cache on target %d failed (%d)\n",
4981		    dev->slot, rv);
4982	}
4983	return (rv);
4984}
4985
4986#if NBIO > 0
4987static int
4988mpii_ioctl(device_t dev, u_long cmd, void *addr)
4989{
4990	struct mpii_softc	*sc = device_private(dev);
4991	int			s, error = 0;
4992
4993	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl ", DEVNAME(sc));
4994	KERNEL_LOCK(1, curlwp);
4995	s = splbio();
4996
4997	switch (cmd) {
4998	case BIOCINQ:
4999		DNPRINTF(MPII_D_IOCTL, "inq\n");
5000		error = mpii_ioctl_inq(sc, (struct bioc_inq *)addr);
5001		break;
5002	case BIOCVOL:
5003		DNPRINTF(MPII_D_IOCTL, "vol\n");
5004		error = mpii_ioctl_vol(sc, (struct bioc_vol *)addr);
5005		break;
5006	case BIOCDISK:
5007		DNPRINTF(MPII_D_IOCTL, "disk\n");
5008		error = mpii_ioctl_disk(sc, (struct bioc_disk *)addr);
5009		break;
5010	default:
5011		DNPRINTF(MPII_D_IOCTL, " invalid ioctl\n");
5012		error = EINVAL;
5013	}
5014
5015	splx(s);
5016	KERNEL_UNLOCK_ONE(curlwp);
5017	return (error);
5018}
5019
5020static int
5021mpii_ioctl_inq(struct mpii_softc *sc, struct bioc_inq *bi)
5022{
5023	int			i;
5024
5025	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_inq\n", DEVNAME(sc));
5026
5027	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
5028	for (i = 0; i < sc->sc_max_devices; i++)
5029		if (sc->sc_devs[i] &&
5030		    ISSET(sc->sc_devs[i]->flags, MPII_DF_VOLUME))
5031			bi->bi_novol++;
5032	return (0);
5033}
5034
5035static int
5036mpii_ioctl_vol(struct mpii_softc *sc, struct bioc_vol *bv)
5037{
5038	struct mpii_cfg_raid_vol_pg0	*vpg;
5039	struct mpii_cfg_hdr		hdr;
5040	struct mpii_device		*dev;
5041	struct scsipi_periph 		*periph;
5042	size_t				pagelen;
5043	u_int16_t			volh;
5044	int				rv, hcnt = 0;
5045
5046	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_vol %d\n",
5047	    DEVNAME(sc), bv->bv_volid);
5048
5049	if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL)
5050		return (ENODEV);
5051	volh = dev->dev_handle;
5052
5053	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
5054	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) {
5055		printf("%s: unable to fetch header for raid volume page 0\n",
5056		    DEVNAME(sc));
5057		return (EINVAL);
5058	}
5059
5060	pagelen = hdr.page_length * 4;
5061	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
5062	if (vpg == NULL) {
5063		printf("%s: unable to allocate space for raid "
5064		    "volume page 0\n", DEVNAME(sc));
5065		return (ENOMEM);
5066	}
5067
5068	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0,
5069	    &hdr, 1, vpg, pagelen) != 0) {
5070		printf("%s: unable to fetch raid volume page 0\n",
5071		    DEVNAME(sc));
5072		free(vpg, M_TEMP);
5073		return (EINVAL);
5074	}
5075
5076	switch (vpg->volume_state) {
5077	case MPII_CFG_RAID_VOL_0_STATE_ONLINE:
5078	case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL:
5079		bv->bv_status = BIOC_SVONLINE;
5080		break;
5081	case MPII_CFG_RAID_VOL_0_STATE_DEGRADED:
5082		if (ISSET(le32toh(vpg->volume_status),
5083		    MPII_CFG_RAID_VOL_0_STATUS_RESYNC)) {
5084			bv->bv_status = BIOC_SVREBUILD;
5085			bv->bv_percent = dev->percent;
5086		} else
5087			bv->bv_status = BIOC_SVDEGRADED;
5088		break;
5089	case MPII_CFG_RAID_VOL_0_STATE_FAILED:
5090		bv->bv_status = BIOC_SVOFFLINE;
5091		break;
5092	case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING:
5093		bv->bv_status = BIOC_SVBUILDING;
5094		break;
5095	case MPII_CFG_RAID_VOL_0_STATE_MISSING:
5096	default:
5097		bv->bv_status = BIOC_SVINVALID;
5098		break;
5099	}
5100
5101	switch (vpg->volume_type) {
5102	case MPII_CFG_RAID_VOL_0_TYPE_RAID0:
5103		bv->bv_level = 0;
5104		break;
5105	case MPII_CFG_RAID_VOL_0_TYPE_RAID1:
5106		bv->bv_level = 1;
5107		break;
5108	case MPII_CFG_RAID_VOL_0_TYPE_RAID1E:
5109	case MPII_CFG_RAID_VOL_0_TYPE_RAID10:
5110		bv->bv_level = 10;
5111		break;
5112	default:
5113		bv->bv_level = -1;
5114	}
5115
5116	if ((rv = mpii_bio_hs(sc, NULL, 0, vpg->hot_spare_pool, &hcnt)) != 0) {
5117		free(vpg, M_TEMP);
5118		return (rv);
5119	}
5120
5121	bv->bv_nodisk = vpg->num_phys_disks + hcnt;
5122
5123	bv->bv_size = le64toh(vpg->max_lba) * le16toh(vpg->block_size);
5124
5125	periph = scsipi_lookup_periph(&sc->sc_chan, dev->slot, 0);
5126	if (periph != NULL) {
5127		if (periph->periph_dev == NULL) {
5128			snprintf(bv->bv_dev, sizeof(bv->bv_dev), "%s:%d",
5129			    DEVNAME(sc), dev->slot);
5130		} else {
5131			strlcpy(bv->bv_dev, device_xname(periph->periph_dev),
5132			    sizeof(bv->bv_dev));
5133		}
5134	}
5135
5136	free(vpg, M_TEMP);
5137	return (0);
5138}
5139
5140static int
5141mpii_ioctl_disk(struct mpii_softc *sc, struct bioc_disk *bd)
5142{
5143	struct mpii_cfg_raid_vol_pg0		*vpg;
5144	struct mpii_cfg_raid_vol_pg0_physdisk	*pd;
5145	struct mpii_cfg_hdr			hdr;
5146	struct mpii_device			*dev;
5147	size_t					pagelen;
5148	u_int16_t				volh;
5149	u_int8_t				dn;
5150
5151	DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_disk %d/%d\n",
5152	    DEVNAME(sc), bd->bd_volid, bd->bd_diskid);
5153
5154	if ((dev = mpii_find_vol(sc, bd->bd_volid)) == NULL)
5155		return (ENODEV);
5156	volh = dev->dev_handle;
5157
5158	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
5159	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) {
5160		printf("%s: unable to fetch header for raid volume page 0\n",
5161		    DEVNAME(sc));
5162		return (EINVAL);
5163	}
5164
5165	pagelen = hdr.page_length * 4;
5166	vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
5167	if (vpg == NULL) {
5168		printf("%s: unable to allocate space for raid "
5169		    "volume page 0\n", DEVNAME(sc));
5170		return (ENOMEM);
5171	}
5172
5173	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0,
5174	    &hdr, 1, vpg, pagelen) != 0) {
5175		printf("%s: unable to fetch raid volume page 0\n",
5176		    DEVNAME(sc));
5177		free(vpg, M_TEMP);
5178		return (EINVAL);
5179	}
5180
5181	if (bd->bd_diskid >= vpg->num_phys_disks) {
5182		int		nvdsk = vpg->num_phys_disks;
5183		int		hsmap = vpg->hot_spare_pool;
5184
5185		free(vpg, M_TEMP);
5186		return (mpii_bio_hs(sc, bd, nvdsk, hsmap, NULL));
5187	}
5188
5189	pd = (struct mpii_cfg_raid_vol_pg0_physdisk *)(vpg + 1) +
5190	    bd->bd_diskid;
5191	dn = pd->phys_disk_num;
5192
5193	free(vpg, M_TEMP);
5194	return (mpii_bio_disk(sc, bd, dn));
5195}
5196
5197static int
5198mpii_bio_hs(struct mpii_softc *sc, struct bioc_disk *bd, int nvdsk,
5199     int hsmap, int *hscnt)
5200{
5201	struct mpii_cfg_raid_config_pg0	*cpg;
5202	struct mpii_raid_config_element	*el;
5203	struct mpii_ecfg_hdr		ehdr;
5204	size_t				pagelen;
5205	int				i, nhs = 0;
5206
5207	if (bd) {
5208		DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs %d\n", DEVNAME(sc),
5209		    bd->bd_diskid - nvdsk);
5210	} else {
5211		DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs\n", DEVNAME(sc));
5212	}
5213
5214	if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_CONFIG,
5215	    0, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG, MPII_PG_EXTENDED,
5216	    &ehdr) != 0) {
5217		printf("%s: unable to fetch header for raid config page 0\n",
5218		    DEVNAME(sc));
5219		return (EINVAL);
5220	}
5221
5222	pagelen = le16toh(ehdr.ext_page_length) * 4;
5223	cpg = malloc(pagelen, M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
5224	if (cpg == NULL) {
5225		printf("%s: unable to allocate space for raid config page 0\n",
5226		    DEVNAME(sc));
5227		return (ENOMEM);
5228	}
5229
5230	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG,
5231	    MPII_PG_EXTENDED, &ehdr, 1, cpg, pagelen) != 0) {
5232		printf("%s: unable to fetch raid config page 0\n",
5233		    DEVNAME(sc));
5234		free(cpg, M_TEMP);
5235		return (EINVAL);
5236	}
5237
5238	el = (struct mpii_raid_config_element *)(cpg + 1);
5239	for (i = 0; i < cpg->num_elements; i++, el++) {
5240		if (ISSET(le16toh(el->element_flags),
5241		    MPII_RAID_CONFIG_ELEMENT_FLAG_HSP_PHYS_DISK) &&
5242		    el->hot_spare_pool == hsmap) {
5243			/*
5244			 * diskid comparison is based on the idea that all
5245			 * disks are counted by the bio(4) in sequence, thus
5246			 * substracting the number of disks in the volume
5247			 * from the diskid yields us a "relative" hotspare
5248			 * number, which is good enough for us.
5249			 */
5250			if (bd != NULL && bd->bd_diskid == nhs + nvdsk) {
5251				u_int8_t dn = el->phys_disk_num;
5252
5253				free(cpg, M_TEMP);
5254				return (mpii_bio_disk(sc, bd, dn));
5255			}
5256			nhs++;
5257		}
5258	}
5259
5260	if (hscnt)
5261		*hscnt = nhs;
5262
5263	free(cpg, M_TEMP);
5264	return (0);
5265}
5266
5267static int
5268mpii_bio_disk(struct mpii_softc *sc, struct bioc_disk *bd, u_int8_t dn)
5269{
5270	struct mpii_cfg_raid_physdisk_pg0	*ppg;
5271	struct mpii_cfg_hdr			hdr;
5272	struct mpii_device			*dev;
5273	int					len;
5274
5275	DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_disk %d\n", DEVNAME(sc),
5276	    bd->bd_diskid);
5277
5278	ppg = malloc(sizeof(*ppg), M_TEMP, M_WAITOK | M_CANFAIL | M_ZERO);
5279	if (ppg == NULL) {
5280		printf("%s: unable to allocate space for raid physical disk "
5281		    "page 0\n", DEVNAME(sc));
5282		return (ENOMEM);
5283	}
5284
5285	hdr.page_version = 0;
5286	hdr.page_length = sizeof(*ppg) / 4;
5287	hdr.page_number = 0;
5288	hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD;
5289
5290	if (mpii_req_cfg_page(sc, MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER | dn, 0,
5291	    &hdr, 1, ppg, sizeof(*ppg)) != 0) {
5292		printf("%s: unable to fetch raid drive page 0\n",
5293		    DEVNAME(sc));
5294		free(ppg, M_TEMP);
5295		return (EINVAL);
5296	}
5297
5298	bd->bd_target = ppg->phys_disk_num;
5299
5300	if ((dev = mpii_find_dev(sc, le16toh(ppg->dev_handle))) == NULL) {
5301		bd->bd_status = BIOC_SDINVALID;
5302		free(ppg, M_TEMP);
5303		return (0);
5304	}
5305
5306	switch (ppg->phys_disk_state) {
5307	case MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE:
5308	case MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL:
5309		bd->bd_status = BIOC_SDONLINE;
5310		break;
5311	case MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE:
5312		if (ppg->offline_reason ==
5313		    MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILED ||
5314		    ppg->offline_reason ==
5315		    MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILEDREQ)
5316			bd->bd_status = BIOC_SDFAILED;
5317		else
5318			bd->bd_status = BIOC_SDOFFLINE;
5319		break;
5320	case MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED:
5321		bd->bd_status = BIOC_SDFAILED;
5322		break;
5323	case MPII_CFG_RAID_PHYDISK_0_STATE_REBUILDING:
5324		bd->bd_status = BIOC_SDREBUILD;
5325		break;
5326	case MPII_CFG_RAID_PHYDISK_0_STATE_HOTSPARE:
5327		bd->bd_status = BIOC_SDHOTSPARE;
5328		break;
5329	case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCONFIGURED:
5330		bd->bd_status = BIOC_SDUNUSED;
5331		break;
5332	case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE:
5333	default:
5334		bd->bd_status = BIOC_SDINVALID;
5335		break;
5336	}
5337
5338	bd->bd_size = le64toh(ppg->dev_max_lba) * le16toh(ppg->block_size);
5339
5340	scsipi_strvis(bd->bd_vendor, sizeof(bd->bd_vendor),
5341	    ppg->vendor_id, sizeof(ppg->vendor_id));
5342	len = strlen(bd->bd_vendor);
5343	bd->bd_vendor[len] = ' ';
5344	scsipi_strvis(&bd->bd_vendor[len + 1], sizeof(ppg->vendor_id) - len - 1,
5345	    ppg->product_id, sizeof(ppg->product_id));
5346	scsipi_strvis(bd->bd_serial, sizeof(bd->bd_serial),
5347	    ppg->serial, sizeof(ppg->serial));
5348
5349	free(ppg, M_TEMP);
5350	return (0);
5351}
5352
5353static struct mpii_device *
5354mpii_find_vol(struct mpii_softc *sc, int volid)
5355{
5356	struct mpii_device	*dev = NULL;
5357
5358	if (sc->sc_vd_id_low + volid >= sc->sc_max_devices)
5359		return (NULL);
5360	dev = sc->sc_devs[sc->sc_vd_id_low + volid];
5361	if (dev && ISSET(dev->flags, MPII_DF_VOLUME))
5362		return (dev);
5363	return (NULL);
5364}
5365
5366/*
5367 * Non-sleeping lightweight version of the mpii_ioctl_vol
5368 */
5369static int
5370mpii_bio_volstate(struct mpii_softc *sc, struct bioc_vol *bv)
5371{
5372	struct mpii_cfg_raid_vol_pg0	*vpg;
5373	struct mpii_cfg_hdr		hdr;
5374	struct mpii_device		*dev = NULL;
5375	size_t				pagelen;
5376	u_int16_t			volh;
5377
5378	if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL)
5379		return (ENODEV);
5380	volh = dev->dev_handle;
5381
5382	if (mpii_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0,
5383	    MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, &hdr) != 0) {
5384		DNPRINTF(MPII_D_MISC, "%s: unable to fetch header for raid "
5385		    "volume page 0\n", DEVNAME(sc));
5386		return (EINVAL);
5387	}
5388
5389	pagelen = hdr.page_length * 4;
5390	vpg = malloc(pagelen, M_TEMP, M_NOWAIT | M_ZERO);
5391	if (vpg == NULL) {
5392		DNPRINTF(MPII_D_MISC, "%s: unable to allocate space for raid "
5393		    "volume page 0\n", DEVNAME(sc));
5394		return (ENOMEM);
5395	}
5396
5397	if (mpii_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh,
5398	    &hdr, 1, vpg, pagelen) != 0) {
5399		DNPRINTF(MPII_D_MISC, "%s: unable to fetch raid volume "
5400		    "page 0\n", DEVNAME(sc));
5401		free(vpg, M_TEMP);
5402		return (EINVAL);
5403	}
5404
5405	switch (vpg->volume_state) {
5406	case MPII_CFG_RAID_VOL_0_STATE_ONLINE:
5407	case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL:
5408		bv->bv_status = BIOC_SVONLINE;
5409		break;
5410	case MPII_CFG_RAID_VOL_0_STATE_DEGRADED:
5411		if (ISSET(le32toh(vpg->volume_status),
5412		    MPII_CFG_RAID_VOL_0_STATUS_RESYNC))
5413			bv->bv_status = BIOC_SVREBUILD;
5414		else
5415			bv->bv_status = BIOC_SVDEGRADED;
5416		break;
5417	case MPII_CFG_RAID_VOL_0_STATE_FAILED:
5418		bv->bv_status = BIOC_SVOFFLINE;
5419		break;
5420	case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING:
5421		bv->bv_status = BIOC_SVBUILDING;
5422		break;
5423	case MPII_CFG_RAID_VOL_0_STATE_MISSING:
5424	default:
5425		bv->bv_status = BIOC_SVINVALID;
5426		break;
5427	}
5428
5429	free(vpg, M_TEMP);
5430	return (0);
5431}
5432
5433static int
5434mpii_create_sensors(struct mpii_softc *sc)
5435{
5436	int			i, rv;
5437
5438	sc->sc_sme = sysmon_envsys_create();
5439	sc->sc_sensors = malloc(sizeof(envsys_data_t) * sc->sc_vd_count,
5440	    M_DEVBUF, M_NOWAIT | M_ZERO);
5441	if (sc->sc_sensors == NULL) {
5442		aprint_error_dev(sc->sc_dev,
5443		    "can't allocate envsys_data_t\n");
5444		return (1);
5445	}
5446
5447	for (i = 0; i < sc->sc_vd_count; i++) {
5448		sc->sc_sensors[i].units = ENVSYS_DRIVE;
5449		sc->sc_sensors[i].state = ENVSYS_SINVALID;
5450		sc->sc_sensors[i].value_cur = ENVSYS_DRIVE_EMPTY;
5451		/* Enable monitoring for drive state changes */
5452		sc->sc_sensors[i].flags |= ENVSYS_FMONSTCHANGED;
5453
5454		/* logical drives */
5455		snprintf(sc->sc_sensors[i].desc,
5456		    sizeof(sc->sc_sensors[i].desc), "%s:%d",
5457		    DEVNAME(sc), i);
5458		if ((rv = sysmon_envsys_sensor_attach(sc->sc_sme,
5459		    &sc->sc_sensors[i])) != 0) {
5460			aprint_error_dev(sc->sc_dev,
5461			    "unable to attach sensor (rv = %d)\n", rv);
5462			goto out;
5463		}
5464	}
5465	sc->sc_sme->sme_name =  DEVNAME(sc);
5466	sc->sc_sme->sme_cookie = sc;
5467	sc->sc_sme->sme_refresh = mpii_refresh_sensors;
5468
5469	rv = sysmon_envsys_register(sc->sc_sme);
5470
5471	if (rv != 0) {
5472		aprint_error_dev(sc->sc_dev,
5473		    "unable to register with sysmon (rv = %d)\n", rv);
5474		goto out;
5475	}
5476	return 0;
5477
5478out:
5479	free(sc->sc_sensors, M_DEVBUF);
5480	sysmon_envsys_destroy(sc->sc_sme);
5481	sc->sc_sme = NULL;
5482	return EINVAL;
5483}
5484
5485static int
5486mpii_destroy_sensors(struct mpii_softc *sc)
5487{
5488	if (sc->sc_sme == NULL)
5489		return 0;
5490	sysmon_envsys_unregister(sc->sc_sme);
5491	sc->sc_sme = NULL;
5492	free(sc->sc_sensors, M_DEVBUF);
5493	return 0;
5494}
5495
5496static void
5497mpii_refresh_sensors(struct sysmon_envsys *sme, envsys_data_t *edata)
5498{
5499	struct mpii_softc	*sc = sc = sme->sme_cookie;
5500	struct bioc_vol		bv;
5501	int			s, error;
5502
5503	bzero(&bv, sizeof(bv));
5504	bv.bv_volid = edata->sensor;
5505	KERNEL_LOCK(1, curlwp);
5506	s = splbio();
5507	error = mpii_bio_volstate(sc, &bv);
5508	splx(s);
5509	KERNEL_UNLOCK_ONE(curlwp);
5510	if (error)
5511		return;
5512	switch(bv.bv_status) {
5513	case BIOC_SVOFFLINE:
5514		edata->value_cur = ENVSYS_DRIVE_FAIL;
5515		edata->state = ENVSYS_SCRITICAL;
5516		break;
5517	case BIOC_SVDEGRADED:
5518		edata->value_cur = ENVSYS_DRIVE_PFAIL;
5519		edata->state = ENVSYS_SCRITICAL;
5520		break;
5521	case BIOC_SVREBUILD:
5522		edata->value_cur = ENVSYS_DRIVE_REBUILD;
5523		edata->state = ENVSYS_SVALID;
5524		break;
5525	case BIOC_SVONLINE:
5526		edata->value_cur = ENVSYS_DRIVE_ONLINE;
5527		edata->state = ENVSYS_SVALID;
5528		break;
5529	case BIOC_SVINVALID:
5530		/* FALLTHROUGH */
5531	default:
5532		edata->value_cur = 0; /* unknown */
5533		edata->state = ENVSYS_SINVALID;
5534	}
5535}
5536#endif /* NBIO > 0 */
5537