xref: /netbsd-src/sys/dev/pci/mfii.c (revision 181254a7b1bdde6873432bffef2d2decc4b5c22f)
1 /* $NetBSD: mfii.c,v 1.7 2020/05/14 08:34:18 msaitoh Exp $ */
2 /* $OpenBSD: mfii.c,v 1.58 2018/08/14 05:22:21 jmatthew Exp $ */
3 
4 /*
5  * Copyright (c) 2018 Manuel Bouyer <Manuel.Bouyer@lip6.fr>
6  * Copyright (c) 2012 David Gwynne <dlg@openbsd.org>
7  *
8  * Permission to use, copy, modify, and distribute this software for any
9  * purpose with or without fee is hereby granted, provided that the above
10  * copyright notice and this permission notice appear in all copies.
11  *
12  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19  */
20 
21 #include <sys/cdefs.h>
22 __KERNEL_RCSID(0, "$NetBSD: mfii.c,v 1.7 2020/05/14 08:34:18 msaitoh Exp $");
23 
24 #include "bio.h"
25 
26 #include <sys/atomic.h>
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/buf.h>
30 #include <sys/ioctl.h>
31 #include <sys/device.h>
32 #include <sys/kernel.h>
33 #include <sys/proc.h>
34 #include <sys/cpu.h>
35 #include <sys/conf.h>
36 #include <sys/kauth.h>
37 #include <sys/workqueue.h>
38 #include <sys/malloc.h>
39 
40 #include <uvm/uvm_param.h>
41 
42 #include <dev/pci/pcidevs.h>
43 #include <dev/pci/pcivar.h>
44 
45 #include <sys/bus.h>
46 
47 #include <dev/sysmon/sysmonvar.h>
48 #include <sys/envsys.h>
49 
50 #include <dev/scsipi/scsipi_all.h>
51 #include <dev/scsipi/scsi_all.h>
52 #include <dev/scsipi/scsi_spc.h>
53 #include <dev/scsipi/scsipi_disk.h>
54 #include <dev/scsipi/scsi_disk.h>
55 #include <dev/scsipi/scsiconf.h>
56 
57 #if NBIO > 0
58 #include <dev/biovar.h>
59 #endif /* NBIO > 0 */
60 
61 #include <dev/ic/mfireg.h>
62 #include <dev/pci/mpiireg.h>
63 
64 #define	MFII_BAR		0x14
65 #define MFII_BAR_35		0x10
66 #define	MFII_PCI_MEMSIZE	0x2000 /* 8k */
67 
68 #define MFII_OSTS_INTR_VALID	0x00000009
69 #define MFII_RPI		0x6c /* reply post host index */
70 #define MFII_OSP2		0xb4 /* outbound scratch pad 2 */
71 #define MFII_OSP3		0xb8 /* outbound scratch pad 3 */
72 
73 #define MFII_REQ_TYPE_SCSI	MPII_REQ_DESCR_SCSI_IO
74 #define MFII_REQ_TYPE_LDIO	(0x7 << 1)
75 #define MFII_REQ_TYPE_MFA	(0x1 << 1)
76 #define MFII_REQ_TYPE_NO_LOCK	(0x2 << 1)
77 #define MFII_REQ_TYPE_HI_PRI	(0x6 << 1)
78 
79 #define MFII_REQ_MFA(_a)	htole64((_a) | MFII_REQ_TYPE_MFA)
80 
81 #define MFII_FUNCTION_PASSTHRU_IO			(0xf0)
82 #define MFII_FUNCTION_LDIO_REQUEST			(0xf1)
83 
84 #define MFII_MAX_CHAIN_UNIT	0x00400000
85 #define MFII_MAX_CHAIN_MASK	0x000003E0
86 #define MFII_MAX_CHAIN_SHIFT	5
87 
88 #define MFII_256K_IO		128
89 #define MFII_1MB_IO		(MFII_256K_IO * 4)
90 
91 #define MFII_CHAIN_FRAME_MIN	1024
92 
93 struct mfii_request_descr {
94 	u_int8_t	flags;
95 	u_int8_t	msix_index;
96 	u_int16_t	smid;
97 
98 	u_int16_t	lmid;
99 	u_int16_t	dev_handle;
100 } __packed;
101 
102 #define MFII_RAID_CTX_IO_TYPE_SYSPD	(0x1 << 4)
103 #define MFII_RAID_CTX_TYPE_CUDA		(0x2 << 4)
104 
105 struct mfii_raid_context {
106 	u_int8_t	type_nseg;
107 	u_int8_t	_reserved1;
108 	u_int16_t	timeout_value;
109 
110 	u_int16_t	reg_lock_flags;
111 #define MFII_RAID_CTX_RL_FLAGS_SEQNO_EN	(0x08)
112 #define MFII_RAID_CTX_RL_FLAGS_CPU0	(0x00)
113 #define MFII_RAID_CTX_RL_FLAGS_CPU1	(0x10)
114 #define MFII_RAID_CTX_RL_FLAGS_CUDA	(0x80)
115 
116 #define MFII_RAID_CTX_ROUTING_FLAGS_SQN	(1 << 4)
117 #define MFII_RAID_CTX_ROUTING_FLAGS_CPU0 0
118 	u_int16_t	virtual_disk_target_id;
119 
120 	u_int64_t	reg_lock_row_lba;
121 
122 	u_int32_t	reg_lock_length;
123 
124 	u_int16_t	next_lm_id;
125 	u_int8_t	ex_status;
126 	u_int8_t	status;
127 
128 	u_int8_t	raid_flags;
129 	u_int8_t	num_sge;
130 	u_int16_t	config_seq_num;
131 
132 	u_int8_t	span_arm;
133 	u_int8_t	_reserved3[3];
134 } __packed;
135 
136 struct mfii_sge {
137 	u_int64_t	sg_addr;
138 	u_int32_t	sg_len;
139 	u_int16_t	_reserved;
140 	u_int8_t	sg_next_chain_offset;
141 	u_int8_t	sg_flags;
142 } __packed;
143 
144 #define MFII_SGE_ADDR_MASK		(0x03)
145 #define MFII_SGE_ADDR_SYSTEM		(0x00)
146 #define MFII_SGE_ADDR_IOCDDR		(0x01)
147 #define MFII_SGE_ADDR_IOCPLB		(0x02)
148 #define MFII_SGE_ADDR_IOCPLBNTA		(0x03)
149 #define MFII_SGE_END_OF_LIST		(0x40)
150 #define MFII_SGE_CHAIN_ELEMENT		(0x80)
151 
152 #define MFII_REQUEST_SIZE	256
153 
154 #define MR_DCMD_LD_MAP_GET_INFO			0x0300e101
155 
156 #define MFII_MAX_ROW		32
157 #define MFII_MAX_ARRAY		128
158 
159 struct mfii_array_map {
160 	uint16_t		mam_pd[MFII_MAX_ROW];
161 } __packed;
162 
163 struct mfii_dev_handle {
164 	uint16_t		mdh_cur_handle;
165 	uint8_t			mdh_valid;
166 	uint8_t			mdh_reserved;
167 	uint16_t		mdh_handle[2];
168 } __packed;
169 
170 struct mfii_ld_map {
171 	uint32_t		mlm_total_size;
172 	uint32_t		mlm_reserved1[5];
173 	uint32_t		mlm_num_lds;
174 	uint32_t		mlm_reserved2;
175 	uint8_t			mlm_tgtid_to_ld[2 * MFI_MAX_LD];
176 	uint8_t			mlm_pd_timeout;
177 	uint8_t			mlm_reserved3[7];
178 	struct mfii_array_map	mlm_am[MFII_MAX_ARRAY];
179 	struct mfii_dev_handle	mlm_dev_handle[MFI_MAX_PD];
180 } __packed;
181 
182 struct mfii_task_mgmt {
183 	union {
184 		uint8_t			request[128];
185 		struct mpii_msg_scsi_task_request
186 					mpii_request;
187 	} __packed __aligned(8);
188 
189 	union {
190 		uint8_t			reply[128];
191 		uint32_t		flags;
192 #define MFII_TASK_MGMT_FLAGS_LD				(1 << 0)
193 #define MFII_TASK_MGMT_FLAGS_PD				(1 << 1)
194 		struct mpii_msg_scsi_task_reply
195 					mpii_reply;
196 	} __packed __aligned(8);
197 } __packed __aligned(8);
198 
199 /* We currently don't know the full details of the following struct */
200 struct mfii_foreign_scan_cfg {
201         char data[24];
202 } __packed;
203 
204 struct mfii_foreign_scan_info {
205 	uint32_t count; /* Number of foreign configs found */
206 	struct mfii_foreign_scan_cfg cfgs[8];
207 } __packed;
208 
209 struct mfii_dmamem {
210 	bus_dmamap_t		mdm_map;
211 	bus_dma_segment_t	mdm_seg;
212 	size_t			mdm_size;
213 	void *			mdm_kva;
214 };
215 #define MFII_DMA_MAP(_mdm)	((_mdm)->mdm_map)
216 #define MFII_DMA_LEN(_mdm)	((_mdm)->mdm_size)
217 #define MFII_DMA_DVA(_mdm)	((u_int64_t)(_mdm)->mdm_map->dm_segs[0].ds_addr)
218 #define MFII_DMA_KVA(_mdm)	((void *)(_mdm)->mdm_kva)
219 
220 struct mfii_softc;
221 
222 typedef enum mfii_direction {
223 	MFII_DATA_NONE = 0,
224 	MFII_DATA_IN,
225 	MFII_DATA_OUT
226 } mfii_direction_t;
227 
228 struct mfii_ccb {
229 	struct mfii_softc	*ccb_sc;
230 	void			*ccb_request;
231 	u_int64_t		ccb_request_dva;
232 	bus_addr_t		ccb_request_offset;
233 
234 	void			*ccb_mfi;
235 	u_int64_t		ccb_mfi_dva;
236 	bus_addr_t		ccb_mfi_offset;
237 
238 	struct mfi_sense	*ccb_sense;
239 	u_int64_t		ccb_sense_dva;
240 	bus_addr_t		ccb_sense_offset;
241 
242 	struct mfii_sge		*ccb_sgl;
243 	u_int64_t		ccb_sgl_dva;
244 	bus_addr_t		ccb_sgl_offset;
245 	u_int			ccb_sgl_len;
246 
247 	struct mfii_request_descr ccb_req;
248 
249 	bus_dmamap_t		ccb_dmamap64;
250 	bus_dmamap_t		ccb_dmamap32;
251 	bool			ccb_dma64;
252 
253 	/* data for sgl */
254 	void			*ccb_data;
255 	size_t			ccb_len;
256 
257 	mfii_direction_t	ccb_direction;
258 
259 	void			*ccb_cookie;
260 	kmutex_t		ccb_mtx;
261 	kcondvar_t		ccb_cv;
262 	void			(*ccb_done)(struct mfii_softc *,
263 				    struct mfii_ccb *);
264 
265 	u_int32_t		ccb_flags;
266 #define MFI_CCB_F_ERR			(1<<0)
267 	u_int			ccb_smid;
268 	SIMPLEQ_ENTRY(mfii_ccb)	ccb_link;
269 };
270 SIMPLEQ_HEAD(mfii_ccb_list, mfii_ccb);
271 
272 struct mfii_iop {
273 	int bar;
274 	int num_sge_loc;
275 #define MFII_IOP_NUM_SGE_LOC_ORIG	0
276 #define MFII_IOP_NUM_SGE_LOC_35		1
277 	u_int16_t ldio_ctx_reg_lock_flags;
278 	u_int8_t ldio_req_type;
279 	u_int8_t ldio_ctx_type_nseg;
280 	u_int8_t sge_flag_chain;
281 	u_int8_t sge_flag_eol;
282 };
283 
284 struct mfii_softc {
285 	device_t		sc_dev;
286 	struct scsipi_channel   sc_chan;
287 	struct scsipi_adapter   sc_adapt;
288 
289 	const struct mfii_iop	*sc_iop;
290 
291 	pci_chipset_tag_t	sc_pc;
292 	pcitag_t		sc_tag;
293 
294 	bus_space_tag_t		sc_iot;
295 	bus_space_handle_t	sc_ioh;
296 	bus_size_t		sc_ios;
297 	bus_dma_tag_t		sc_dmat;
298 	bus_dma_tag_t		sc_dmat64;
299 	bool			sc_64bit_dma;
300 
301 	void			*sc_ih;
302 
303 	kmutex_t		sc_ccb_mtx;
304 	kmutex_t		sc_post_mtx;
305 
306 	u_int			sc_max_fw_cmds;
307 	u_int			sc_max_cmds;
308 	u_int			sc_max_sgl;
309 
310 	u_int			sc_reply_postq_depth;
311 	u_int			sc_reply_postq_index;
312 	kmutex_t		sc_reply_postq_mtx;
313 	struct mfii_dmamem	*sc_reply_postq;
314 
315 	struct mfii_dmamem	*sc_requests;
316 	struct mfii_dmamem	*sc_mfi;
317 	struct mfii_dmamem	*sc_sense;
318 	struct mfii_dmamem	*sc_sgl;
319 
320 	struct mfii_ccb		*sc_ccb;
321 	struct mfii_ccb_list	sc_ccb_freeq;
322 
323 	struct mfii_ccb		*sc_aen_ccb;
324 	struct workqueue	*sc_aen_wq;
325 	struct work		sc_aen_work;
326 
327 	kmutex_t		sc_abort_mtx;
328 	struct mfii_ccb_list	sc_abort_list;
329 	struct workqueue	*sc_abort_wq;
330 	struct work		sc_abort_work;
331 
332 	/* save some useful information for logical drives that is missing
333 	 * in sc_ld_list
334 	 */
335 	struct {
336 		bool		ld_present;
337 		char		ld_dev[16];	/* device name sd? */
338 	}			sc_ld[MFI_MAX_LD];
339 	int			sc_target_lds[MFI_MAX_LD];
340 
341 	/* bio */
342 	struct mfi_conf	 *sc_cfg;
343 	struct mfi_ctrl_info    sc_info;
344 	struct mfi_ld_list	sc_ld_list;
345 	struct mfi_ld_details	*sc_ld_details; /* array to all logical disks */
346 	int			sc_no_pd; /* used physical disks */
347 	int			sc_ld_sz; /* sizeof sc_ld_details */
348 
349 	/* mgmt lock */
350 	kmutex_t		sc_lock;
351 	bool			sc_running;
352 
353 	/* sensors */
354 	struct sysmon_envsys	*sc_sme;
355 	envsys_data_t		*sc_sensors;
356 	bool			sc_bbuok;
357 
358 	device_t		sc_child;
359 };
360 
361 // #define MFII_DEBUG
362 #ifdef MFII_DEBUG
363 #define DPRINTF(x...)		do { if (mfii_debug) printf(x); } while(0)
364 #define DNPRINTF(n,x...)	do { if (mfii_debug & n) printf(x); } while(0)
365 #define	MFII_D_CMD		0x0001
366 #define	MFII_D_INTR		0x0002
367 #define	MFII_D_MISC		0x0004
368 #define	MFII_D_DMA		0x0008
369 #define	MFII_D_IOCTL		0x0010
370 #define	MFII_D_RW		0x0020
371 #define	MFII_D_MEM		0x0040
372 #define	MFII_D_CCB		0x0080
373 uint32_t	mfii_debug = 0
374 /*		    | MFII_D_CMD */
375 /*		    | MFII_D_INTR */
376 	    	    | MFII_D_MISC
377 /*		    | MFII_D_DMA */
378 /*		    | MFII_D_IOCTL */
379 /*		    | MFII_D_RW */
380 /*		    | MFII_D_MEM */
381 /*		    | MFII_D_CCB */
382 		;
383 #else
384 #define DPRINTF(x...)
385 #define DNPRINTF(n,x...)
386 #endif
387 
388 static int	mfii_match(device_t, cfdata_t, void *);
389 static void	mfii_attach(device_t, device_t, void *);
390 static int	mfii_detach(device_t, int);
391 static int	mfii_rescan(device_t, const char *, const int *);
392 static void	mfii_childdetached(device_t, device_t);
393 static bool	mfii_suspend(device_t, const pmf_qual_t *);
394 static bool	mfii_resume(device_t, const pmf_qual_t *);
395 static bool	mfii_shutdown(device_t, int);
396 
397 
398 CFATTACH_DECL3_NEW(mfii, sizeof(struct mfii_softc),
399     mfii_match, mfii_attach, mfii_detach, NULL, mfii_rescan,
400 	mfii_childdetached, DVF_DETACH_SHUTDOWN);
401 
402 static void	mfii_scsipi_request(struct scsipi_channel *,
403 			scsipi_adapter_req_t, void *);
404 static void	mfii_scsi_cmd_done(struct mfii_softc *, struct mfii_ccb *);
405 
406 #define DEVNAME(_sc)		(device_xname((_sc)->sc_dev))
407 
408 static u_int32_t	mfii_read(struct mfii_softc *, bus_size_t);
409 static void		mfii_write(struct mfii_softc *, bus_size_t, u_int32_t);
410 
411 static struct mfii_dmamem *	mfii_dmamem_alloc(struct mfii_softc *, size_t);
412 static void		mfii_dmamem_free(struct mfii_softc *,
413 			    struct mfii_dmamem *);
414 
415 static struct mfii_ccb *	mfii_get_ccb(struct mfii_softc *);
416 static void		mfii_put_ccb(struct mfii_softc *, struct mfii_ccb *);
417 static int		mfii_init_ccb(struct mfii_softc *);
418 static void		mfii_scrub_ccb(struct mfii_ccb *);
419 
420 static int		mfii_transition_firmware(struct mfii_softc *);
421 static int		mfii_initialise_firmware(struct mfii_softc *);
422 static int		mfii_get_info(struct mfii_softc *);
423 
424 static void		mfii_start(struct mfii_softc *, struct mfii_ccb *);
425 static void		mfii_done(struct mfii_softc *, struct mfii_ccb *);
426 static int		mfii_poll(struct mfii_softc *, struct mfii_ccb *);
427 static void		mfii_poll_done(struct mfii_softc *, struct mfii_ccb *);
428 static int		mfii_exec(struct mfii_softc *, struct mfii_ccb *);
429 static void		mfii_exec_done(struct mfii_softc *, struct mfii_ccb *);
430 static int		mfii_my_intr(struct mfii_softc *);
431 static int		mfii_intr(void *);
432 static void		mfii_postq(struct mfii_softc *);
433 
434 static int		mfii_load_ccb(struct mfii_softc *, struct mfii_ccb *,
435 			    void *, int);
436 static int		mfii_load_mfa(struct mfii_softc *, struct mfii_ccb *,
437 			    void *, int);
438 
439 static int		mfii_mfa_poll(struct mfii_softc *, struct mfii_ccb *);
440 
441 static int		mfii_mgmt(struct mfii_softc *, uint32_t,
442 			    const union mfi_mbox *, void *, size_t,
443 			    mfii_direction_t, bool);
444 static int		mfii_do_mgmt(struct mfii_softc *, struct mfii_ccb *,
445 			    uint32_t, const union mfi_mbox *, void *, size_t,
446 			    mfii_direction_t, bool);
447 static void		mfii_empty_done(struct mfii_softc *, struct mfii_ccb *);
448 
449 static int		mfii_scsi_cmd_io(struct mfii_softc *,
450 			    struct mfii_ccb *, struct scsipi_xfer *);
451 static int		mfii_scsi_cmd_cdb(struct mfii_softc *,
452 			    struct mfii_ccb *, struct scsipi_xfer *);
453 static void		mfii_scsi_cmd_tmo(void *);
454 
455 static void		mfii_abort_task(struct work *, void *);
456 static void		mfii_abort(struct mfii_softc *, struct mfii_ccb *,
457 			    uint16_t, uint16_t, uint8_t, uint32_t);
458 static void		mfii_scsi_cmd_abort_done(struct mfii_softc *,
459 			    struct mfii_ccb *);
460 
461 static int		mfii_aen_register(struct mfii_softc *);
462 static void		mfii_aen_start(struct mfii_softc *, struct mfii_ccb *,
463 			    struct mfii_dmamem *, uint32_t);
464 static void		mfii_aen_done(struct mfii_softc *, struct mfii_ccb *);
465 static void		mfii_aen(struct work *, void *);
466 static void		mfii_aen_unregister(struct mfii_softc *);
467 
468 static void		mfii_aen_pd_insert(struct mfii_softc *,
469 			    const struct mfi_evtarg_pd_address *);
470 static void		mfii_aen_pd_remove(struct mfii_softc *,
471 			    const struct mfi_evtarg_pd_address *);
472 static void		mfii_aen_pd_state_change(struct mfii_softc *,
473 			    const struct mfi_evtarg_pd_state *);
474 static void		mfii_aen_ld_update(struct mfii_softc *);
475 
476 #if NBIO > 0
477 static int	mfii_ioctl(device_t, u_long, void *);
478 static int	mfii_ioctl_inq(struct mfii_softc *, struct bioc_inq *);
479 static int	mfii_ioctl_vol(struct mfii_softc *, struct bioc_vol *);
480 static int	mfii_ioctl_disk(struct mfii_softc *, struct bioc_disk *);
481 static int	mfii_ioctl_alarm(struct mfii_softc *, struct bioc_alarm *);
482 static int	mfii_ioctl_blink(struct mfii_softc *sc, struct bioc_blink *);
483 static int	mfii_ioctl_setstate(struct mfii_softc *,
484 		    struct bioc_setstate *);
485 static int	mfii_bio_hs(struct mfii_softc *, int, int, void *);
486 static int	mfii_bio_getitall(struct mfii_softc *);
487 #endif /* NBIO > 0 */
488 
489 #if 0
490 static const char *mfi_bbu_indicators[] = {
491 	"pack missing",
492 	"voltage low",
493 	"temp high",
494 	"charge active",
495 	"discharge active",
496 	"learn cycle req'd",
497 	"learn cycle active",
498 	"learn cycle failed",
499 	"learn cycle timeout",
500 	"I2C errors",
501 	"replace pack",
502 	"low capacity",
503 	"periodic learn req'd"
504 };
505 #endif
506 
507 static void	mfii_init_ld_sensor(struct mfii_softc *, envsys_data_t *, int);
508 static void	mfii_refresh_ld_sensor(struct mfii_softc *, envsys_data_t *);
509 static void	mfii_attach_sensor(struct mfii_softc *, envsys_data_t *);
510 static int	mfii_create_sensors(struct mfii_softc *);
511 static int	mfii_destroy_sensors(struct mfii_softc *);
512 static void	mfii_refresh_sensor(struct sysmon_envsys *, envsys_data_t *);
513 static void	mfii_bbu(struct mfii_softc *, envsys_data_t *);
514 
515 /*
516  * mfii boards support asynchronous (and non-polled) completion of
517  * dcmds by proxying them through a passthru mpii command that points
518  * at a dcmd frame. since the passthru command is submitted like
519  * the scsi commands using an SMID in the request descriptor,
520  * ccb_request memory * must contain the passthru command because
521  * that is what the SMID refers to. this means ccb_request cannot
522  * contain the dcmd. rather than allocating separate dma memory to
523  * hold the dcmd, we reuse the sense memory buffer for it.
524  */
525 
526 static void	mfii_dcmd_start(struct mfii_softc *, struct mfii_ccb *);
527 
528 static inline void
529 mfii_dcmd_scrub(struct mfii_ccb *ccb)
530 {
531 	memset(ccb->ccb_sense, 0, sizeof(*ccb->ccb_sense));
532 }
533 
534 static inline struct mfi_dcmd_frame *
535 mfii_dcmd_frame(struct mfii_ccb *ccb)
536 {
537 	CTASSERT(sizeof(struct mfi_dcmd_frame) <= sizeof(*ccb->ccb_sense));
538 	return ((struct mfi_dcmd_frame *)ccb->ccb_sense);
539 }
540 
541 static inline void
542 mfii_dcmd_sync(struct mfii_softc *sc, struct mfii_ccb *ccb, int flags)
543 {
544 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sense),
545 	    ccb->ccb_sense_offset, sizeof(*ccb->ccb_sense), flags);
546 }
547 
548 #define mfii_fw_state(_sc) mfii_read((_sc), MFI_OSP)
549 
550 static const struct mfii_iop mfii_iop_thunderbolt = {
551 	MFII_BAR,
552 	MFII_IOP_NUM_SGE_LOC_ORIG,
553 	0,
554 	MFII_REQ_TYPE_LDIO,
555 	0,
556 	MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA,
557 	0
558 };
559 
560 /*
561  * a lot of these values depend on us not implementing fastpath yet.
562  */
563 static const struct mfii_iop mfii_iop_25 = {
564 	MFII_BAR,
565 	MFII_IOP_NUM_SGE_LOC_ORIG,
566 	MFII_RAID_CTX_RL_FLAGS_CPU0, /* | MFII_RAID_CTX_RL_FLAGS_SEQNO_EN */
567 	MFII_REQ_TYPE_NO_LOCK,
568 	MFII_RAID_CTX_TYPE_CUDA | 0x1,
569 	MFII_SGE_CHAIN_ELEMENT,
570 	MFII_SGE_END_OF_LIST
571 };
572 
573 static const struct mfii_iop mfii_iop_35 = {
574 	MFII_BAR_35,
575 	MFII_IOP_NUM_SGE_LOC_35,
576 	MFII_RAID_CTX_ROUTING_FLAGS_CPU0, /* | MFII_RAID_CTX_ROUTING_FLAGS_SQN */
577 	MFII_REQ_TYPE_NO_LOCK,
578 	MFII_RAID_CTX_TYPE_CUDA | 0x1,
579 	MFII_SGE_CHAIN_ELEMENT,
580 	MFII_SGE_END_OF_LIST
581 };
582 
583 struct mfii_device {
584 	pcireg_t		mpd_vendor;
585 	pcireg_t		mpd_product;
586 	const struct mfii_iop	*mpd_iop;
587 };
588 
589 static const struct mfii_device mfii_devices[] = {
590 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_2208,
591 	    &mfii_iop_thunderbolt },
592 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3008,
593 	    &mfii_iop_25 },
594 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3108,
595 	    &mfii_iop_25 },
596 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3404,
597 	    &mfii_iop_35 },
598 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3504,
599 	    &mfii_iop_35 },
600 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3408,
601 	    &mfii_iop_35 },
602 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3508,
603 	    &mfii_iop_35 },
604 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3416,
605 	    &mfii_iop_35 },
606 	{ PCI_VENDOR_SYMBIOS,	PCI_PRODUCT_SYMBIOS_MEGARAID_3516,
607 	    &mfii_iop_35 }
608 };
609 
610 static const struct mfii_iop *mfii_find_iop(struct pci_attach_args *);
611 
612 static const struct mfii_iop *
613 mfii_find_iop(struct pci_attach_args *pa)
614 {
615 	const struct mfii_device *mpd;
616 	int i;
617 
618 	for (i = 0; i < __arraycount(mfii_devices); i++) {
619 		mpd = &mfii_devices[i];
620 
621 		if (mpd->mpd_vendor == PCI_VENDOR(pa->pa_id) &&
622 		    mpd->mpd_product == PCI_PRODUCT(pa->pa_id))
623 			return (mpd->mpd_iop);
624 	}
625 
626 	return (NULL);
627 }
628 
629 static int
630 mfii_match(device_t parent, cfdata_t match, void *aux)
631 {
632 	return ((mfii_find_iop(aux) != NULL) ? 2 : 0);
633 }
634 
635 static void
636 mfii_attach(device_t parent, device_t self, void *aux)
637 {
638 	struct mfii_softc *sc = device_private(self);
639 	struct pci_attach_args *pa = aux;
640 	pcireg_t memtype;
641 	pci_intr_handle_t ih;
642 	char intrbuf[PCI_INTRSTR_LEN];
643 	const char *intrstr;
644 	u_int32_t status, scpad2, scpad3;
645 	int chain_frame_sz, nsge_in_io, nsge_in_chain, i;
646 	struct scsipi_adapter *adapt = &sc->sc_adapt;
647 	struct scsipi_channel *chan = &sc->sc_chan;
648 
649 	/* init sc */
650 	sc->sc_dev = self;
651 	sc->sc_iop = mfii_find_iop(aux);
652 	sc->sc_dmat = pa->pa_dmat;
653 	if (pci_dma64_available(pa)) {
654 		sc->sc_dmat64 = pa->pa_dmat64;
655 		sc->sc_64bit_dma = 1;
656 	} else {
657 		sc->sc_dmat64 = pa->pa_dmat;
658 		sc->sc_64bit_dma = 0;
659 	}
660 	SIMPLEQ_INIT(&sc->sc_ccb_freeq);
661 	mutex_init(&sc->sc_ccb_mtx, MUTEX_DEFAULT, IPL_BIO);
662 	mutex_init(&sc->sc_post_mtx, MUTEX_DEFAULT, IPL_BIO);
663 	mutex_init(&sc->sc_reply_postq_mtx, MUTEX_DEFAULT, IPL_BIO);
664 
665 	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
666 
667 	sc->sc_aen_ccb = NULL;
668 	snprintf(intrbuf, sizeof(intrbuf) - 1, "%saen", device_xname(self));
669 	workqueue_create(&sc->sc_aen_wq, intrbuf, mfii_aen, sc,
670 	    PRI_BIO, IPL_BIO, WQ_MPSAFE);
671 
672 	snprintf(intrbuf, sizeof(intrbuf) - 1, "%sabrt", device_xname(self));
673 	workqueue_create(&sc->sc_abort_wq, intrbuf, mfii_abort_task,
674 	    sc, PRI_BIO, IPL_BIO, WQ_MPSAFE);
675 
676 	mutex_init(&sc->sc_abort_mtx, MUTEX_DEFAULT, IPL_BIO);
677 	SIMPLEQ_INIT(&sc->sc_abort_list);
678 
679 	/* wire up the bus shizz */
680 	memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, sc->sc_iop->bar);
681 	memtype |= PCI_MAPREG_MEM_TYPE_32BIT;
682 	if (pci_mapreg_map(pa, sc->sc_iop->bar, memtype, 0,
683 	    &sc->sc_iot, &sc->sc_ioh, NULL, &sc->sc_ios)) {
684 		aprint_error(": unable to map registers\n");
685 		return;
686 	}
687 
688 	/* disable interrupts */
689 	mfii_write(sc, MFI_OMSK, 0xffffffff);
690 
691 	if (pci_intr_map(pa, &ih) != 0) {
692 		aprint_error(": unable to map interrupt\n");
693 		goto pci_unmap;
694 	}
695 	intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf));
696 	pci_intr_setattr(pa->pa_pc, &ih, PCI_INTR_MPSAFE, true);
697 
698 	/* lets get started */
699 	if (mfii_transition_firmware(sc))
700 		goto pci_unmap;
701 	sc->sc_running = true;
702 
703 	/* determine max_cmds (refer to the Linux megaraid_sas driver) */
704 	scpad3 = mfii_read(sc, MFII_OSP3);
705 	status = mfii_fw_state(sc);
706 	sc->sc_max_fw_cmds = scpad3 & MFI_STATE_MAXCMD_MASK;
707 	if (sc->sc_max_fw_cmds == 0)
708 		sc->sc_max_fw_cmds = status & MFI_STATE_MAXCMD_MASK;
709 	/*
710 	 * reduce max_cmds by 1 to ensure that the reply queue depth does not
711 	 * exceed FW supplied max_fw_cmds.
712 	 */
713 	sc->sc_max_cmds = uimin(sc->sc_max_fw_cmds, 1024) - 1;
714 
715 	/* determine max_sgl (refer to the Linux megaraid_sas driver) */
716 	scpad2 = mfii_read(sc, MFII_OSP2);
717 	chain_frame_sz =
718 		((scpad2 & MFII_MAX_CHAIN_MASK) >> MFII_MAX_CHAIN_SHIFT) *
719 		((scpad2 & MFII_MAX_CHAIN_UNIT) ? MFII_1MB_IO : MFII_256K_IO);
720 	if (chain_frame_sz < MFII_CHAIN_FRAME_MIN)
721 		chain_frame_sz = MFII_CHAIN_FRAME_MIN;
722 
723 	nsge_in_io = (MFII_REQUEST_SIZE -
724 		sizeof(struct mpii_msg_scsi_io) -
725 		sizeof(struct mfii_raid_context)) / sizeof(struct mfii_sge);
726 	nsge_in_chain = chain_frame_sz / sizeof(struct mfii_sge);
727 
728 	/* round down to nearest power of two */
729 	sc->sc_max_sgl = 1;
730 	while ((sc->sc_max_sgl << 1) <= (nsge_in_io + nsge_in_chain))
731 		sc->sc_max_sgl <<= 1;
732 
733 	DNPRINTF(MFII_D_MISC, "%s: OSP 0x%08x, OSP2 0x%08x, OSP3 0x%08x\n",
734 	    DEVNAME(sc), status, scpad2, scpad3);
735 	DNPRINTF(MFII_D_MISC, "%s: max_fw_cmds %d, max_cmds %d\n",
736 	    DEVNAME(sc), sc->sc_max_fw_cmds, sc->sc_max_cmds);
737 	DNPRINTF(MFII_D_MISC, "%s: nsge_in_io %d, nsge_in_chain %d, "
738 	    "max_sgl %d\n", DEVNAME(sc), nsge_in_io, nsge_in_chain,
739 	    sc->sc_max_sgl);
740 
741 	/* sense memory */
742 	CTASSERT(sizeof(struct mfi_sense) == MFI_SENSE_SIZE);
743 	sc->sc_sense = mfii_dmamem_alloc(sc, sc->sc_max_cmds * MFI_SENSE_SIZE);
744 	if (sc->sc_sense == NULL) {
745 		aprint_error(": unable to allocate sense memory\n");
746 		goto pci_unmap;
747 	}
748 
749 	/* reply post queue */
750 	sc->sc_reply_postq_depth = roundup(sc->sc_max_fw_cmds, 16);
751 
752 	sc->sc_reply_postq = mfii_dmamem_alloc(sc,
753 	    sc->sc_reply_postq_depth * sizeof(struct mpii_reply_descr));
754 	if (sc->sc_reply_postq == NULL)
755 		goto free_sense;
756 
757 	memset(MFII_DMA_KVA(sc->sc_reply_postq), 0xff,
758 	    MFII_DMA_LEN(sc->sc_reply_postq));
759 
760 	/* MPII request frame array */
761 	sc->sc_requests = mfii_dmamem_alloc(sc,
762 	    MFII_REQUEST_SIZE * (sc->sc_max_cmds + 1));
763 	if (sc->sc_requests == NULL)
764 		goto free_reply_postq;
765 
766 	/* MFI command frame array */
767 	sc->sc_mfi = mfii_dmamem_alloc(sc, sc->sc_max_cmds * MFI_FRAME_SIZE);
768 	if (sc->sc_mfi == NULL)
769 		goto free_requests;
770 
771 	/* MPII SGL array */
772 	sc->sc_sgl = mfii_dmamem_alloc(sc, sc->sc_max_cmds *
773 	    sizeof(struct mfii_sge) * sc->sc_max_sgl);
774 	if (sc->sc_sgl == NULL)
775 		goto free_mfi;
776 
777 	if (mfii_init_ccb(sc) != 0) {
778 		aprint_error(": could not init ccb list\n");
779 		goto free_sgl;
780 	}
781 
782 	/* kickstart firmware with all addresses and pointers */
783 	if (mfii_initialise_firmware(sc) != 0) {
784 		aprint_error(": could not initialize firmware\n");
785 		goto free_sgl;
786 	}
787 
788 	mutex_enter(&sc->sc_lock);
789 	if (mfii_get_info(sc) != 0) {
790 		mutex_exit(&sc->sc_lock);
791 		aprint_error(": could not retrieve controller information\n");
792 		goto free_sgl;
793 	}
794 	mutex_exit(&sc->sc_lock);
795 
796 	aprint_normal(": \"%s\", firmware %s",
797 	    sc->sc_info.mci_product_name, sc->sc_info.mci_package_version);
798 	if (le16toh(sc->sc_info.mci_memory_size) > 0) {
799 		aprint_normal(", %uMB cache",
800 		    le16toh(sc->sc_info.mci_memory_size));
801 	}
802 	aprint_normal("\n");
803 	aprint_naive("\n");
804 
805 	sc->sc_ih = pci_intr_establish_xname(sc->sc_pc, ih, IPL_BIO,
806 	    mfii_intr, sc, DEVNAME(sc));
807 	if (sc->sc_ih == NULL) {
808 		aprint_error_dev(self, "can't establish interrupt");
809 		if (intrstr)
810 			aprint_error(" at %s", intrstr);
811 		aprint_error("\n");
812 		goto free_sgl;
813 	}
814 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
815 
816 	for (i = 0; i < sc->sc_info.mci_lds_present; i++)
817 		sc->sc_ld[i].ld_present = 1;
818 
819 	memset(adapt, 0, sizeof(*adapt));
820 	adapt->adapt_dev = sc->sc_dev;
821 	adapt->adapt_nchannels = 1;
822 	/* keep a few commands for management */
823 	if (sc->sc_max_cmds > 4)
824 		adapt->adapt_openings = sc->sc_max_cmds - 4;
825 	else
826 		adapt->adapt_openings = sc->sc_max_cmds;
827 	adapt->adapt_max_periph = adapt->adapt_openings;
828 	adapt->adapt_request = mfii_scsipi_request;
829 	adapt->adapt_minphys = minphys;
830 	adapt->adapt_flags = SCSIPI_ADAPT_MPSAFE;
831 
832 	memset(chan, 0, sizeof(*chan));
833 	chan->chan_adapter = adapt;
834 	chan->chan_bustype = &scsi_sas_bustype;
835 	chan->chan_channel = 0;
836 	chan->chan_flags = 0;
837 	chan->chan_nluns = 8;
838 	chan->chan_ntargets = sc->sc_info.mci_max_lds;
839 	chan->chan_id = sc->sc_info.mci_max_lds;
840 
841 	mfii_rescan(sc->sc_dev, "scsi", NULL);
842 
843 	if (mfii_aen_register(sc) != 0) {
844 		/* error printed by mfii_aen_register */
845 		goto intr_disestablish;
846 	}
847 
848 	mutex_enter(&sc->sc_lock);
849 	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, NULL, &sc->sc_ld_list,
850 	    sizeof(sc->sc_ld_list), MFII_DATA_IN, true) != 0) {
851 		mutex_exit(&sc->sc_lock);
852 		aprint_error_dev(self,
853 		    "getting list of logical disks failed\n");
854 		goto intr_disestablish;
855 	}
856 	mutex_exit(&sc->sc_lock);
857 	memset(sc->sc_target_lds, -1, sizeof(sc->sc_target_lds));
858 	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
859 		int target = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
860 		sc->sc_target_lds[target] = i;
861 	}
862 
863 	/* enable interrupts */
864 	mfii_write(sc, MFI_OSTS, 0xffffffff);
865 	mfii_write(sc, MFI_OMSK, ~MFII_OSTS_INTR_VALID);
866 
867 #if NBIO > 0
868 	if (bio_register(sc->sc_dev, mfii_ioctl) != 0)
869 		panic("%s: controller registration failed", DEVNAME(sc));
870 #endif /* NBIO > 0 */
871 
872 	if (mfii_create_sensors(sc) != 0)
873 		aprint_error_dev(self, "unable to create sensors\n");
874 
875 	if (!pmf_device_register1(sc->sc_dev, mfii_suspend, mfii_resume,
876 	    mfii_shutdown))
877 		aprint_error_dev(self, "couldn't establish power handler\n");
878 	return;
879 intr_disestablish:
880 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
881 free_sgl:
882 	mfii_dmamem_free(sc, sc->sc_sgl);
883 free_mfi:
884 	mfii_dmamem_free(sc, sc->sc_mfi);
885 free_requests:
886 	mfii_dmamem_free(sc, sc->sc_requests);
887 free_reply_postq:
888 	mfii_dmamem_free(sc, sc->sc_reply_postq);
889 free_sense:
890 	mfii_dmamem_free(sc, sc->sc_sense);
891 pci_unmap:
892 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
893 }
894 
895 #if 0
896 struct srp_gc mfii_dev_handles_gc =
897     SRP_GC_INITIALIZER(mfii_dev_handles_dtor, NULL);
898 
899 static inline uint16_t
900 mfii_dev_handle(struct mfii_softc *sc, uint16_t target)
901 {
902 	struct srp_ref sr;
903 	uint16_t *map, handle;
904 
905 	map = srp_enter(&sr, &sc->sc_pd->pd_dev_handles);
906 	handle = map[target];
907 	srp_leave(&sr);
908 
909 	return (handle);
910 }
911 
912 static int
913 mfii_dev_handles_update(struct mfii_softc *sc)
914 {
915 	struct mfii_ld_map *lm;
916 	uint16_t *dev_handles = NULL;
917 	int i;
918 	int rv = 0;
919 
920 	lm = malloc(sizeof(*lm), M_TEMP, M_WAITOK|M_ZERO);
921 
922 	rv = mfii_mgmt(sc, MR_DCMD_LD_MAP_GET_INFO, NULL, lm, sizeof(*lm),
923 	    MFII_DATA_IN, false);
924 
925 	if (rv != 0) {
926 		rv = EIO;
927 		goto free_lm;
928 	}
929 
930 	dev_handles = mallocarray(MFI_MAX_PD, sizeof(*dev_handles),
931 	    M_DEVBUF, M_WAITOK);
932 
933 	for (i = 0; i < MFI_MAX_PD; i++)
934 		dev_handles[i] = lm->mlm_dev_handle[i].mdh_cur_handle;
935 
936 	/* commit the updated info */
937 	sc->sc_pd->pd_timeout = lm->mlm_pd_timeout;
938 	srp_update_locked(&mfii_dev_handles_gc,
939 	    &sc->sc_pd->pd_dev_handles, dev_handles);
940 
941 free_lm:
942 	free(lm, M_TEMP, sizeof(*lm));
943 
944 	return (rv);
945 }
946 
947 static void
948 mfii_dev_handles_dtor(void *null, void *v)
949 {
950 	uint16_t *dev_handles = v;
951 
952 	free(dev_handles, M_DEVBUF, sizeof(*dev_handles) * MFI_MAX_PD);
953 }
954 #endif /* 0 */
955 
956 static int
957 mfii_detach(device_t self, int flags)
958 {
959 	struct mfii_softc *sc = device_private(self);
960 	int error;
961 
962 	if (sc->sc_ih == NULL)
963 		return (0);
964 
965 	if ((error = config_detach_children(sc->sc_dev, flags)) != 0)
966 		return error;
967 
968 	mfii_destroy_sensors(sc);
969 #if NBIO > 0
970 	bio_unregister(sc->sc_dev);
971 #endif
972 	mfii_shutdown(sc->sc_dev, 0);
973 	mfii_write(sc, MFI_OMSK, 0xffffffff);
974 
975 	mfii_aen_unregister(sc);
976 	pci_intr_disestablish(sc->sc_pc, sc->sc_ih);
977 	mfii_dmamem_free(sc, sc->sc_sgl);
978 	mfii_dmamem_free(sc, sc->sc_mfi);
979 	mfii_dmamem_free(sc, sc->sc_requests);
980 	mfii_dmamem_free(sc, sc->sc_reply_postq);
981 	mfii_dmamem_free(sc, sc->sc_sense);
982 	bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios);
983 
984 	return (0);
985 }
986 
987 static int
988 mfii_rescan(device_t self, const char *ifattr, const int *locators)
989 {
990 	struct mfii_softc *sc = device_private(self);
991 	if (sc->sc_child != NULL)
992 		return 0;
993 
994 	sc->sc_child = config_found_sm_loc(self, ifattr, locators, &sc->sc_chan,
995 	    scsiprint, NULL);
996 	return 0;
997 }
998 
999 static void
1000 mfii_childdetached(device_t self, device_t child)
1001 {
1002 	struct mfii_softc *sc = device_private(self);
1003 
1004 	KASSERT(self == sc->sc_dev);
1005 	KASSERT(child == sc->sc_child);
1006 
1007 	if (child == sc->sc_child)
1008 		sc->sc_child = NULL;
1009 }
1010 
1011 static bool
1012 mfii_suspend(device_t dev, const pmf_qual_t *q)
1013 {
1014 	/* XXX to be implemented */
1015 	return false;
1016 }
1017 
1018 static bool
1019 mfii_resume(device_t dev, const pmf_qual_t *q)
1020 {
1021 	/* XXX to be implemented */
1022 	return false;
1023 }
1024 
1025 static bool
1026 mfii_shutdown(device_t dev, int how)
1027 {
1028 	struct mfii_softc	*sc = device_private(dev);
1029 	struct mfii_ccb *ccb;
1030 	union mfi_mbox		mbox;
1031 	bool rv = true;
1032 
1033 	memset(&mbox, 0, sizeof(mbox));
1034 
1035 	mutex_enter(&sc->sc_lock);
1036 	DNPRINTF(MFI_D_MISC, "%s: mfii_shutdown\n", DEVNAME(sc));
1037 	ccb = mfii_get_ccb(sc);
1038 	if (ccb == NULL)
1039 		return false;
1040 	mutex_enter(&sc->sc_ccb_mtx);
1041 	if (sc->sc_running) {
1042 		sc->sc_running = 0; /* prevent new commands */
1043 		mutex_exit(&sc->sc_ccb_mtx);
1044 #if 0 /* XXX why does this hang ? */
1045 		mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
1046 		mfii_scrub_ccb(ccb);
1047 		if (mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_CACHE_FLUSH, &mbox,
1048 		    NULL, 0, MFII_DATA_NONE, true)) {
1049 			aprint_error_dev(dev, "shutdown: cache flush failed\n");
1050 			rv = false;
1051 			goto fail;
1052 		}
1053 		printf("ok1\n");
1054 #endif
1055 		mbox.b[0] = 0;
1056 		mfii_scrub_ccb(ccb);
1057 		if (mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_SHUTDOWN, &mbox,
1058 		    NULL, 0, MFII_DATA_NONE, true)) {
1059 			aprint_error_dev(dev, "shutdown: "
1060 			    "firmware shutdown failed\n");
1061 		    	rv = false;
1062 			goto fail;
1063 		}
1064 	} else {
1065 		mutex_exit(&sc->sc_ccb_mtx);
1066 	}
1067 fail:
1068 	mfii_put_ccb(sc, ccb);
1069 	mutex_exit(&sc->sc_lock);
1070 	return rv;
1071 }
1072 
1073 static u_int32_t
1074 mfii_read(struct mfii_softc *sc, bus_size_t r)
1075 {
1076 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1077 	    BUS_SPACE_BARRIER_READ);
1078 	return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r));
1079 }
1080 
1081 static void
1082 mfii_write(struct mfii_softc *sc, bus_size_t r, u_int32_t v)
1083 {
1084 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
1085 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
1086 	    BUS_SPACE_BARRIER_WRITE);
1087 }
1088 
1089 static struct mfii_dmamem *
1090 mfii_dmamem_alloc(struct mfii_softc *sc, size_t size)
1091 {
1092 	struct mfii_dmamem *m;
1093 	int nsegs;
1094 
1095 	m = malloc(sizeof(*m), M_DEVBUF, M_WAITOK | M_ZERO);
1096 	m->mdm_size = size;
1097 
1098 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
1099 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &m->mdm_map) != 0)
1100 		goto mdmfree;
1101 
1102 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &m->mdm_seg, 1,
1103 	    &nsegs, BUS_DMA_NOWAIT) != 0)
1104 		goto destroy;
1105 
1106 	if (bus_dmamem_map(sc->sc_dmat, &m->mdm_seg, nsegs, size, &m->mdm_kva,
1107 	    BUS_DMA_NOWAIT) != 0)
1108 		goto free;
1109 
1110 	if (bus_dmamap_load(sc->sc_dmat, m->mdm_map, m->mdm_kva, size, NULL,
1111 	    BUS_DMA_NOWAIT) != 0)
1112 		goto unmap;
1113 
1114 	memset(m->mdm_kva, 0, size);
1115 	return (m);
1116 
1117 unmap:
1118 	bus_dmamem_unmap(sc->sc_dmat, m->mdm_kva, m->mdm_size);
1119 free:
1120 	bus_dmamem_free(sc->sc_dmat, &m->mdm_seg, 1);
1121 destroy:
1122 	bus_dmamap_destroy(sc->sc_dmat, m->mdm_map);
1123 mdmfree:
1124 	free(m, M_DEVBUF);
1125 
1126 	return (NULL);
1127 }
1128 
1129 static void
1130 mfii_dmamem_free(struct mfii_softc *sc, struct mfii_dmamem *m)
1131 {
1132 	bus_dmamap_unload(sc->sc_dmat, m->mdm_map);
1133 	bus_dmamem_unmap(sc->sc_dmat, m->mdm_kva, m->mdm_size);
1134 	bus_dmamem_free(sc->sc_dmat, &m->mdm_seg, 1);
1135 	bus_dmamap_destroy(sc->sc_dmat, m->mdm_map);
1136 	free(m, M_DEVBUF);
1137 }
1138 
1139 static void
1140 mfii_dcmd_start(struct mfii_softc *sc, struct mfii_ccb *ccb)
1141 {
1142 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
1143 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
1144 	struct mfii_sge *sge = (struct mfii_sge *)(ctx + 1);
1145 
1146 	io->function = MFII_FUNCTION_PASSTHRU_IO;
1147 	io->sgl_offset0 = (uint32_t *)sge - (uint32_t *)io;
1148 	io->chain_offset = io->sgl_offset0 / 4;
1149 
1150 	sge->sg_addr = htole64(ccb->ccb_sense_dva);
1151 	sge->sg_len = htole32(sizeof(*ccb->ccb_sense));
1152 	sge->sg_flags = MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA;
1153 
1154 	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
1155 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
1156 
1157 	mfii_start(sc, ccb);
1158 }
1159 
1160 static int
1161 mfii_aen_register(struct mfii_softc *sc)
1162 {
1163 	struct mfi_evt_log_info mel;
1164 	struct mfii_ccb *ccb;
1165 	struct mfii_dmamem *mdm;
1166 	int rv;
1167 
1168 	ccb = mfii_get_ccb(sc);
1169 	if (ccb == NULL) {
1170 		printf("%s: unable to allocate ccb for aen\n", DEVNAME(sc));
1171 		return (ENOMEM);
1172 	}
1173 
1174 	memset(&mel, 0, sizeof(mel));
1175 	mfii_scrub_ccb(ccb);
1176 
1177 	rv = mfii_do_mgmt(sc, ccb, MR_DCMD_CTRL_EVENT_GET_INFO, NULL,
1178 	    &mel, sizeof(mel), MFII_DATA_IN, true);
1179 	if (rv != 0) {
1180 		mfii_put_ccb(sc, ccb);
1181 		aprint_error_dev(sc->sc_dev, "unable to get event info\n");
1182 		return (EIO);
1183 	}
1184 
1185 	mdm = mfii_dmamem_alloc(sc, sizeof(struct mfi_evt_detail));
1186 	if (mdm == NULL) {
1187 		mfii_put_ccb(sc, ccb);
1188 		aprint_error_dev(sc->sc_dev, "unable to allocate event data\n");
1189 		return (ENOMEM);
1190 	}
1191 
1192 	/* replay all the events from boot */
1193 	mfii_aen_start(sc, ccb, mdm, le32toh(mel.mel_boot_seq_num));
1194 
1195 	return (0);
1196 }
1197 
1198 static void
1199 mfii_aen_start(struct mfii_softc *sc, struct mfii_ccb *ccb,
1200     struct mfii_dmamem *mdm, uint32_t seq)
1201 {
1202 	struct mfi_dcmd_frame *dcmd = mfii_dcmd_frame(ccb);
1203 	struct mfi_frame_header *hdr = &dcmd->mdf_header;
1204 	union mfi_sgl *sgl = &dcmd->mdf_sgl;
1205 	union mfi_evt_class_locale mec;
1206 
1207 	mfii_scrub_ccb(ccb);
1208 	mfii_dcmd_scrub(ccb);
1209 	memset(MFII_DMA_KVA(mdm), 0, MFII_DMA_LEN(mdm));
1210 
1211 	ccb->ccb_cookie = mdm;
1212 	ccb->ccb_done = mfii_aen_done;
1213 	sc->sc_aen_ccb = ccb;
1214 
1215 	mec.mec_members.class = MFI_EVT_CLASS_DEBUG;
1216 	mec.mec_members.reserved = 0;
1217 	mec.mec_members.locale = htole16(MFI_EVT_LOCALE_ALL);
1218 
1219 	hdr->mfh_cmd = MFI_CMD_DCMD;
1220 	hdr->mfh_sg_count = 1;
1221 	hdr->mfh_flags = htole16(MFI_FRAME_DIR_READ | MFI_FRAME_SGL64);
1222 	hdr->mfh_data_len = htole32(MFII_DMA_LEN(mdm));
1223 	dcmd->mdf_opcode = htole32(MR_DCMD_CTRL_EVENT_WAIT);
1224 	dcmd->mdf_mbox.w[0] = htole32(seq);
1225 	dcmd->mdf_mbox.w[1] = htole32(mec.mec_word);
1226 	sgl->sg64[0].addr = htole64(MFII_DMA_DVA(mdm));
1227 	sgl->sg64[0].len = htole32(MFII_DMA_LEN(mdm));
1228 
1229 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(mdm),
1230 	    0, MFII_DMA_LEN(mdm), BUS_DMASYNC_PREREAD);
1231 
1232 	mfii_dcmd_sync(sc, ccb, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
1233 	mfii_dcmd_start(sc, ccb);
1234 }
1235 
1236 static void
1237 mfii_aen_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1238 {
1239 	KASSERT(sc->sc_aen_ccb == ccb);
1240 
1241 	/*
1242 	 * defer to a thread with KERNEL_LOCK so we can run autoconf
1243 	 * We shouldn't have more than one AEN command pending at a time,
1244 	 * so no need to lock
1245 	 */
1246 	if (sc->sc_running)
1247 		workqueue_enqueue(sc->sc_aen_wq, &sc->sc_aen_work, NULL);
1248 }
1249 
1250 static void
1251 mfii_aen(struct work *wk, void *arg)
1252 {
1253 	struct mfii_softc *sc = arg;
1254 	struct mfii_ccb *ccb = sc->sc_aen_ccb;
1255 	struct mfii_dmamem *mdm = ccb->ccb_cookie;
1256 	const struct mfi_evt_detail *med = MFII_DMA_KVA(mdm);
1257 
1258 	mfii_dcmd_sync(sc, ccb,
1259 	    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
1260 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(mdm),
1261 	    0, MFII_DMA_LEN(mdm), BUS_DMASYNC_POSTREAD);
1262 
1263 	DNPRINTF(MFII_D_MISC, "%s: %u %08x %02x %s\n", DEVNAME(sc),
1264 	    le32toh(med->med_seq_num), le32toh(med->med_code),
1265 	    med->med_arg_type, med->med_description);
1266 
1267 	switch (le32toh(med->med_code)) {
1268 	case MR_EVT_PD_INSERTED_EXT:
1269 		if (med->med_arg_type != MR_EVT_ARGS_PD_ADDRESS)
1270 			break;
1271 
1272 		mfii_aen_pd_insert(sc, &med->args.pd_address);
1273 		break;
1274  	case MR_EVT_PD_REMOVED_EXT:
1275 		if (med->med_arg_type != MR_EVT_ARGS_PD_ADDRESS)
1276 			break;
1277 
1278 		mfii_aen_pd_remove(sc, &med->args.pd_address);
1279 		break;
1280 
1281 	case MR_EVT_PD_STATE_CHANGE:
1282 		if (med->med_arg_type != MR_EVT_ARGS_PD_STATE)
1283 			break;
1284 
1285 		mfii_aen_pd_state_change(sc, &med->args.pd_state);
1286 		break;
1287 
1288 	case MR_EVT_LD_CREATED:
1289 	case MR_EVT_LD_DELETED:
1290 		mfii_aen_ld_update(sc);
1291 		break;
1292 
1293 	default:
1294 		break;
1295 	}
1296 
1297 	mfii_aen_start(sc, ccb, mdm, le32toh(med->med_seq_num) + 1);
1298 }
1299 
1300 static void
1301 mfii_aen_pd_insert(struct mfii_softc *sc,
1302     const struct mfi_evtarg_pd_address *pd)
1303 {
1304 	printf("%s: physical disk inserted id %d enclosure %d\n", DEVNAME(sc),
1305 	    le16toh(pd->device_id), le16toh(pd->encl_id));
1306 }
1307 
1308 static void
1309 mfii_aen_pd_remove(struct mfii_softc *sc,
1310     const struct mfi_evtarg_pd_address *pd)
1311 {
1312 	printf("%s: physical disk removed id %d enclosure %d\n", DEVNAME(sc),
1313 	    le16toh(pd->device_id), le16toh(pd->encl_id));
1314 }
1315 
1316 static void
1317 mfii_aen_pd_state_change(struct mfii_softc *sc,
1318     const struct mfi_evtarg_pd_state *state)
1319 {
1320 	return;
1321 }
1322 
1323 static void
1324 mfii_aen_ld_update(struct mfii_softc *sc)
1325 {
1326 	int i, target, old, nld;
1327 	int newlds[MFI_MAX_LD];
1328 
1329 	mutex_enter(&sc->sc_lock);
1330 	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, NULL, &sc->sc_ld_list,
1331 	    sizeof(sc->sc_ld_list), MFII_DATA_IN, false) != 0) {
1332 		mutex_exit(&sc->sc_lock);
1333 		DNPRINTF(MFII_D_MISC, "%s: getting list of logical disks failed\n",
1334 		    DEVNAME(sc));
1335 		return;
1336 	}
1337 	mutex_exit(&sc->sc_lock);
1338 
1339 	memset(newlds, -1, sizeof(newlds));
1340 
1341 	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
1342 		target = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
1343 		DNPRINTF(MFII_D_MISC, "%s: target %d: state %d\n",
1344 		    DEVNAME(sc), target, sc->sc_ld_list.mll_list[i].mll_state);
1345 		newlds[target] = i;
1346 	}
1347 
1348 	for (i = 0; i < MFI_MAX_LD; i++) {
1349 		old = sc->sc_target_lds[i];
1350 		nld = newlds[i];
1351 
1352 		if (old == -1 && nld != -1) {
1353 			printf("%s: logical drive %d added (target %d)\n",
1354 			    DEVNAME(sc), i, nld);
1355 
1356 			// XXX scsi_probe_target(sc->sc_scsibus, i);
1357 
1358 			mfii_init_ld_sensor(sc, &sc->sc_sensors[i], i);
1359 			mfii_attach_sensor(sc, &sc->sc_sensors[i]);
1360 		} else if (nld == -1 && old != -1) {
1361 			printf("%s: logical drive %d removed (target %d)\n",
1362 			    DEVNAME(sc), i, old);
1363 
1364 			scsipi_target_detach(&sc->sc_chan, i, 0, DETACH_FORCE);
1365 			sysmon_envsys_sensor_detach(sc->sc_sme,
1366 			    &sc->sc_sensors[i]);
1367 		}
1368 	}
1369 
1370 	memcpy(sc->sc_target_lds, newlds, sizeof(sc->sc_target_lds));
1371 }
1372 
1373 static void
1374 mfii_aen_unregister(struct mfii_softc *sc)
1375 {
1376 	/* XXX */
1377 }
1378 
1379 static int
1380 mfii_transition_firmware(struct mfii_softc *sc)
1381 {
1382 	int32_t			fw_state, cur_state;
1383 	int			max_wait, i;
1384 
1385 	fw_state = mfii_fw_state(sc) & MFI_STATE_MASK;
1386 
1387 	while (fw_state != MFI_STATE_READY) {
1388 		cur_state = fw_state;
1389 		switch (fw_state) {
1390 		case MFI_STATE_FAULT:
1391 			printf("%s: firmware fault\n", DEVNAME(sc));
1392 			return (1);
1393 		case MFI_STATE_WAIT_HANDSHAKE:
1394 			mfii_write(sc, MFI_SKINNY_IDB,
1395 			    MFI_INIT_CLEAR_HANDSHAKE);
1396 			max_wait = 2;
1397 			break;
1398 		case MFI_STATE_OPERATIONAL:
1399 			mfii_write(sc, MFI_SKINNY_IDB, MFI_INIT_READY);
1400 			max_wait = 10;
1401 			break;
1402 		case MFI_STATE_UNDEFINED:
1403 		case MFI_STATE_BB_INIT:
1404 			max_wait = 2;
1405 			break;
1406 		case MFI_STATE_FW_INIT:
1407 		case MFI_STATE_DEVICE_SCAN:
1408 		case MFI_STATE_FLUSH_CACHE:
1409 			max_wait = 20;
1410 			break;
1411 		default:
1412 			printf("%s: unknown firmware state %d\n",
1413 			    DEVNAME(sc), fw_state);
1414 			return (1);
1415 		}
1416 		for (i = 0; i < (max_wait * 10); i++) {
1417 			fw_state = mfii_fw_state(sc) & MFI_STATE_MASK;
1418 			if (fw_state == cur_state)
1419 				DELAY(100000);
1420 			else
1421 				break;
1422 		}
1423 		if (fw_state == cur_state) {
1424 			printf("%s: firmware stuck in state %#x\n",
1425 			    DEVNAME(sc), fw_state);
1426 			return (1);
1427 		}
1428 	}
1429 
1430 	return (0);
1431 }
1432 
1433 static int
1434 mfii_get_info(struct mfii_softc *sc)
1435 {
1436 	int i, rv;
1437 
1438 	rv = mfii_mgmt(sc, MR_DCMD_CTRL_GET_INFO, NULL, &sc->sc_info,
1439 	    sizeof(sc->sc_info), MFII_DATA_IN, true);
1440 
1441 	if (rv != 0)
1442 		return (rv);
1443 
1444 	for (i = 0; i < sc->sc_info.mci_image_component_count; i++) {
1445 		DPRINTF("%s: active FW %s Version %s date %s time %s\n",
1446 		    DEVNAME(sc),
1447 		    sc->sc_info.mci_image_component[i].mic_name,
1448 		    sc->sc_info.mci_image_component[i].mic_version,
1449 		    sc->sc_info.mci_image_component[i].mic_build_date,
1450 		    sc->sc_info.mci_image_component[i].mic_build_time);
1451 	}
1452 
1453 	for (i = 0; i < sc->sc_info.mci_pending_image_component_count; i++) {
1454 		DPRINTF("%s: pending FW %s Version %s date %s time %s\n",
1455 		    DEVNAME(sc),
1456 		    sc->sc_info.mci_pending_image_component[i].mic_name,
1457 		    sc->sc_info.mci_pending_image_component[i].mic_version,
1458 		    sc->sc_info.mci_pending_image_component[i].mic_build_date,
1459 		    sc->sc_info.mci_pending_image_component[i].mic_build_time);
1460 	}
1461 
1462 	DPRINTF("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n",
1463 	    DEVNAME(sc),
1464 	    sc->sc_info.mci_max_arms,
1465 	    sc->sc_info.mci_max_spans,
1466 	    sc->sc_info.mci_max_arrays,
1467 	    sc->sc_info.mci_max_lds,
1468 	    sc->sc_info.mci_product_name);
1469 
1470 	DPRINTF("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n",
1471 	    DEVNAME(sc),
1472 	    sc->sc_info.mci_serial_number,
1473 	    sc->sc_info.mci_hw_present,
1474 	    sc->sc_info.mci_current_fw_time,
1475 	    sc->sc_info.mci_max_cmds,
1476 	    sc->sc_info.mci_max_sg_elements);
1477 
1478 	DPRINTF("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n",
1479 	    DEVNAME(sc),
1480 	    sc->sc_info.mci_max_request_size,
1481 	    sc->sc_info.mci_lds_present,
1482 	    sc->sc_info.mci_lds_degraded,
1483 	    sc->sc_info.mci_lds_offline,
1484 	    sc->sc_info.mci_pd_present);
1485 
1486 	DPRINTF("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n",
1487 	    DEVNAME(sc),
1488 	    sc->sc_info.mci_pd_disks_present,
1489 	    sc->sc_info.mci_pd_disks_pred_failure,
1490 	    sc->sc_info.mci_pd_disks_failed);
1491 
1492 	DPRINTF("%s: nvram %d mem %d flash %d\n",
1493 	    DEVNAME(sc),
1494 	    sc->sc_info.mci_nvram_size,
1495 	    sc->sc_info.mci_memory_size,
1496 	    sc->sc_info.mci_flash_size);
1497 
1498 	DPRINTF("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n",
1499 	    DEVNAME(sc),
1500 	    sc->sc_info.mci_ram_correctable_errors,
1501 	    sc->sc_info.mci_ram_uncorrectable_errors,
1502 	    sc->sc_info.mci_cluster_allowed,
1503 	    sc->sc_info.mci_cluster_active);
1504 
1505 	DPRINTF("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n",
1506 	    DEVNAME(sc),
1507 	    sc->sc_info.mci_max_strips_per_io,
1508 	    sc->sc_info.mci_raid_levels,
1509 	    sc->sc_info.mci_adapter_ops,
1510 	    sc->sc_info.mci_ld_ops);
1511 
1512 	DPRINTF("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n",
1513 	    DEVNAME(sc),
1514 	    sc->sc_info.mci_stripe_sz_ops.min,
1515 	    sc->sc_info.mci_stripe_sz_ops.max,
1516 	    sc->sc_info.mci_pd_ops,
1517 	    sc->sc_info.mci_pd_mix_support);
1518 
1519 	DPRINTF("%s: ecc_bucket %d pckg_prop %s\n",
1520 	    DEVNAME(sc),
1521 	    sc->sc_info.mci_ecc_bucket_count,
1522 	    sc->sc_info.mci_package_version);
1523 
1524 	DPRINTF("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n",
1525 	    DEVNAME(sc),
1526 	    sc->sc_info.mci_properties.mcp_seq_num,
1527 	    sc->sc_info.mci_properties.mcp_pred_fail_poll_interval,
1528 	    sc->sc_info.mci_properties.mcp_intr_throttle_cnt,
1529 	    sc->sc_info.mci_properties.mcp_intr_throttle_timeout);
1530 
1531 	DPRINTF("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n",
1532 	    DEVNAME(sc),
1533 	    sc->sc_info.mci_properties.mcp_rebuild_rate,
1534 	    sc->sc_info.mci_properties.mcp_patrol_read_rate,
1535 	    sc->sc_info.mci_properties.mcp_bgi_rate,
1536 	    sc->sc_info.mci_properties.mcp_cc_rate);
1537 
1538 	DPRINTF("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n",
1539 	    DEVNAME(sc),
1540 	    sc->sc_info.mci_properties.mcp_recon_rate,
1541 	    sc->sc_info.mci_properties.mcp_cache_flush_interval,
1542 	    sc->sc_info.mci_properties.mcp_spinup_drv_cnt,
1543 	    sc->sc_info.mci_properties.mcp_spinup_delay,
1544 	    sc->sc_info.mci_properties.mcp_cluster_enable);
1545 
1546 	DPRINTF("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n",
1547 	    DEVNAME(sc),
1548 	    sc->sc_info.mci_properties.mcp_coercion_mode,
1549 	    sc->sc_info.mci_properties.mcp_alarm_enable,
1550 	    sc->sc_info.mci_properties.mcp_disable_auto_rebuild,
1551 	    sc->sc_info.mci_properties.mcp_disable_battery_warn,
1552 	    sc->sc_info.mci_properties.mcp_ecc_bucket_size);
1553 
1554 	DPRINTF("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n",
1555 	    DEVNAME(sc),
1556 	    sc->sc_info.mci_properties.mcp_ecc_bucket_leak_rate,
1557 	    sc->sc_info.mci_properties.mcp_restore_hotspare_on_insertion,
1558 	    sc->sc_info.mci_properties.mcp_expose_encl_devices);
1559 
1560 	DPRINTF("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n",
1561 	    DEVNAME(sc),
1562 	    sc->sc_info.mci_pci.mip_vendor,
1563 	    sc->sc_info.mci_pci.mip_device,
1564 	    sc->sc_info.mci_pci.mip_subvendor,
1565 	    sc->sc_info.mci_pci.mip_subdevice);
1566 
1567 	DPRINTF("%s: type %#x port_count %d port_addr ",
1568 	    DEVNAME(sc),
1569 	    sc->sc_info.mci_host.mih_type,
1570 	    sc->sc_info.mci_host.mih_port_count);
1571 
1572 	for (i = 0; i < 8; i++)
1573 		DPRINTF("%.0" PRIx64 " ", sc->sc_info.mci_host.mih_port_addr[i]);
1574 	DPRINTF("\n");
1575 
1576 	DPRINTF("%s: type %.x port_count %d port_addr ",
1577 	    DEVNAME(sc),
1578 	    sc->sc_info.mci_device.mid_type,
1579 	    sc->sc_info.mci_device.mid_port_count);
1580 
1581 	for (i = 0; i < 8; i++)
1582 		DPRINTF("%.0" PRIx64 " ", sc->sc_info.mci_device.mid_port_addr[i]);
1583 	DPRINTF("\n");
1584 
1585 	return (0);
1586 }
1587 
1588 static int
1589 mfii_mfa_poll(struct mfii_softc *sc, struct mfii_ccb *ccb)
1590 {
1591 	struct mfi_frame_header	*hdr = ccb->ccb_request;
1592 	u_int64_t r;
1593 	int to = 0, rv = 0;
1594 
1595 #ifdef DIAGNOSTIC
1596 	if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL)
1597 		panic("mfii_mfa_poll called with cookie or done set");
1598 #endif
1599 
1600 	hdr->mfh_context = ccb->ccb_smid;
1601 	hdr->mfh_cmd_status = MFI_STAT_INVALID_STATUS;
1602 	hdr->mfh_flags |= htole16(MFI_FRAME_DONT_POST_IN_REPLY_QUEUE);
1603 
1604 	r = MFII_REQ_MFA(ccb->ccb_request_dva);
1605 	memcpy(&ccb->ccb_req, &r, sizeof(ccb->ccb_req));
1606 
1607 	mfii_start(sc, ccb);
1608 
1609 	for (;;) {
1610 		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
1611 		    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
1612 		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1613 
1614 		if (hdr->mfh_cmd_status != MFI_STAT_INVALID_STATUS)
1615 			break;
1616 
1617 		if (to++ > 5000) { /* XXX 5 seconds busywait sucks */
1618 			printf("%s: timeout on ccb %d\n", DEVNAME(sc),
1619 			    ccb->ccb_smid);
1620 			ccb->ccb_flags |= MFI_CCB_F_ERR;
1621 			rv = 1;
1622 			break;
1623 		}
1624 
1625 		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
1626 		    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
1627 		    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1628 
1629 		delay(1000);
1630 	}
1631 
1632 	if (ccb->ccb_len > 0) {
1633 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap32,
1634 		    0, ccb->ccb_dmamap32->dm_mapsize,
1635 		    (ccb->ccb_direction == MFII_DATA_IN) ?
1636 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1637 
1638 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap32);
1639 	}
1640 
1641 	return (rv);
1642 }
1643 
1644 static int
1645 mfii_poll(struct mfii_softc *sc, struct mfii_ccb *ccb)
1646 {
1647 	void (*done)(struct mfii_softc *, struct mfii_ccb *);
1648 	void *cookie;
1649 	int rv = 1;
1650 
1651 	done = ccb->ccb_done;
1652 	cookie = ccb->ccb_cookie;
1653 
1654 	ccb->ccb_done = mfii_poll_done;
1655 	ccb->ccb_cookie = &rv;
1656 
1657 	mfii_start(sc, ccb);
1658 
1659 	do {
1660 		delay(10);
1661 		mfii_postq(sc);
1662 	} while (rv == 1);
1663 
1664 	ccb->ccb_cookie = cookie;
1665 	done(sc, ccb);
1666 
1667 	return (0);
1668 }
1669 
1670 static void
1671 mfii_poll_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1672 {
1673 	int *rv = ccb->ccb_cookie;
1674 
1675 	*rv = 0;
1676 }
1677 
1678 static int
1679 mfii_exec(struct mfii_softc *sc, struct mfii_ccb *ccb)
1680 {
1681 #ifdef DIAGNOSTIC
1682 	if (ccb->ccb_cookie != NULL || ccb->ccb_done != NULL)
1683 		panic("mfii_exec called with cookie or done set");
1684 #endif
1685 
1686 	ccb->ccb_cookie = ccb;
1687 	ccb->ccb_done = mfii_exec_done;
1688 
1689 	mfii_start(sc, ccb);
1690 
1691 	mutex_enter(&ccb->ccb_mtx);
1692 	while (ccb->ccb_cookie != NULL)
1693 		cv_wait(&ccb->ccb_cv, &ccb->ccb_mtx);
1694 	mutex_exit(&ccb->ccb_mtx);
1695 
1696 	return (0);
1697 }
1698 
1699 static void
1700 mfii_exec_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1701 {
1702 	mutex_enter(&ccb->ccb_mtx);
1703 	ccb->ccb_cookie = NULL;
1704 	cv_signal(&ccb->ccb_cv);
1705 	mutex_exit(&ccb->ccb_mtx);
1706 }
1707 
1708 static int
1709 mfii_mgmt(struct mfii_softc *sc, uint32_t opc, const union mfi_mbox *mbox,
1710     void *buf, size_t len, mfii_direction_t dir, bool poll)
1711 {
1712 	struct mfii_ccb *ccb;
1713 	int rv;
1714 
1715 	KASSERT(mutex_owned(&sc->sc_lock));
1716 	if (!sc->sc_running)
1717 		return EAGAIN;
1718 
1719 	ccb = mfii_get_ccb(sc);
1720 	if (ccb == NULL)
1721 		return (ENOMEM);
1722 
1723 	mfii_scrub_ccb(ccb);
1724 	rv = mfii_do_mgmt(sc, ccb, opc, mbox, buf, len, dir, poll);
1725 	mfii_put_ccb(sc, ccb);
1726 
1727 	return (rv);
1728 }
1729 
1730 static int
1731 mfii_do_mgmt(struct mfii_softc *sc, struct mfii_ccb *ccb, uint32_t opc,
1732     const union mfi_mbox *mbox, void *buf, size_t len, mfii_direction_t dir,
1733     bool poll)
1734 {
1735 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
1736 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
1737 	struct mfii_sge *sge = (struct mfii_sge *)(ctx + 1);
1738 	struct mfi_dcmd_frame *dcmd = ccb->ccb_mfi;
1739 	struct mfi_frame_header *hdr = &dcmd->mdf_header;
1740 	int rv = EIO;
1741 
1742 	if (cold)
1743 		poll = true;
1744 
1745 	ccb->ccb_data = buf;
1746 	ccb->ccb_len = len;
1747 	ccb->ccb_direction = dir;
1748 	switch (dir) {
1749 	case MFII_DATA_IN:
1750 		hdr->mfh_flags = htole16(MFI_FRAME_DIR_READ);
1751 		break;
1752 	case MFII_DATA_OUT:
1753 		hdr->mfh_flags = htole16(MFI_FRAME_DIR_WRITE);
1754 		break;
1755 	case MFII_DATA_NONE:
1756 		hdr->mfh_flags = htole16(MFI_FRAME_DIR_NONE);
1757 		break;
1758 	}
1759 
1760 	if (mfii_load_mfa(sc, ccb, &dcmd->mdf_sgl, poll) != 0) {
1761 		rv = ENOMEM;
1762 		goto done;
1763 	}
1764 
1765 	hdr->mfh_cmd = MFI_CMD_DCMD;
1766 	hdr->mfh_context = ccb->ccb_smid;
1767 	hdr->mfh_data_len = htole32(len);
1768 	hdr->mfh_sg_count = ccb->ccb_dmamap32->dm_nsegs;
1769 	KASSERT(!ccb->ccb_dma64);
1770 
1771 	dcmd->mdf_opcode = opc;
1772 	/* handle special opcodes */
1773 	if (mbox != NULL)
1774 		memcpy(&dcmd->mdf_mbox, mbox, sizeof(dcmd->mdf_mbox));
1775 
1776 	io->function = MFII_FUNCTION_PASSTHRU_IO;
1777 	io->sgl_offset0 = ((u_int8_t *)sge - (u_int8_t *)io) / 4;
1778 	io->chain_offset = ((u_int8_t *)sge - (u_int8_t *)io) / 16;
1779 
1780 	sge->sg_addr = htole64(ccb->ccb_mfi_dva);
1781 	sge->sg_len = htole32(MFI_FRAME_SIZE);
1782 	sge->sg_flags = MFII_SGE_CHAIN_ELEMENT | MFII_SGE_ADDR_IOCPLBNTA;
1783 
1784 	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
1785 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
1786 
1787 	if (poll) {
1788 		ccb->ccb_done = mfii_empty_done;
1789 		mfii_poll(sc, ccb);
1790 	} else
1791 		mfii_exec(sc, ccb);
1792 
1793 	if (hdr->mfh_cmd_status == MFI_STAT_OK) {
1794 		rv = 0;
1795 	}
1796 
1797 done:
1798 	return (rv);
1799 }
1800 
1801 static void
1802 mfii_empty_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1803 {
1804 	return;
1805 }
1806 
1807 static int
1808 mfii_load_mfa(struct mfii_softc *sc, struct mfii_ccb *ccb,
1809     void *sglp, int nosleep)
1810 {
1811 	union mfi_sgl *sgl = sglp;
1812 	bus_dmamap_t dmap = ccb->ccb_dmamap32;
1813 	int error;
1814 	int i;
1815 
1816 	KASSERT(!ccb->ccb_dma64);
1817 	if (ccb->ccb_len == 0)
1818 		return (0);
1819 
1820 	error = bus_dmamap_load(sc->sc_dmat, dmap,
1821 	    ccb->ccb_data, ccb->ccb_len, NULL,
1822 	    nosleep ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
1823 	if (error) {
1824 		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
1825 		return (1);
1826 	}
1827 
1828 	for (i = 0; i < dmap->dm_nsegs; i++) {
1829 		sgl->sg32[i].addr = htole32(dmap->dm_segs[i].ds_addr);
1830 		sgl->sg32[i].len = htole32(dmap->dm_segs[i].ds_len);
1831 	}
1832 
1833 	bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize,
1834 	    ccb->ccb_direction == MFII_DATA_OUT ?
1835 	    BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
1836 
1837 	return (0);
1838 }
1839 
1840 static void
1841 mfii_start(struct mfii_softc *sc, struct mfii_ccb *ccb)
1842 {
1843 	u_long *r = (u_long *)&ccb->ccb_req;
1844 
1845 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
1846 	    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
1847 	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1848 
1849 #if defined(__LP64__) && 0
1850 	bus_space_write_8(sc->sc_iot, sc->sc_ioh, MFI_IQPL, *r);
1851 #else
1852 	mutex_enter(&sc->sc_post_mtx);
1853 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MFI_IQPL, r[0]);
1854 	bus_space_barrier(sc->sc_iot, sc->sc_ioh,
1855 	    MFI_IQPL, 8, BUS_SPACE_BARRIER_WRITE);
1856 
1857 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, MFI_IQPH, r[1]);
1858 	bus_space_barrier(sc->sc_iot, sc->sc_ioh,
1859 	    MFI_IQPH, 8, BUS_SPACE_BARRIER_WRITE);
1860 	mutex_exit(&sc->sc_post_mtx);
1861 #endif
1862 }
1863 
1864 static void
1865 mfii_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
1866 {
1867 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_requests),
1868 	    ccb->ccb_request_offset, MFII_REQUEST_SIZE,
1869 	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1870 
1871 	if (ccb->ccb_sgl_len > 0) {
1872 		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sgl),
1873 		    ccb->ccb_sgl_offset, ccb->ccb_sgl_len,
1874 		    BUS_DMASYNC_POSTWRITE);
1875 	}
1876 
1877 	if (ccb->ccb_dma64) {
1878 		KASSERT(ccb->ccb_len > 0);
1879 		bus_dmamap_sync(sc->sc_dmat64, ccb->ccb_dmamap64,
1880 		    0, ccb->ccb_dmamap64->dm_mapsize,
1881 		    (ccb->ccb_direction == MFII_DATA_IN) ?
1882 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1883 
1884 		bus_dmamap_unload(sc->sc_dmat64, ccb->ccb_dmamap64);
1885 	} else if (ccb->ccb_len > 0) {
1886 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap32,
1887 		    0, ccb->ccb_dmamap32->dm_mapsize,
1888 		    (ccb->ccb_direction == MFII_DATA_IN) ?
1889 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1890 
1891 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap32);
1892 	}
1893 
1894 	ccb->ccb_done(sc, ccb);
1895 }
1896 
1897 static int
1898 mfii_initialise_firmware(struct mfii_softc *sc)
1899 {
1900 	struct mpii_msg_iocinit_request *iiq;
1901 	struct mfii_dmamem *m;
1902 	struct mfii_ccb *ccb;
1903 	struct mfi_init_frame *init;
1904 	int rv;
1905 
1906 	m = mfii_dmamem_alloc(sc, sizeof(*iiq));
1907 	if (m == NULL)
1908 		return (1);
1909 
1910 	iiq = MFII_DMA_KVA(m);
1911 	memset(iiq, 0, sizeof(*iiq));
1912 
1913 	iiq->function = MPII_FUNCTION_IOC_INIT;
1914 	iiq->whoinit = MPII_WHOINIT_HOST_DRIVER;
1915 
1916 	iiq->msg_version_maj = 0x02;
1917 	iiq->msg_version_min = 0x00;
1918 	iiq->hdr_version_unit = 0x10;
1919 	iiq->hdr_version_dev = 0x0;
1920 
1921 	iiq->system_request_frame_size = htole16(MFII_REQUEST_SIZE / 4);
1922 
1923 	iiq->reply_descriptor_post_queue_depth =
1924 	    htole16(sc->sc_reply_postq_depth);
1925 	iiq->reply_free_queue_depth = htole16(0);
1926 
1927 	iiq->sense_buffer_address_high = htole32(
1928 	    MFII_DMA_DVA(sc->sc_sense) >> 32);
1929 
1930 	iiq->reply_descriptor_post_queue_address_lo =
1931 	    htole32(MFII_DMA_DVA(sc->sc_reply_postq));
1932 	iiq->reply_descriptor_post_queue_address_hi =
1933 	    htole32(MFII_DMA_DVA(sc->sc_reply_postq) >> 32);
1934 
1935 	iiq->system_request_frame_base_address_lo =
1936 	    htole32(MFII_DMA_DVA(sc->sc_requests));
1937 	iiq->system_request_frame_base_address_hi =
1938 	    htole32(MFII_DMA_DVA(sc->sc_requests) >> 32);
1939 
1940 	iiq->timestamp = htole64(time_uptime);
1941 
1942 	ccb = mfii_get_ccb(sc);
1943 	if (ccb == NULL) {
1944 		/* shouldn't ever run out of ccbs during attach */
1945 		return (1);
1946 	}
1947 	mfii_scrub_ccb(ccb);
1948 	init = ccb->ccb_request;
1949 
1950 	init->mif_header.mfh_cmd = MFI_CMD_INIT;
1951 	init->mif_header.mfh_data_len = htole32(sizeof(*iiq));
1952 	init->mif_qinfo_new_addr_lo = htole32(MFII_DMA_DVA(m));
1953 	init->mif_qinfo_new_addr_hi = htole32((uint64_t)MFII_DMA_DVA(m) >> 32);
1954 
1955 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
1956 	    0, MFII_DMA_LEN(sc->sc_reply_postq),
1957 	    BUS_DMASYNC_PREREAD);
1958 
1959 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(m),
1960 	    0, sizeof(*iiq), BUS_DMASYNC_PREREAD);
1961 
1962 	rv = mfii_mfa_poll(sc, ccb);
1963 
1964 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(m),
1965 	    0, sizeof(*iiq), BUS_DMASYNC_POSTREAD);
1966 
1967 	mfii_put_ccb(sc, ccb);
1968 	mfii_dmamem_free(sc, m);
1969 
1970 	return (rv);
1971 }
1972 
1973 static int
1974 mfii_my_intr(struct mfii_softc *sc)
1975 {
1976 	u_int32_t status;
1977 
1978 	status = mfii_read(sc, MFI_OSTS);
1979 
1980 	DNPRINTF(MFII_D_INTR, "%s: intr status 0x%x\n", DEVNAME(sc), status);
1981 	if (ISSET(status, 0x1)) {
1982 		mfii_write(sc, MFI_OSTS, status);
1983 		return (1);
1984 	}
1985 
1986 	return (ISSET(status, MFII_OSTS_INTR_VALID) ? 1 : 0);
1987 }
1988 
1989 static int
1990 mfii_intr(void *arg)
1991 {
1992 	struct mfii_softc *sc = arg;
1993 
1994 	if (!mfii_my_intr(sc))
1995 		return (0);
1996 
1997 	mfii_postq(sc);
1998 
1999 	return (1);
2000 }
2001 
2002 static void
2003 mfii_postq(struct mfii_softc *sc)
2004 {
2005 	struct mfii_ccb_list ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs);
2006 	struct mpii_reply_descr *postq = MFII_DMA_KVA(sc->sc_reply_postq);
2007 	struct mpii_reply_descr *rdp;
2008 	struct mfii_ccb *ccb;
2009 	int rpi = 0;
2010 
2011 	mutex_enter(&sc->sc_reply_postq_mtx);
2012 
2013 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
2014 	    0, MFII_DMA_LEN(sc->sc_reply_postq),
2015 	    BUS_DMASYNC_POSTREAD);
2016 
2017 	for (;;) {
2018 		rdp = &postq[sc->sc_reply_postq_index];
2019 		DNPRINTF(MFII_D_INTR, "%s: mfii_postq index %d flags 0x%x data 0x%x\n",
2020 		    DEVNAME(sc), sc->sc_reply_postq_index, rdp->reply_flags,
2021 			rdp->data == 0xffffffff);
2022 		if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) ==
2023 		    MPII_REPLY_DESCR_UNUSED)
2024 			break;
2025 		if (rdp->data == 0xffffffff) {
2026 			/*
2027 			 * ioc is still writing to the reply post queue
2028 			 * race condition - bail!
2029 			 */
2030 			break;
2031 		}
2032 
2033 		ccb = &sc->sc_ccb[le16toh(rdp->smid) - 1];
2034 		SIMPLEQ_INSERT_TAIL(&ccbs, ccb, ccb_link);
2035 		memset(rdp, 0xff, sizeof(*rdp));
2036 
2037 		sc->sc_reply_postq_index++;
2038 		sc->sc_reply_postq_index %= sc->sc_reply_postq_depth;
2039 		rpi = 1;
2040 	}
2041 
2042 	bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_reply_postq),
2043 	    0, MFII_DMA_LEN(sc->sc_reply_postq),
2044 	    BUS_DMASYNC_PREREAD);
2045 
2046 	if (rpi)
2047 		mfii_write(sc, MFII_RPI, sc->sc_reply_postq_index);
2048 
2049 	mutex_exit(&sc->sc_reply_postq_mtx);
2050 
2051 	while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) {
2052 		SIMPLEQ_REMOVE_HEAD(&ccbs, ccb_link);
2053 		mfii_done(sc, ccb);
2054 	}
2055 }
2056 
2057 static void
2058 mfii_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req,
2059     void *arg)
2060 {
2061 	struct scsipi_periph    *periph;
2062 	struct scsipi_xfer	*xs;
2063 	struct scsipi_adapter   *adapt = chan->chan_adapter;
2064 	struct mfii_softc	*sc = device_private(adapt->adapt_dev);
2065 	struct mfii_ccb *ccb;
2066 	int timeout;
2067 	int target;
2068 
2069 	switch(req) {
2070 		case ADAPTER_REQ_GROW_RESOURCES:
2071 		/* Not supported. */
2072 		return;
2073 	case ADAPTER_REQ_SET_XFER_MODE:
2074 	{
2075 		struct scsipi_xfer_mode *xm = arg;
2076 		xm->xm_mode = PERIPH_CAP_TQING;
2077 		xm->xm_period = 0;
2078 		xm->xm_offset = 0;
2079 		scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm);
2080 		return;
2081 	}
2082 	case ADAPTER_REQ_RUN_XFER:
2083 		break;
2084 	}
2085 
2086 	xs = arg;
2087 	periph = xs->xs_periph;
2088 	target = periph->periph_target;
2089 
2090 	if (target >= MFI_MAX_LD || !sc->sc_ld[target].ld_present ||
2091 	    periph->periph_lun != 0) {
2092 		xs->error = XS_SELTIMEOUT;
2093 		scsipi_done(xs);
2094 		return;
2095 	}
2096 
2097 	if ((xs->cmd->opcode == SCSI_SYNCHRONIZE_CACHE_10 ||
2098 	    xs->cmd->opcode == SCSI_SYNCHRONIZE_CACHE_16) && sc->sc_bbuok) {
2099 		/* the cache is stable storage, don't flush */
2100 		xs->error = XS_NOERROR;
2101 		xs->status = SCSI_OK;
2102 		xs->resid = 0;
2103 		scsipi_done(xs);
2104 		return;
2105 	}
2106 
2107 	ccb = mfii_get_ccb(sc);
2108 	if (ccb == NULL) {
2109 		xs->error = XS_RESOURCE_SHORTAGE;
2110 		scsipi_done(xs);
2111 		return;
2112 	}
2113 	mfii_scrub_ccb(ccb);
2114 	ccb->ccb_cookie = xs;
2115 	ccb->ccb_done = mfii_scsi_cmd_done;
2116 	ccb->ccb_data = xs->data;
2117 	ccb->ccb_len = xs->datalen;
2118 
2119 	timeout = mstohz(xs->timeout);
2120 	if (timeout == 0)
2121 		timeout = 1;
2122 	callout_reset(&xs->xs_callout, timeout, mfii_scsi_cmd_tmo, ccb);
2123 
2124 	switch (xs->cmd->opcode) {
2125 	case SCSI_READ_6_COMMAND:
2126 	case READ_10:
2127 	case READ_12:
2128 	case READ_16:
2129 	case SCSI_WRITE_6_COMMAND:
2130 	case WRITE_10:
2131 	case WRITE_12:
2132 	case WRITE_16:
2133 		if (mfii_scsi_cmd_io(sc, ccb, xs) != 0)
2134 			goto stuffup;
2135 		break;
2136 
2137 	default:
2138 		if (mfii_scsi_cmd_cdb(sc, ccb, xs) != 0)
2139 			goto stuffup;
2140 		break;
2141 	}
2142 
2143 	xs->error = XS_NOERROR;
2144 	xs->resid = 0;
2145 
2146 	DNPRINTF(MFII_D_CMD, "%s: start io %d cmd %d\n", DEVNAME(sc), target,
2147 	    xs->cmd->opcode);
2148 
2149 	if (xs->xs_control & XS_CTL_POLL) {
2150 		if (mfii_poll(sc, ccb) != 0)
2151 			goto stuffup;
2152 		return;
2153 	}
2154 
2155 	mfii_start(sc, ccb);
2156 
2157 	return;
2158 
2159 stuffup:
2160 	xs->error = XS_DRIVER_STUFFUP;
2161 	scsipi_done(xs);
2162 	mfii_put_ccb(sc, ccb);
2163 }
2164 
2165 static void
2166 mfii_scsi_cmd_done(struct mfii_softc *sc, struct mfii_ccb *ccb)
2167 {
2168 	struct scsipi_xfer *xs = ccb->ccb_cookie;
2169 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
2170 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
2171 
2172 	if (callout_stop(&xs->xs_callout) != 0)
2173 		return;
2174 
2175 	switch (ctx->status) {
2176 	case MFI_STAT_OK:
2177 		break;
2178 
2179 	case MFI_STAT_SCSI_DONE_WITH_ERROR:
2180 		xs->error = XS_SENSE;
2181 		memset(&xs->sense, 0, sizeof(xs->sense));
2182 		memcpy(&xs->sense, ccb->ccb_sense, sizeof(xs->sense));
2183 		break;
2184 
2185 	case MFI_STAT_LD_OFFLINE:
2186 	case MFI_STAT_DEVICE_NOT_FOUND:
2187 		xs->error = XS_SELTIMEOUT;
2188 		break;
2189 
2190 	default:
2191 		xs->error = XS_DRIVER_STUFFUP;
2192 		break;
2193 	}
2194 
2195 	scsipi_done(xs);
2196 	mfii_put_ccb(sc, ccb);
2197 }
2198 
2199 static int
2200 mfii_scsi_cmd_io(struct mfii_softc *sc, struct mfii_ccb *ccb,
2201     struct scsipi_xfer *xs)
2202 {
2203 	struct scsipi_periph *periph = xs->xs_periph;
2204 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
2205 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
2206 	int segs;
2207 
2208 	io->dev_handle = htole16(periph->periph_target);
2209 	io->function = MFII_FUNCTION_LDIO_REQUEST;
2210 	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
2211 	io->sgl_flags = htole16(0x02); /* XXX */
2212 	io->sense_buffer_length = sizeof(xs->sense);
2213 	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
2214 	io->data_length = htole32(xs->datalen);
2215 	io->io_flags = htole16(xs->cmdlen);
2216 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
2217 	case XS_CTL_DATA_IN:
2218 		ccb->ccb_direction = MFII_DATA_IN;
2219 		io->direction = MPII_SCSIIO_DIR_READ;
2220 		break;
2221 	case XS_CTL_DATA_OUT:
2222 		ccb->ccb_direction = MFII_DATA_OUT;
2223 		io->direction = MPII_SCSIIO_DIR_WRITE;
2224 		break;
2225 	default:
2226 		ccb->ccb_direction = MFII_DATA_NONE;
2227 		io->direction = MPII_SCSIIO_DIR_NONE;
2228 		break;
2229 	}
2230 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
2231 
2232 	ctx->type_nseg = sc->sc_iop->ldio_ctx_type_nseg;
2233 	ctx->timeout_value = htole16(0x14); /* XXX */
2234 	ctx->reg_lock_flags = htole16(sc->sc_iop->ldio_ctx_reg_lock_flags);
2235 	ctx->virtual_disk_target_id = htole16(periph->periph_target);
2236 
2237 	if (mfii_load_ccb(sc, ccb, ctx + 1,
2238 	    ISSET(xs->xs_control, XS_CTL_NOSLEEP)) != 0)
2239 		return (1);
2240 
2241 	KASSERT(ccb->ccb_len == 0 || ccb->ccb_dma64);
2242 	segs = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap64->dm_nsegs;
2243 	switch (sc->sc_iop->num_sge_loc) {
2244 	case MFII_IOP_NUM_SGE_LOC_ORIG:
2245 		ctx->num_sge = segs;
2246 		break;
2247 	case MFII_IOP_NUM_SGE_LOC_35:
2248 		/* 12 bit field, but we're only using the lower 8 */
2249 		ctx->span_arm = segs;
2250 		break;
2251 	}
2252 
2253 	ccb->ccb_req.flags = sc->sc_iop->ldio_req_type;
2254 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
2255 
2256 	return (0);
2257 }
2258 
2259 static int
2260 mfii_scsi_cmd_cdb(struct mfii_softc *sc, struct mfii_ccb *ccb,
2261     struct scsipi_xfer *xs)
2262 {
2263 	struct scsipi_periph *periph = xs->xs_periph;
2264 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
2265 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
2266 
2267 	io->dev_handle = htole16(periph->periph_target);
2268 	io->function = MFII_FUNCTION_LDIO_REQUEST;
2269 	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
2270 	io->sgl_flags = htole16(0x02); /* XXX */
2271 	io->sense_buffer_length = sizeof(xs->sense);
2272 	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
2273 	io->data_length = htole32(xs->datalen);
2274 	io->io_flags = htole16(xs->cmdlen);
2275 	io->lun[0] = htobe16(periph->periph_lun);
2276 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
2277 	case XS_CTL_DATA_IN:
2278 		ccb->ccb_direction = MFII_DATA_IN;
2279 		io->direction = MPII_SCSIIO_DIR_READ;
2280 		break;
2281 	case XS_CTL_DATA_OUT:
2282 		ccb->ccb_direction = MFII_DATA_OUT;
2283 		io->direction = MPII_SCSIIO_DIR_WRITE;
2284 		break;
2285 	default:
2286 		ccb->ccb_direction = MFII_DATA_NONE;
2287 		io->direction = MPII_SCSIIO_DIR_NONE;
2288 		break;
2289 	}
2290 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
2291 
2292 	ctx->virtual_disk_target_id = htole16(periph->periph_target);
2293 
2294 	if (mfii_load_ccb(sc, ccb, ctx + 1,
2295 	    ISSET(xs->xs_control, XS_CTL_NOSLEEP)) != 0)
2296 		return (1);
2297 
2298 	ctx->num_sge = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap64->dm_nsegs;
2299 	KASSERT(ccb->ccb_len == 0 || ccb->ccb_dma64);
2300 
2301 	ccb->ccb_req.flags = MFII_REQ_TYPE_SCSI;
2302 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
2303 
2304 	return (0);
2305 }
2306 
2307 #if 0
2308 void
2309 mfii_pd_scsi_cmd(struct scsipi_xfer *xs)
2310 {
2311 	struct scsi_link *link = xs->sc_link;
2312 	struct mfii_softc *sc = link->adapter_softc;
2313 	struct mfii_ccb *ccb = xs->io;
2314 
2315 	mfii_scrub_ccb(ccb);
2316 	ccb->ccb_cookie = xs;
2317 	ccb->ccb_done = mfii_scsi_cmd_done;
2318 	ccb->ccb_data = xs->data;
2319 	ccb->ccb_len = xs->datalen;
2320 
2321 	// XXX timeout_set(&xs->stimeout, mfii_scsi_cmd_tmo, xs);
2322 
2323 	xs->error = mfii_pd_scsi_cmd_cdb(sc, xs);
2324 	if (xs->error != XS_NOERROR)
2325 		goto done;
2326 
2327 	xs->resid = 0;
2328 
2329 	if (ISSET(xs->xs_control, XS_CTL_POLL)) {
2330 		if (mfii_poll(sc, ccb) != 0)
2331 			goto stuffup;
2332 		return;
2333 	}
2334 
2335 	// XXX timeout_add_msec(&xs->stimeout, xs->timeout);
2336 	mfii_start(sc, ccb);
2337 
2338 	return;
2339 
2340 stuffup:
2341 	xs->error = XS_DRIVER_STUFFUP;
2342 done:
2343 	scsi_done(xs);
2344 }
2345 
2346 int
2347 mfii_pd_scsi_probe(struct scsi_link *link)
2348 {
2349 	struct mfii_softc *sc = link->adapter_softc;
2350 	struct mfi_pd_details mpd;
2351 	union mfi_mbox mbox;
2352 	int rv;
2353 
2354 	if (link->lun > 0)
2355 		return (0);
2356 
2357 	memset(&mbox, 0, sizeof(mbox));
2358 	mbox.s[0] = htole16(link->target);
2359 
2360 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, &mpd, sizeof(mpd),
2361 	    MFII_DATA_IN, true);
2362 	if (rv != 0)
2363 		return (EIO);
2364 
2365 	if (mpd.mpd_fw_state != htole16(MFI_PD_SYSTEM))
2366 		return (ENXIO);
2367 
2368 	return (0);
2369 }
2370 
2371 int
2372 mfii_pd_scsi_cmd_cdb(struct mfii_softc *sc, struct mfii_ccb *ccb,
2373     struct scsipi_xfer *xs)
2374 {
2375 	struct scsi_link *link = xs->sc_link;
2376 	struct mpii_msg_scsi_io *io = ccb->ccb_request;
2377 	struct mfii_raid_context *ctx = (struct mfii_raid_context *)(io + 1);
2378 	uint16_t dev_handle;
2379 
2380 	dev_handle = mfii_dev_handle(sc, link->target);
2381 	if (dev_handle == htole16(0xffff))
2382 		return (XS_SELTIMEOUT);
2383 
2384 	io->dev_handle = dev_handle;
2385 	io->function = 0;
2386 	io->sense_buffer_low_address = htole32(ccb->ccb_sense_dva);
2387 	io->sgl_flags = htole16(0x02); /* XXX */
2388 	io->sense_buffer_length = sizeof(xs->sense);
2389 	io->sgl_offset0 = (sizeof(*io) + sizeof(*ctx)) / 4;
2390 	io->data_length = htole32(xs->datalen);
2391 	io->io_flags = htole16(xs->cmdlen);
2392 	io->lun[0] = htobe16(link->lun);
2393 	switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) {
2394 	case XS_CTL_DATA_IN:
2395 		ccb->ccb_direction = MFII_DATA_IN;
2396 		io->direction = MPII_SCSIIO_DIR_READ;
2397 		break;
2398 	case XS_CTL_DATA_OUT:
2399 		ccb->ccb_direction = MFII_DATA_OUT;
2400 		io->direction = MPII_SCSIIO_DIR_WRITE;
2401 		break;
2402 	default:
2403 		ccb->ccb_direction = MFII_DATA_NONE;
2404 		io->direction = MPII_SCSIIO_DIR_NONE;
2405 		break;
2406 	}
2407 	memcpy(io->cdb, xs->cmd, xs->cmdlen);
2408 
2409 	ctx->virtual_disk_target_id = htole16(link->target);
2410 	ctx->raid_flags = MFII_RAID_CTX_IO_TYPE_SYSPD;
2411 	ctx->timeout_value = sc->sc_pd->pd_timeout;
2412 
2413 	if (mfii_load_ccb(sc, ccb, ctx + 1,
2414 	    ISSET(xs->xs_control, XS_CTL_NOSLEEP)) != 0)
2415 		return (XS_DRIVER_STUFFUP);
2416 
2417 	ctx->num_sge = (ccb->ccb_len == 0) ? 0 : ccb->ccb_dmamap64->dm_nsegs;
2418 	KASSERT(ccb->ccb_dma64);
2419 
2420 	ccb->ccb_req.flags = MFII_REQ_TYPE_HI_PRI;
2421 	ccb->ccb_req.smid = le16toh(ccb->ccb_smid);
2422 	ccb->ccb_req.dev_handle = dev_handle;
2423 
2424 	return (XS_NOERROR);
2425 }
2426 #endif
2427 
2428 static int
2429 mfii_load_ccb(struct mfii_softc *sc, struct mfii_ccb *ccb, void *sglp,
2430     int nosleep)
2431 {
2432 	struct mpii_msg_request *req = ccb->ccb_request;
2433 	struct mfii_sge *sge = NULL, *nsge = sglp;
2434 	struct mfii_sge *ce = NULL;
2435 	bus_dmamap_t dmap = ccb->ccb_dmamap64;
2436 	u_int space;
2437 	int i;
2438 
2439 	int error;
2440 
2441 	if (ccb->ccb_len == 0)
2442 		return (0);
2443 
2444 	ccb->ccb_dma64 = true;
2445 	error = bus_dmamap_load(sc->sc_dmat64, dmap,
2446 	    ccb->ccb_data, ccb->ccb_len, NULL,
2447 	    nosleep ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK);
2448 	if (error) {
2449 		printf("%s: error %d loading dmamap\n", DEVNAME(sc), error);
2450 		return (1);
2451 	}
2452 
2453 	space = (MFII_REQUEST_SIZE - ((u_int8_t *)nsge - (u_int8_t *)req)) /
2454 	    sizeof(*nsge);
2455 	if (dmap->dm_nsegs > space) {
2456 		space--;
2457 
2458 		ccb->ccb_sgl_len = (dmap->dm_nsegs - space) * sizeof(*nsge);
2459 		memset(ccb->ccb_sgl, 0, ccb->ccb_sgl_len);
2460 
2461 		ce = nsge + space;
2462 		ce->sg_addr = htole64(ccb->ccb_sgl_dva);
2463 		ce->sg_len = htole32(ccb->ccb_sgl_len);
2464 		ce->sg_flags = sc->sc_iop->sge_flag_chain;
2465 
2466 		req->chain_offset = ((u_int8_t *)ce - (u_int8_t *)req) / 16;
2467 	}
2468 
2469 	for (i = 0; i < dmap->dm_nsegs; i++) {
2470 		if (nsge == ce)
2471 			nsge = ccb->ccb_sgl;
2472 
2473 		sge = nsge;
2474 
2475 		sge->sg_addr = htole64(dmap->dm_segs[i].ds_addr);
2476 		sge->sg_len = htole32(dmap->dm_segs[i].ds_len);
2477 		sge->sg_flags = MFII_SGE_ADDR_SYSTEM;
2478 
2479 		nsge = sge + 1;
2480 	}
2481 	sge->sg_flags |= sc->sc_iop->sge_flag_eol;
2482 
2483 	bus_dmamap_sync(sc->sc_dmat64, dmap, 0, dmap->dm_mapsize,
2484 	    ccb->ccb_direction == MFII_DATA_OUT ?
2485 	    BUS_DMASYNC_PREWRITE : BUS_DMASYNC_PREREAD);
2486 
2487 	if (ccb->ccb_sgl_len > 0) {
2488 		bus_dmamap_sync(sc->sc_dmat, MFII_DMA_MAP(sc->sc_sgl),
2489 		    ccb->ccb_sgl_offset, ccb->ccb_sgl_len,
2490 		    BUS_DMASYNC_PREWRITE);
2491 	}
2492 
2493 	return (0);
2494 }
2495 
2496 static void
2497 mfii_scsi_cmd_tmo(void *p)
2498 {
2499 	struct mfii_ccb *ccb = p;
2500 	struct mfii_softc *sc = ccb->ccb_sc;
2501 	bool start_abort;
2502 
2503 	printf("%s: cmd timeout ccb %p\n", DEVNAME(sc), p);
2504 
2505 	mutex_enter(&sc->sc_abort_mtx);
2506 	start_abort = (SIMPLEQ_FIRST(&sc->sc_abort_list) == 0);
2507 	SIMPLEQ_INSERT_TAIL(&sc->sc_abort_list, ccb, ccb_link);
2508 	if (start_abort)
2509 		workqueue_enqueue(sc->sc_abort_wq, &sc->sc_abort_work, NULL);
2510 	mutex_exit(&sc->sc_abort_mtx);
2511 }
2512 
2513 static void
2514 mfii_abort_task(struct work *wk, void *scp)
2515 {
2516 	struct mfii_softc *sc = scp;
2517 	struct mfii_ccb *list;
2518 
2519 	mutex_enter(&sc->sc_abort_mtx);
2520 	list = SIMPLEQ_FIRST(&sc->sc_abort_list);
2521 	SIMPLEQ_INIT(&sc->sc_abort_list);
2522 	mutex_exit(&sc->sc_abort_mtx);
2523 
2524 	while (list != NULL) {
2525 		struct mfii_ccb *ccb = list;
2526 		struct scsipi_xfer *xs = ccb->ccb_cookie;
2527 		struct scsipi_periph *periph = xs->xs_periph;
2528 		struct mfii_ccb *accb;
2529 
2530 		list = SIMPLEQ_NEXT(ccb, ccb_link);
2531 
2532 		if (!sc->sc_ld[periph->periph_target].ld_present) {
2533 			/* device is gone */
2534 			xs->error = XS_SELTIMEOUT;
2535 			scsipi_done(xs);
2536 			mfii_put_ccb(sc, ccb);
2537 			continue;
2538 		}
2539 
2540 		accb = mfii_get_ccb(sc);
2541 		mfii_scrub_ccb(accb);
2542 		mfii_abort(sc, accb, periph->periph_target, ccb->ccb_smid,
2543 		    MPII_SCSI_TASK_ABORT_TASK,
2544 		    htole32(MFII_TASK_MGMT_FLAGS_PD));
2545 
2546 		accb->ccb_cookie = ccb;
2547 		accb->ccb_done = mfii_scsi_cmd_abort_done;
2548 
2549 		mfii_start(sc, accb);
2550 	}
2551 }
2552 
2553 static void
2554 mfii_abort(struct mfii_softc *sc, struct mfii_ccb *accb, uint16_t dev_handle,
2555     uint16_t smid, uint8_t type, uint32_t flags)
2556 {
2557 	struct mfii_task_mgmt *msg;
2558 	struct mpii_msg_scsi_task_request *req;
2559 
2560 	msg = accb->ccb_request;
2561 	req = &msg->mpii_request;
2562 	req->dev_handle = dev_handle;
2563 	req->function = MPII_FUNCTION_SCSI_TASK_MGMT;
2564 	req->task_type = type;
2565 	req->task_mid = htole16( smid);
2566 	msg->flags = flags;
2567 
2568 	accb->ccb_req.flags = MFII_REQ_TYPE_HI_PRI;
2569 	accb->ccb_req.smid = le16toh(accb->ccb_smid);
2570 }
2571 
2572 static void
2573 mfii_scsi_cmd_abort_done(struct mfii_softc *sc, struct mfii_ccb *accb)
2574 {
2575 	struct mfii_ccb *ccb = accb->ccb_cookie;
2576 	struct scsipi_xfer *xs = ccb->ccb_cookie;
2577 
2578 	/* XXX check accb completion? */
2579 
2580 	mfii_put_ccb(sc, accb);
2581 	printf("%s: cmd aborted ccb %p\n", DEVNAME(sc), ccb);
2582 
2583 	xs->error = XS_TIMEOUT;
2584 	scsipi_done(xs);
2585 	mfii_put_ccb(sc, ccb);
2586 }
2587 
2588 static struct mfii_ccb *
2589 mfii_get_ccb(struct mfii_softc *sc)
2590 {
2591 	struct mfii_ccb *ccb;
2592 
2593 	mutex_enter(&sc->sc_ccb_mtx);
2594 	if (!sc->sc_running) {
2595 		ccb = NULL;
2596 	} else {
2597 		ccb = SIMPLEQ_FIRST(&sc->sc_ccb_freeq);
2598 		if (ccb != NULL)
2599 			SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_freeq, ccb_link);
2600 	}
2601 	mutex_exit(&sc->sc_ccb_mtx);
2602 	return (ccb);
2603 }
2604 
2605 static void
2606 mfii_scrub_ccb(struct mfii_ccb *ccb)
2607 {
2608 	ccb->ccb_cookie = NULL;
2609 	ccb->ccb_done = NULL;
2610 	ccb->ccb_flags = 0;
2611 	ccb->ccb_data = NULL;
2612 	ccb->ccb_direction = MFII_DATA_NONE;
2613 	ccb->ccb_dma64 = false;
2614 	ccb->ccb_len = 0;
2615 	ccb->ccb_sgl_len = 0;
2616 	memset(&ccb->ccb_req, 0, sizeof(ccb->ccb_req));
2617 	memset(ccb->ccb_request, 0, MFII_REQUEST_SIZE);
2618 	memset(ccb->ccb_mfi, 0, MFI_FRAME_SIZE);
2619 }
2620 
2621 static void
2622 mfii_put_ccb(struct mfii_softc *sc, struct mfii_ccb *ccb)
2623 {
2624 	mutex_enter(&sc->sc_ccb_mtx);
2625 	SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_freeq, ccb, ccb_link);
2626 	mutex_exit(&sc->sc_ccb_mtx);
2627 }
2628 
2629 static int
2630 mfii_init_ccb(struct mfii_softc *sc)
2631 {
2632 	struct mfii_ccb *ccb;
2633 	u_int8_t *request = MFII_DMA_KVA(sc->sc_requests);
2634 	u_int8_t *mfi = MFII_DMA_KVA(sc->sc_mfi);
2635 	u_int8_t *sense = MFII_DMA_KVA(sc->sc_sense);
2636 	u_int8_t *sgl = MFII_DMA_KVA(sc->sc_sgl);
2637 	u_int i;
2638 	int error;
2639 
2640 	sc->sc_ccb = malloc(sc->sc_max_cmds * sizeof(struct mfii_ccb),
2641 	    M_DEVBUF, M_WAITOK|M_ZERO);
2642 
2643 	for (i = 0; i < sc->sc_max_cmds; i++) {
2644 		ccb = &sc->sc_ccb[i];
2645 		ccb->ccb_sc = sc;
2646 
2647 		/* create a dma map for transfer */
2648 		error = bus_dmamap_create(sc->sc_dmat,
2649 		    MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
2650 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap32);
2651 		if (error) {
2652 			printf("%s: cannot create ccb dmamap32 (%d)\n",
2653 			    DEVNAME(sc), error);
2654 			goto destroy;
2655 		}
2656 		error = bus_dmamap_create(sc->sc_dmat64,
2657 		    MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
2658 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap64);
2659 		if (error) {
2660 			printf("%s: cannot create ccb dmamap64 (%d)\n",
2661 			    DEVNAME(sc), error);
2662 			goto destroy32;
2663 		}
2664 
2665 		/* select i + 1'th request. 0 is reserved for events */
2666 		ccb->ccb_smid = i + 1;
2667 		ccb->ccb_request_offset = MFII_REQUEST_SIZE * (i + 1);
2668 		ccb->ccb_request = request + ccb->ccb_request_offset;
2669 		ccb->ccb_request_dva = MFII_DMA_DVA(sc->sc_requests) +
2670 		    ccb->ccb_request_offset;
2671 
2672 		/* select i'th MFI command frame */
2673 		ccb->ccb_mfi_offset = MFI_FRAME_SIZE * i;
2674 		ccb->ccb_mfi = mfi + ccb->ccb_mfi_offset;
2675 		ccb->ccb_mfi_dva = MFII_DMA_DVA(sc->sc_mfi) +
2676 		    ccb->ccb_mfi_offset;
2677 
2678 		/* select i'th sense */
2679 		ccb->ccb_sense_offset = MFI_SENSE_SIZE * i;
2680 		ccb->ccb_sense = (struct mfi_sense *)(sense +
2681 		    ccb->ccb_sense_offset);
2682 		ccb->ccb_sense_dva = MFII_DMA_DVA(sc->sc_sense) +
2683 		    ccb->ccb_sense_offset;
2684 
2685 		/* select i'th sgl */
2686 		ccb->ccb_sgl_offset = sizeof(struct mfii_sge) *
2687 		    sc->sc_max_sgl * i;
2688 		ccb->ccb_sgl = (struct mfii_sge *)(sgl + ccb->ccb_sgl_offset);
2689 		ccb->ccb_sgl_dva = MFII_DMA_DVA(sc->sc_sgl) +
2690 		    ccb->ccb_sgl_offset;
2691 
2692 		mutex_init(&ccb->ccb_mtx, MUTEX_DEFAULT, IPL_BIO);
2693 		cv_init(&ccb->ccb_cv, "mfiiexec");
2694 
2695 		/* add ccb to queue */
2696 		mfii_put_ccb(sc, ccb);
2697 	}
2698 
2699 	return (0);
2700 
2701 destroy32:
2702 	bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap32);
2703 destroy:
2704 	/* free dma maps and ccb memory */
2705 	while ((ccb = mfii_get_ccb(sc)) != NULL) {
2706 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap32);
2707 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap64);
2708 	}
2709 
2710 	free(sc->sc_ccb, M_DEVBUF);
2711 
2712 	return (1);
2713 }
2714 
2715 #if NBIO > 0
2716 static int
2717 mfii_ioctl(device_t dev, u_long cmd, void *addr)
2718 {
2719 	struct mfii_softc	*sc = device_private(dev);
2720 	int error = 0;
2721 
2722 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl ", DEVNAME(sc));
2723 
2724 	mutex_enter(&sc->sc_lock);
2725 
2726 	switch (cmd) {
2727 	case BIOCINQ:
2728 		DNPRINTF(MFII_D_IOCTL, "inq\n");
2729 		error = mfii_ioctl_inq(sc, (struct bioc_inq *)addr);
2730 		break;
2731 
2732 	case BIOCVOL:
2733 		DNPRINTF(MFII_D_IOCTL, "vol\n");
2734 		error = mfii_ioctl_vol(sc, (struct bioc_vol *)addr);
2735 		break;
2736 
2737 	case BIOCDISK:
2738 		DNPRINTF(MFII_D_IOCTL, "disk\n");
2739 		error = mfii_ioctl_disk(sc, (struct bioc_disk *)addr);
2740 		break;
2741 
2742 	case BIOCALARM:
2743 		DNPRINTF(MFII_D_IOCTL, "alarm\n");
2744 		error = mfii_ioctl_alarm(sc, (struct bioc_alarm *)addr);
2745 		break;
2746 
2747 	case BIOCBLINK:
2748 		DNPRINTF(MFII_D_IOCTL, "blink\n");
2749 		error = mfii_ioctl_blink(sc, (struct bioc_blink *)addr);
2750 		break;
2751 
2752 	case BIOCSETSTATE:
2753 		DNPRINTF(MFII_D_IOCTL, "setstate\n");
2754 		error = mfii_ioctl_setstate(sc, (struct bioc_setstate *)addr);
2755 		break;
2756 
2757 #if 0
2758 	case BIOCPATROL:
2759 		DNPRINTF(MFII_D_IOCTL, "patrol\n");
2760 		error = mfii_ioctl_patrol(sc, (struct bioc_patrol *)addr);
2761 		break;
2762 #endif
2763 
2764 	default:
2765 		DNPRINTF(MFII_D_IOCTL, " invalid ioctl\n");
2766 		error = ENOTTY;
2767 	}
2768 
2769 	mutex_exit(&sc->sc_lock);
2770 
2771 	return (error);
2772 }
2773 
2774 static int
2775 mfii_bio_getitall(struct mfii_softc *sc)
2776 {
2777 	int			i, d, rv = EINVAL;
2778 	size_t			size;
2779 	union mfi_mbox		mbox;
2780 	struct mfi_conf		*cfg = NULL;
2781 	struct mfi_ld_details	*ld_det = NULL;
2782 
2783 	/* get info */
2784 	if (mfii_get_info(sc)) {
2785 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_get_info failed\n",
2786 		    DEVNAME(sc));
2787 		goto done;
2788 	}
2789 
2790 	/* send single element command to retrieve size for full structure */
2791 	cfg = malloc(sizeof *cfg, M_DEVBUF, M_NOWAIT | M_ZERO);
2792 	if (cfg == NULL)
2793 		goto done;
2794 	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, sizeof(*cfg),
2795 	    MFII_DATA_IN, false)) {
2796 		free(cfg, M_DEVBUF);
2797 		goto done;
2798 	}
2799 
2800 	size = cfg->mfc_size;
2801 	free(cfg, M_DEVBUF);
2802 
2803 	/* memory for read config */
2804 	cfg = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
2805 	if (cfg == NULL)
2806 		goto done;
2807 	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, size,
2808 	    MFII_DATA_IN, false)) {
2809 		free(cfg, M_DEVBUF);
2810 		goto done;
2811 	}
2812 
2813 	/* replace current pointer with new one */
2814 	if (sc->sc_cfg)
2815 		free(sc->sc_cfg, M_DEVBUF);
2816 	sc->sc_cfg = cfg;
2817 
2818 	/* get all ld info */
2819 	if (mfii_mgmt(sc, MR_DCMD_LD_GET_LIST, NULL, &sc->sc_ld_list,
2820 	    sizeof(sc->sc_ld_list), MFII_DATA_IN, false))
2821 		goto done;
2822 
2823 	/* get memory for all ld structures */
2824 	size = cfg->mfc_no_ld * sizeof(struct mfi_ld_details);
2825 	if (sc->sc_ld_sz != size) {
2826 		if (sc->sc_ld_details)
2827 			free(sc->sc_ld_details, M_DEVBUF);
2828 
2829 		ld_det = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
2830 		if (ld_det == NULL)
2831 			goto done;
2832 		sc->sc_ld_sz = size;
2833 		sc->sc_ld_details = ld_det;
2834 	}
2835 
2836 	/* find used physical disks */
2837 	size = sizeof(struct mfi_ld_details);
2838 	for (i = 0, d = 0; i < cfg->mfc_no_ld; i++) {
2839 		memset(&mbox, 0, sizeof(mbox));
2840 		mbox.b[0] = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
2841 		if (mfii_mgmt(sc, MR_DCMD_LD_GET_INFO, &mbox,
2842 		    &sc->sc_ld_details[i], size, MFII_DATA_IN, false))
2843 			goto done;
2844 
2845 		d += sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
2846 		    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
2847 	}
2848 	sc->sc_no_pd = d;
2849 
2850 	rv = 0;
2851 done:
2852 	return (rv);
2853 }
2854 
2855 static int
2856 mfii_ioctl_inq(struct mfii_softc *sc, struct bioc_inq *bi)
2857 {
2858 	int			rv = EINVAL;
2859 	struct mfi_conf		*cfg = NULL;
2860 
2861 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_inq\n", DEVNAME(sc));
2862 
2863 	if (mfii_bio_getitall(sc)) {
2864 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
2865 		    DEVNAME(sc));
2866 		goto done;
2867 	}
2868 
2869 	/* count unused disks as volumes */
2870 	if (sc->sc_cfg == NULL)
2871 		goto done;
2872 	cfg = sc->sc_cfg;
2873 
2874 	bi->bi_nodisk = sc->sc_info.mci_pd_disks_present;
2875 	bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs;
2876 #if notyet
2877 	bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs +
2878 	    (bi->bi_nodisk - sc->sc_no_pd);
2879 #endif
2880 	/* tell bio who we are */
2881 	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
2882 
2883 	rv = 0;
2884 done:
2885 	return (rv);
2886 }
2887 
2888 static int
2889 mfii_ioctl_vol(struct mfii_softc *sc, struct bioc_vol *bv)
2890 {
2891 	int			i, per, rv = EINVAL;
2892 
2893 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_vol %#x\n",
2894 	    DEVNAME(sc), bv->bv_volid);
2895 
2896 	/* we really could skip and expect that inq took care of it */
2897 	if (mfii_bio_getitall(sc)) {
2898 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
2899 		    DEVNAME(sc));
2900 		goto done;
2901 	}
2902 
2903 	if (bv->bv_volid >= sc->sc_ld_list.mll_no_ld) {
2904 		/* go do hotspares & unused disks */
2905 		rv = mfii_bio_hs(sc, bv->bv_volid, MFI_MGMT_VD, bv);
2906 		goto done;
2907 	}
2908 
2909 	i = bv->bv_volid;
2910 	strlcpy(bv->bv_dev, sc->sc_ld_details[i].mld_cfg.mlc_prop.mlp_name,
2911 	    sizeof(bv->bv_dev));
2912 
2913 	switch(sc->sc_ld_list.mll_list[i].mll_state) {
2914 	case MFI_LD_OFFLINE:
2915 		bv->bv_status = BIOC_SVOFFLINE;
2916 		break;
2917 
2918 	case MFI_LD_PART_DEGRADED:
2919 	case MFI_LD_DEGRADED:
2920 		bv->bv_status = BIOC_SVDEGRADED;
2921 		break;
2922 
2923 	case MFI_LD_ONLINE:
2924 		bv->bv_status = BIOC_SVONLINE;
2925 		break;
2926 
2927 	default:
2928 		bv->bv_status = BIOC_SVINVALID;
2929 		DNPRINTF(MFII_D_IOCTL, "%s: invalid logical disk state %#x\n",
2930 		    DEVNAME(sc),
2931 		    sc->sc_ld_list.mll_list[i].mll_state);
2932 	}
2933 
2934 	/* additional status can modify MFI status */
2935 	switch (sc->sc_ld_details[i].mld_progress.mlp_in_prog) {
2936 	case MFI_LD_PROG_CC:
2937 	case MFI_LD_PROG_BGI:
2938 		bv->bv_status = BIOC_SVSCRUB;
2939 		per = (int)sc->sc_ld_details[i].mld_progress.mlp_cc.mp_progress;
2940 		bv->bv_percent = (per * 100) / 0xffff;
2941 		bv->bv_seconds =
2942 		    sc->sc_ld_details[i].mld_progress.mlp_cc.mp_elapsed_seconds;
2943 		break;
2944 
2945 	case MFI_LD_PROG_FGI:
2946 	case MFI_LD_PROG_RECONSTRUCT:
2947 		/* nothing yet */
2948 		break;
2949 	}
2950 
2951 #if 0
2952 	if (sc->sc_ld_details[i].mld_cfg.mlc_prop.mlp_cur_cache_policy & 0x01)
2953 		bv->bv_cache = BIOC_CVWRITEBACK;
2954 	else
2955 		bv->bv_cache = BIOC_CVWRITETHROUGH;
2956 #endif
2957 
2958 	/*
2959 	 * The RAID levels are determined per the SNIA DDF spec, this is only
2960 	 * a subset that is valid for the MFI controller.
2961 	 */
2962 	bv->bv_level = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_pri_raid;
2963 	if (sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth > 1)
2964 		bv->bv_level *= 10;
2965 
2966 	bv->bv_nodisk = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
2967 	    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
2968 
2969 	bv->bv_size = sc->sc_ld_details[i].mld_size * 512; /* bytes per block */
2970 
2971 	rv = 0;
2972 done:
2973 	return (rv);
2974 }
2975 
2976 static int
2977 mfii_ioctl_disk(struct mfii_softc *sc, struct bioc_disk *bd)
2978 {
2979 	struct mfi_conf		*cfg;
2980 	struct mfi_array	*ar;
2981 	struct mfi_ld_cfg	*ld;
2982 	struct mfi_pd_details	*pd;
2983 	struct mfi_pd_list	*pl;
2984 	struct scsipi_inquiry_data *inqbuf;
2985 	char			vend[8+16+4+1], *vendp;
2986 	int			i, rv = EINVAL;
2987 	int			arr, vol, disk, span;
2988 	union mfi_mbox		mbox;
2989 
2990 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_disk %#x\n",
2991 	    DEVNAME(sc), bd->bd_diskid);
2992 
2993 	/* we really could skip and expect that inq took care of it */
2994 	if (mfii_bio_getitall(sc)) {
2995 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
2996 		    DEVNAME(sc));
2997 		return (rv);
2998 	}
2999 	cfg = sc->sc_cfg;
3000 
3001 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3002 	pl = malloc(sizeof *pl, M_DEVBUF, M_WAITOK);
3003 
3004 	ar = cfg->mfc_array;
3005 	vol = bd->bd_volid;
3006 	if (vol >= cfg->mfc_no_ld) {
3007 		/* do hotspares */
3008 		rv = mfii_bio_hs(sc, bd->bd_volid, MFI_MGMT_SD, bd);
3009 		goto freeme;
3010 	}
3011 
3012 	/* calculate offset to ld structure */
3013 	ld = (struct mfi_ld_cfg *)(
3014 	    ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
3015 	    cfg->mfc_array_size * cfg->mfc_no_array);
3016 
3017 	/* use span 0 only when raid group is not spanned */
3018 	if (ld[vol].mlc_parm.mpa_span_depth > 1)
3019 		span = bd->bd_diskid / ld[vol].mlc_parm.mpa_no_drv_per_span;
3020 	else
3021 		span = 0;
3022 	arr = ld[vol].mlc_span[span].mls_index;
3023 
3024 	/* offset disk into pd list */
3025 	disk = bd->bd_diskid % ld[vol].mlc_parm.mpa_no_drv_per_span;
3026 
3027 	if (ar[arr].pd[disk].mar_pd.mfp_id == 0xffffU) {
3028 		/* disk is missing but succeed command */
3029 		bd->bd_status = BIOC_SDFAILED;
3030 		rv = 0;
3031 
3032 		/* try to find an unused disk for the target to rebuild */
3033 		if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pl, sizeof(*pl),
3034 		    MFII_DATA_IN, false))
3035 			goto freeme;
3036 
3037 		for (i = 0; i < pl->mpl_no_pd; i++) {
3038 			if (pl->mpl_address[i].mpa_scsi_type != 0)
3039 				continue;
3040 
3041 			memset(&mbox, 0, sizeof(mbox));
3042 			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3043 			if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox,
3044 			    pd, sizeof(*pd), MFII_DATA_IN, false))
3045 				continue;
3046 
3047 			if (pd->mpd_fw_state == MFI_PD_UNCONFIG_GOOD ||
3048 			    pd->mpd_fw_state == MFI_PD_UNCONFIG_BAD)
3049 				break;
3050 		}
3051 
3052 		if (i == pl->mpl_no_pd)
3053 			goto freeme;
3054 	} else {
3055 		memset(&mbox, 0, sizeof(mbox));
3056 		mbox.s[0] = ar[arr].pd[disk].mar_pd.mfp_id;
3057 		if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3058 		    MFII_DATA_IN, false)) {
3059 			bd->bd_status = BIOC_SDINVALID;
3060 			goto freeme;
3061 		}
3062 	}
3063 
3064 	/* get the remaining fields */
3065 	bd->bd_channel = pd->mpd_enc_idx;
3066 	bd->bd_target = pd->mpd_enc_slot;
3067 
3068 	/* get status */
3069 	switch (pd->mpd_fw_state){
3070 	case MFI_PD_UNCONFIG_GOOD:
3071 	case MFI_PD_UNCONFIG_BAD:
3072 		bd->bd_status = BIOC_SDUNUSED;
3073 		break;
3074 
3075 	case MFI_PD_HOTSPARE: /* XXX dedicated hotspare part of array? */
3076 		bd->bd_status = BIOC_SDHOTSPARE;
3077 		break;
3078 
3079 	case MFI_PD_OFFLINE:
3080 		bd->bd_status = BIOC_SDOFFLINE;
3081 		break;
3082 
3083 	case MFI_PD_FAILED:
3084 		bd->bd_status = BIOC_SDFAILED;
3085 		break;
3086 
3087 	case MFI_PD_REBUILD:
3088 		bd->bd_status = BIOC_SDREBUILD;
3089 		break;
3090 
3091 	case MFI_PD_ONLINE:
3092 		bd->bd_status = BIOC_SDONLINE;
3093 		break;
3094 
3095 	case MFI_PD_COPYBACK:
3096 	case MFI_PD_SYSTEM:
3097 	default:
3098 		bd->bd_status = BIOC_SDINVALID;
3099 		break;
3100 	}
3101 
3102 	bd->bd_size = pd->mpd_size * 512; /* bytes per block */
3103 
3104 	inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data;
3105 	vendp = inqbuf->vendor;
3106 	memcpy(vend, vendp, sizeof vend - 1);
3107 	vend[sizeof vend - 1] = '\0';
3108 	strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
3109 
3110 	/* XXX find a way to retrieve serial nr from drive */
3111 	/* XXX find a way to get bd_procdev */
3112 
3113 #if 0
3114 	mfp = &pd->mpd_progress;
3115 	if (mfp->mfp_in_prog & MFI_PD_PROG_PR) {
3116 		mp = &mfp->mfp_patrol_read;
3117 		bd->bd_patrol.bdp_percent = (mp->mp_progress * 100) / 0xffff;
3118 		bd->bd_patrol.bdp_seconds = mp->mp_elapsed_seconds;
3119 	}
3120 #endif
3121 
3122 	rv = 0;
3123 freeme:
3124 	free(pd, M_DEVBUF);
3125 	free(pl, M_DEVBUF);
3126 
3127 	return (rv);
3128 }
3129 
3130 static int
3131 mfii_ioctl_alarm(struct mfii_softc *sc, struct bioc_alarm *ba)
3132 {
3133 	uint32_t		opc;
3134 	int			rv = 0;
3135 	int8_t			ret;
3136 	mfii_direction_t dir = MFII_DATA_NONE;
3137 
3138 	switch(ba->ba_opcode) {
3139 	case BIOC_SADISABLE:
3140 		opc = MR_DCMD_SPEAKER_DISABLE;
3141 		break;
3142 
3143 	case BIOC_SAENABLE:
3144 		opc = MR_DCMD_SPEAKER_ENABLE;
3145 		break;
3146 
3147 	case BIOC_SASILENCE:
3148 		opc = MR_DCMD_SPEAKER_SILENCE;
3149 		break;
3150 
3151 	case BIOC_GASTATUS:
3152 		opc = MR_DCMD_SPEAKER_GET;
3153 		dir = MFII_DATA_IN;
3154 		break;
3155 
3156 	case BIOC_SATEST:
3157 		opc = MR_DCMD_SPEAKER_TEST;
3158 		break;
3159 
3160 	default:
3161 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_alarm biocalarm invalid "
3162 		    "opcode %x\n", DEVNAME(sc), ba->ba_opcode);
3163 		return (EINVAL);
3164 	}
3165 
3166 	if (mfii_mgmt(sc, opc, NULL, &ret, sizeof(ret), dir, false))
3167 		rv = EINVAL;
3168 	else
3169 		if (ba->ba_opcode == BIOC_GASTATUS)
3170 			ba->ba_status = ret;
3171 		else
3172 			ba->ba_status = 0;
3173 
3174 	return (rv);
3175 }
3176 
3177 static int
3178 mfii_ioctl_blink(struct mfii_softc *sc, struct bioc_blink *bb)
3179 {
3180 	int			i, found, rv = EINVAL;
3181 	union mfi_mbox		mbox;
3182 	uint32_t		cmd;
3183 	struct mfi_pd_list	*pd;
3184 
3185 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_blink %x\n", DEVNAME(sc),
3186 	    bb->bb_status);
3187 
3188 	/* channel 0 means not in an enclosure so can't be blinked */
3189 	if (bb->bb_channel == 0)
3190 		return (EINVAL);
3191 
3192 	pd = malloc(sizeof(*pd), M_DEVBUF, M_WAITOK);
3193 
3194 	if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pd, sizeof(*pd),
3195 	    MFII_DATA_IN, false))
3196 		goto done;
3197 
3198 	for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
3199 		if (bb->bb_channel == pd->mpl_address[i].mpa_enc_index &&
3200 		    bb->bb_target == pd->mpl_address[i].mpa_enc_slot) {
3201 			found = 1;
3202 			break;
3203 		}
3204 
3205 	if (!found)
3206 		goto done;
3207 
3208 	memset(&mbox, 0, sizeof(mbox));
3209 	mbox.s[0] = pd->mpl_address[i].mpa_pd_id;
3210 
3211 	switch (bb->bb_status) {
3212 	case BIOC_SBUNBLINK:
3213 		cmd = MR_DCMD_PD_UNBLINK;
3214 		break;
3215 
3216 	case BIOC_SBBLINK:
3217 		cmd = MR_DCMD_PD_BLINK;
3218 		break;
3219 
3220 	case BIOC_SBALARM:
3221 	default:
3222 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_blink biocblink invalid "
3223 		    "opcode %x\n", DEVNAME(sc), bb->bb_status);
3224 		goto done;
3225 	}
3226 
3227 
3228 	if (mfii_mgmt(sc, cmd, &mbox, NULL, 0, MFII_DATA_NONE, false))
3229 		goto done;
3230 
3231 	rv = 0;
3232 done:
3233 	free(pd, M_DEVBUF);
3234 	return (rv);
3235 }
3236 
3237 static int
3238 mfii_makegood(struct mfii_softc *sc, uint16_t pd_id)
3239 {
3240 	struct mfii_foreign_scan_info *fsi;
3241 	struct mfi_pd_details	*pd;
3242 	union mfi_mbox		mbox;
3243 	int			rv;
3244 
3245 	fsi = malloc(sizeof *fsi, M_DEVBUF, M_WAITOK);
3246 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3247 
3248 	memset(&mbox, 0, sizeof mbox);
3249 	mbox.s[0] = pd_id;
3250 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3251 	    MFII_DATA_IN, false);
3252 	if (rv != 0)
3253 		goto done;
3254 
3255 	if (pd->mpd_fw_state == MFI_PD_UNCONFIG_BAD) {
3256 		mbox.s[0] = pd_id;
3257 		mbox.s[1] = pd->mpd_pd.mfp_seq;
3258 		mbox.b[4] = MFI_PD_UNCONFIG_GOOD;
3259 		rv = mfii_mgmt(sc, MR_DCMD_PD_SET_STATE, &mbox, NULL, 0,
3260 		    MFII_DATA_NONE, false);
3261 		if (rv != 0)
3262 			goto done;
3263 	}
3264 
3265 	memset(&mbox, 0, sizeof mbox);
3266 	mbox.s[0] = pd_id;
3267 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3268 	    MFII_DATA_IN, false);
3269 	if (rv != 0)
3270 		goto done;
3271 
3272 	if (pd->mpd_ddf_state & MFI_DDF_FOREIGN) {
3273 		rv = mfii_mgmt(sc, MR_DCMD_CFG_FOREIGN_SCAN, NULL,
3274 		    fsi, sizeof(*fsi), MFII_DATA_IN, false);
3275 		if (rv != 0)
3276 			goto done;
3277 
3278 		if (fsi->count > 0) {
3279 			rv = mfii_mgmt(sc, MR_DCMD_CFG_FOREIGN_CLEAR, NULL,
3280 			    NULL, 0, MFII_DATA_NONE, false);
3281 			if (rv != 0)
3282 				goto done;
3283 		}
3284 	}
3285 
3286 	memset(&mbox, 0, sizeof mbox);
3287 	mbox.s[0] = pd_id;
3288 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3289 	    MFII_DATA_IN, false);
3290 	if (rv != 0)
3291 		goto done;
3292 
3293 	if (pd->mpd_fw_state != MFI_PD_UNCONFIG_GOOD ||
3294 	    pd->mpd_ddf_state & MFI_DDF_FOREIGN)
3295 		rv = ENXIO;
3296 
3297 done:
3298 	free(fsi, M_DEVBUF);
3299 	free(pd, M_DEVBUF);
3300 
3301 	return (rv);
3302 }
3303 
3304 static int
3305 mfii_makespare(struct mfii_softc *sc, uint16_t pd_id)
3306 {
3307 	struct mfi_hotspare	*hs;
3308 	struct mfi_pd_details	*pd;
3309 	union mfi_mbox		mbox;
3310 	size_t			size;
3311 	int			rv = EINVAL;
3312 
3313 	/* we really could skip and expect that inq took care of it */
3314 	if (mfii_bio_getitall(sc)) {
3315 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_bio_getitall failed\n",
3316 		    DEVNAME(sc));
3317 		return (rv);
3318 	}
3319 	size = sizeof *hs + sizeof(uint16_t) * sc->sc_cfg->mfc_no_array;
3320 
3321 	hs = malloc(size, M_DEVBUF, M_WAITOK);
3322 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3323 
3324 	memset(&mbox, 0, sizeof mbox);
3325 	mbox.s[0] = pd_id;
3326 	rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3327 	    MFII_DATA_IN, false);
3328 	if (rv != 0)
3329 		goto done;
3330 
3331 	memset(hs, 0, size);
3332 	hs->mhs_pd.mfp_id = pd->mpd_pd.mfp_id;
3333 	hs->mhs_pd.mfp_seq = pd->mpd_pd.mfp_seq;
3334 	rv = mfii_mgmt(sc, MR_DCMD_CFG_MAKE_SPARE, NULL, hs, size,
3335 	    MFII_DATA_OUT, false);
3336 
3337 done:
3338 	free(hs, M_DEVBUF);
3339 	free(pd, M_DEVBUF);
3340 
3341 	return (rv);
3342 }
3343 
3344 static int
3345 mfii_ioctl_setstate(struct mfii_softc *sc, struct bioc_setstate *bs)
3346 {
3347 	struct mfi_pd_details	*pd;
3348 	struct mfi_pd_list	*pl;
3349 	int			i, found, rv = EINVAL;
3350 	union mfi_mbox		mbox;
3351 
3352 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_setstate %x\n", DEVNAME(sc),
3353 	    bs->bs_status);
3354 
3355 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3356 	pl = malloc(sizeof *pl, M_DEVBUF, M_WAITOK);
3357 
3358 	if (mfii_mgmt(sc, MR_DCMD_PD_GET_LIST, NULL, pl, sizeof(*pl),
3359 	    MFII_DATA_IN, false))
3360 		goto done;
3361 
3362 	for (i = 0, found = 0; i < pl->mpl_no_pd; i++)
3363 		if (bs->bs_channel == pl->mpl_address[i].mpa_enc_index &&
3364 		    bs->bs_target == pl->mpl_address[i].mpa_enc_slot) {
3365 			found = 1;
3366 			break;
3367 		}
3368 
3369 	if (!found)
3370 		goto done;
3371 
3372 	memset(&mbox, 0, sizeof(mbox));
3373 	mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3374 
3375 	if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3376 	    MFII_DATA_IN, false))
3377 		goto done;
3378 
3379 	mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3380 	mbox.s[1] = pd->mpd_pd.mfp_seq;
3381 
3382 	switch (bs->bs_status) {
3383 	case BIOC_SSONLINE:
3384 		mbox.b[4] = MFI_PD_ONLINE;
3385 		break;
3386 
3387 	case BIOC_SSOFFLINE:
3388 		mbox.b[4] = MFI_PD_OFFLINE;
3389 		break;
3390 
3391 	case BIOC_SSHOTSPARE:
3392 		mbox.b[4] = MFI_PD_HOTSPARE;
3393 		break;
3394 
3395 	case BIOC_SSREBUILD:
3396 		if (pd->mpd_fw_state != MFI_PD_OFFLINE) {
3397 			if ((rv = mfii_makegood(sc,
3398 			    pl->mpl_address[i].mpa_pd_id)))
3399 				goto done;
3400 
3401 			if ((rv = mfii_makespare(sc,
3402 			    pl->mpl_address[i].mpa_pd_id)))
3403 				goto done;
3404 
3405 			memset(&mbox, 0, sizeof(mbox));
3406 			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3407 			rv = mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox,
3408 			    pd, sizeof(*pd), MFII_DATA_IN, false);
3409 			if (rv != 0)
3410 				goto done;
3411 
3412 			/* rebuilding might be started by mfii_makespare() */
3413 			if (pd->mpd_fw_state == MFI_PD_REBUILD) {
3414 				rv = 0;
3415 				goto done;
3416 			}
3417 
3418 			mbox.s[0] = pl->mpl_address[i].mpa_pd_id;
3419 			mbox.s[1] = pd->mpd_pd.mfp_seq;
3420 		}
3421 		mbox.b[4] = MFI_PD_REBUILD;
3422 		break;
3423 
3424 	default:
3425 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_setstate invalid "
3426 		    "opcode %x\n", DEVNAME(sc), bs->bs_status);
3427 		goto done;
3428 	}
3429 
3430 
3431 	rv = mfii_mgmt(sc, MR_DCMD_PD_SET_STATE, &mbox, NULL, 0,
3432 	    MFII_DATA_NONE, false);
3433 done:
3434 	free(pd, M_DEVBUF);
3435 	free(pl, M_DEVBUF);
3436 	return (rv);
3437 }
3438 
3439 #if 0
3440 int
3441 mfii_ioctl_patrol(struct mfii_softc *sc, struct bioc_patrol *bp)
3442 {
3443 	uint32_t		opc;
3444 	int			rv = 0;
3445 	struct mfi_pr_properties prop;
3446 	struct mfi_pr_status	status;
3447 	uint32_t		time, exec_freq;
3448 
3449 	switch (bp->bp_opcode) {
3450 	case BIOC_SPSTOP:
3451 	case BIOC_SPSTART:
3452 		if (bp->bp_opcode == BIOC_SPSTART)
3453 			opc = MR_DCMD_PR_START;
3454 		else
3455 			opc = MR_DCMD_PR_STOP;
3456 		if (mfii_mgmt(sc, opc, NULL, NULL, 0, MFII_DATA_IN, false))
3457 			return (EINVAL);
3458 		break;
3459 
3460 	case BIOC_SPMANUAL:
3461 	case BIOC_SPDISABLE:
3462 	case BIOC_SPAUTO:
3463 		/* Get device's time. */
3464 		opc = MR_DCMD_TIME_SECS_GET;
3465 		if (mfii_mgmt(sc, opc, NULL, &time, sizeof(time),
3466 		    MFII_DATA_IN, false))
3467 			return (EINVAL);
3468 
3469 		opc = MR_DCMD_PR_GET_PROPERTIES;
3470 		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop),
3471 		    MFII_DATA_IN, false))
3472 			return (EINVAL);
3473 
3474 		switch (bp->bp_opcode) {
3475 		case BIOC_SPMANUAL:
3476 			prop.op_mode = MFI_PR_OPMODE_MANUAL;
3477 			break;
3478 		case BIOC_SPDISABLE:
3479 			prop.op_mode = MFI_PR_OPMODE_DISABLED;
3480 			break;
3481 		case BIOC_SPAUTO:
3482 			if (bp->bp_autoival != 0) {
3483 				if (bp->bp_autoival == -1)
3484 					/* continuously */
3485 					exec_freq = 0xffffffffU;
3486 				else if (bp->bp_autoival > 0)
3487 					exec_freq = bp->bp_autoival;
3488 				else
3489 					return (EINVAL);
3490 				prop.exec_freq = exec_freq;
3491 			}
3492 			if (bp->bp_autonext != 0) {
3493 				if (bp->bp_autonext < 0)
3494 					return (EINVAL);
3495 				else
3496 					prop.next_exec = time + bp->bp_autonext;
3497 			}
3498 			prop.op_mode = MFI_PR_OPMODE_AUTO;
3499 			break;
3500 		}
3501 
3502 		opc = MR_DCMD_PR_SET_PROPERTIES;
3503 		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop),
3504 		    MFII_DATA_OUT, false))
3505 			return (EINVAL);
3506 
3507 		break;
3508 
3509 	case BIOC_GPSTATUS:
3510 		opc = MR_DCMD_PR_GET_PROPERTIES;
3511 		if (mfii_mgmt(sc, opc, NULL, &prop, sizeof(prop),
3512 		    MFII_DATA_IN, false))
3513 			return (EINVAL);
3514 
3515 		opc = MR_DCMD_PR_GET_STATUS;
3516 		if (mfii_mgmt(sc, opc, NULL, &status, sizeof(status),
3517 		    MFII_DATA_IN, false))
3518 			return (EINVAL);
3519 
3520 		/* Get device's time. */
3521 		opc = MR_DCMD_TIME_SECS_GET;
3522 		if (mfii_mgmt(sc, opc, NULL, &time, sizeof(time),
3523 		    MFII_DATA_IN, false))
3524 			return (EINVAL);
3525 
3526 		switch (prop.op_mode) {
3527 		case MFI_PR_OPMODE_AUTO:
3528 			bp->bp_mode = BIOC_SPMAUTO;
3529 			bp->bp_autoival = prop.exec_freq;
3530 			bp->bp_autonext = prop.next_exec;
3531 			bp->bp_autonow = time;
3532 			break;
3533 		case MFI_PR_OPMODE_MANUAL:
3534 			bp->bp_mode = BIOC_SPMMANUAL;
3535 			break;
3536 		case MFI_PR_OPMODE_DISABLED:
3537 			bp->bp_mode = BIOC_SPMDISABLED;
3538 			break;
3539 		default:
3540 			printf("%s: unknown patrol mode %d\n",
3541 			    DEVNAME(sc), prop.op_mode);
3542 			break;
3543 		}
3544 
3545 		switch (status.state) {
3546 		case MFI_PR_STATE_STOPPED:
3547 			bp->bp_status = BIOC_SPSSTOPPED;
3548 			break;
3549 		case MFI_PR_STATE_READY:
3550 			bp->bp_status = BIOC_SPSREADY;
3551 			break;
3552 		case MFI_PR_STATE_ACTIVE:
3553 			bp->bp_status = BIOC_SPSACTIVE;
3554 			break;
3555 		case MFI_PR_STATE_ABORTED:
3556 			bp->bp_status = BIOC_SPSABORTED;
3557 			break;
3558 		default:
3559 			printf("%s: unknown patrol state %d\n",
3560 			    DEVNAME(sc), status.state);
3561 			break;
3562 		}
3563 
3564 		break;
3565 
3566 	default:
3567 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_ioctl_patrol biocpatrol invalid "
3568 		    "opcode %x\n", DEVNAME(sc), bp->bp_opcode);
3569 		return (EINVAL);
3570 	}
3571 
3572 	return (rv);
3573 }
3574 #endif
3575 
3576 static int
3577 mfii_bio_hs(struct mfii_softc *sc, int volid, int type, void *bio_hs)
3578 {
3579 	struct mfi_conf		*cfg;
3580 	struct mfi_hotspare	*hs;
3581 	struct mfi_pd_details	*pd;
3582 	struct bioc_disk	*sdhs;
3583 	struct bioc_vol		*vdhs;
3584 	struct scsipi_inquiry_data *inqbuf;
3585 	char			vend[8+16+4+1], *vendp;
3586 	int			i, rv = EINVAL;
3587 	uint32_t		size;
3588 	union mfi_mbox		mbox;
3589 
3590 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs %d\n", DEVNAME(sc), volid);
3591 
3592 	if (!bio_hs)
3593 		return (EINVAL);
3594 
3595 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
3596 
3597 	/* send single element command to retrieve size for full structure */
3598 	cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
3599 	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, sizeof(*cfg),
3600 	    MFII_DATA_IN, false))
3601 		goto freeme;
3602 
3603 	size = cfg->mfc_size;
3604 	free(cfg, M_DEVBUF);
3605 
3606 	/* memory for read config */
3607 	cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO);
3608 	if (mfii_mgmt(sc, MR_DCMD_CONF_GET, NULL, cfg, size,
3609 	    MFII_DATA_IN, false))
3610 		goto freeme;
3611 
3612 	/* calculate offset to hs structure */
3613 	hs = (struct mfi_hotspare *)(
3614 	    ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
3615 	    cfg->mfc_array_size * cfg->mfc_no_array +
3616 	    cfg->mfc_ld_size * cfg->mfc_no_ld);
3617 
3618 	if (volid < cfg->mfc_no_ld)
3619 		goto freeme; /* not a hotspare */
3620 
3621 	if (volid > (cfg->mfc_no_ld + cfg->mfc_no_hs))
3622 		goto freeme; /* not a hotspare */
3623 
3624 	/* offset into hotspare structure */
3625 	i = volid - cfg->mfc_no_ld;
3626 
3627 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs i %d volid %d no_ld %d no_hs %d "
3628 	    "hs %p cfg %p id %02x\n", DEVNAME(sc), i, volid, cfg->mfc_no_ld,
3629 	    cfg->mfc_no_hs, hs, cfg, hs[i].mhs_pd.mfp_id);
3630 
3631 	/* get pd fields */
3632 	memset(&mbox, 0, sizeof(mbox));
3633 	mbox.s[0] = hs[i].mhs_pd.mfp_id;
3634 	if (mfii_mgmt(sc, MR_DCMD_PD_GET_INFO, &mbox, pd, sizeof(*pd),
3635 	    MFII_DATA_IN, false)) {
3636 		DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs illegal PD\n",
3637 		    DEVNAME(sc));
3638 		goto freeme;
3639 	}
3640 
3641 	switch (type) {
3642 	case MFI_MGMT_VD:
3643 		vdhs = bio_hs;
3644 		vdhs->bv_status = BIOC_SVONLINE;
3645 		vdhs->bv_size = pd->mpd_size / 2 * 1024; /* XXX why? */
3646 		vdhs->bv_level = -1; /* hotspare */
3647 		vdhs->bv_nodisk = 1;
3648 		break;
3649 
3650 	case MFI_MGMT_SD:
3651 		sdhs = bio_hs;
3652 		sdhs->bd_status = BIOC_SDHOTSPARE;
3653 		sdhs->bd_size = pd->mpd_size / 2 * 1024; /* XXX why? */
3654 		sdhs->bd_channel = pd->mpd_enc_idx;
3655 		sdhs->bd_target = pd->mpd_enc_slot;
3656 		inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data;
3657 		vendp = inqbuf->vendor;
3658 		memcpy(vend, vendp, sizeof vend - 1);
3659 		vend[sizeof vend - 1] = '\0';
3660 		strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor));
3661 		break;
3662 
3663 	default:
3664 		goto freeme;
3665 	}
3666 
3667 	DNPRINTF(MFII_D_IOCTL, "%s: mfii_vol_hs 6\n", DEVNAME(sc));
3668 	rv = 0;
3669 freeme:
3670 	free(pd, M_DEVBUF);
3671 	free(cfg, M_DEVBUF);
3672 
3673 	return (rv);
3674 }
3675 
3676 #endif /* NBIO > 0 */
3677 
3678 #define MFI_BBU_SENSORS 4
3679 
3680 static void
3681 mfii_bbu(struct mfii_softc *sc, envsys_data_t *edata)
3682 {
3683 	struct mfi_bbu_status bbu;
3684 	u_int32_t status;
3685 	u_int32_t mask;
3686 	u_int32_t soh_bad;
3687 	int rv;
3688 
3689 	mutex_enter(&sc->sc_lock);
3690 	rv = mfii_mgmt(sc, MR_DCMD_BBU_GET_STATUS, NULL, &bbu,
3691 	    sizeof(bbu), MFII_DATA_IN, false);
3692 	mutex_exit(&sc->sc_lock);
3693 	if (rv != 0) {
3694 		edata->state = ENVSYS_SINVALID;
3695 		edata->value_cur = 0;
3696 		return;
3697 	}
3698 
3699 	switch (bbu.battery_type) {
3700 	case MFI_BBU_TYPE_IBBU:
3701 		mask = MFI_BBU_STATE_BAD_IBBU;
3702 		soh_bad = 0;
3703 		break;
3704 	case MFI_BBU_TYPE_BBU:
3705 		mask = MFI_BBU_STATE_BAD_BBU;
3706 		soh_bad = (bbu.detail.bbu.is_SOH_good == 0);
3707 		break;
3708 
3709 	case MFI_BBU_TYPE_NONE:
3710 	default:
3711 		edata->state = ENVSYS_SCRITICAL;
3712 		edata->value_cur = 0;
3713 		return;
3714 	}
3715 
3716 	status = le32toh(bbu.fw_status) & mask;
3717 	switch(edata->sensor) {
3718 	case 0:
3719 		edata->value_cur = (status || soh_bad) ? 0 : 1;
3720 		edata->state =
3721 		    edata->value_cur ? ENVSYS_SVALID : ENVSYS_SCRITICAL;
3722 		return;
3723 	case 1:
3724 		edata->value_cur = le16toh(bbu.voltage) * 1000;
3725 		edata->state = ENVSYS_SVALID;
3726 		return;
3727 	case 2:
3728 		edata->value_cur = (int16_t)le16toh(bbu.current) * 1000;
3729 		edata->state = ENVSYS_SVALID;
3730 		return;
3731 	case 3:
3732 		edata->value_cur = le16toh(bbu.temperature) * 1000000 + 273150000;
3733 		edata->state = ENVSYS_SVALID;
3734 		return;
3735 	}
3736 }
3737 
3738 static void
3739 mfii_refresh_ld_sensor(struct mfii_softc *sc, envsys_data_t *edata)
3740 {
3741 	struct bioc_vol bv;
3742 	int error;
3743 
3744 	memset(&bv, 0, sizeof(bv));
3745 	bv.bv_volid = edata->sensor - MFI_BBU_SENSORS;
3746 	mutex_enter(&sc->sc_lock);
3747 	error = mfii_ioctl_vol(sc, &bv);
3748 	mutex_exit(&sc->sc_lock);
3749 	if (error)
3750 		bv.bv_status = BIOC_SVINVALID;
3751 	bio_vol_to_envsys(edata, &bv);
3752 }
3753 
3754 static void
3755 mfii_init_ld_sensor(struct mfii_softc *sc, envsys_data_t *sensor, int i)
3756 {
3757 	sensor->units = ENVSYS_DRIVE;
3758 	sensor->state = ENVSYS_SINVALID;
3759 	sensor->value_cur = ENVSYS_DRIVE_EMPTY;
3760 	/* Enable monitoring for drive state changes */
3761 	sensor->flags |= ENVSYS_FMONSTCHANGED;
3762 	snprintf(sensor->desc, sizeof(sensor->desc), "%s:%d", DEVNAME(sc), i);
3763 }
3764 
3765 static void
3766 mfii_attach_sensor(struct mfii_softc *sc, envsys_data_t *s)
3767 {
3768 	if (sysmon_envsys_sensor_attach(sc->sc_sme, s))
3769 		aprint_error_dev(sc->sc_dev,
3770 		    "failed to attach sensor %s\n", s->desc);
3771 }
3772 
3773 static int
3774 mfii_create_sensors(struct mfii_softc *sc)
3775 {
3776 	int i, rv;
3777 	const int nsensors = MFI_BBU_SENSORS + MFI_MAX_LD;
3778 
3779 	sc->sc_sme = sysmon_envsys_create();
3780 	sc->sc_sensors = malloc(sizeof(envsys_data_t) * nsensors,
3781 	    M_DEVBUF, M_WAITOK | M_ZERO);
3782 
3783 	/* BBU */
3784 	sc->sc_sensors[0].units = ENVSYS_INDICATOR;
3785 	sc->sc_sensors[0].state = ENVSYS_SINVALID;
3786 	sc->sc_sensors[0].value_cur = 0;
3787 	sc->sc_sensors[1].units = ENVSYS_SVOLTS_DC;
3788 	sc->sc_sensors[1].state = ENVSYS_SINVALID;
3789 	sc->sc_sensors[1].value_cur = 0;
3790 	sc->sc_sensors[2].units = ENVSYS_SAMPS;
3791 	sc->sc_sensors[2].state = ENVSYS_SINVALID;
3792 	sc->sc_sensors[2].value_cur = 0;
3793 	sc->sc_sensors[3].units = ENVSYS_STEMP;
3794 	sc->sc_sensors[3].state = ENVSYS_SINVALID;
3795 	sc->sc_sensors[3].value_cur = 0;
3796 
3797 	if (ISSET(le32toh(sc->sc_info.mci_hw_present), MFI_INFO_HW_BBU)) {
3798 		sc->sc_bbuok = true;
3799 		sc->sc_sensors[0].flags |= ENVSYS_FMONCRITICAL;
3800 		snprintf(sc->sc_sensors[0].desc, sizeof(sc->sc_sensors[0].desc),
3801 		    "%s BBU state", DEVNAME(sc));
3802 		snprintf(sc->sc_sensors[1].desc, sizeof(sc->sc_sensors[1].desc),
3803 		    "%s BBU voltage", DEVNAME(sc));
3804 		snprintf(sc->sc_sensors[2].desc, sizeof(sc->sc_sensors[2].desc),
3805 		    "%s BBU current", DEVNAME(sc));
3806 		snprintf(sc->sc_sensors[3].desc, sizeof(sc->sc_sensors[3].desc),
3807 		    "%s BBU temperature", DEVNAME(sc));
3808 		for (i = 0; i < MFI_BBU_SENSORS; i++) {
3809 			mfii_attach_sensor(sc, &sc->sc_sensors[i]);
3810 		}
3811 	}
3812 
3813 	for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) {
3814 		mfii_init_ld_sensor(sc, &sc->sc_sensors[i + MFI_BBU_SENSORS], i);
3815 		mfii_attach_sensor(sc, &sc->sc_sensors[i + MFI_BBU_SENSORS]);
3816 	}
3817 
3818 	sc->sc_sme->sme_name = DEVNAME(sc);
3819 	sc->sc_sme->sme_cookie = sc;
3820 	sc->sc_sme->sme_refresh = mfii_refresh_sensor;
3821 	rv = sysmon_envsys_register(sc->sc_sme);
3822 	if (rv) {
3823 		aprint_error_dev(sc->sc_dev,
3824 		    "unable to register with sysmon (rv = %d)\n", rv);
3825 	}
3826 	return rv;
3827 
3828 }
3829 
3830 static int
3831 mfii_destroy_sensors(struct mfii_softc *sc)
3832 {
3833 	if (sc->sc_sme == NULL)
3834 		return 0;
3835 	sysmon_envsys_unregister(sc->sc_sme);
3836 	sc->sc_sme = NULL;
3837 	free(sc->sc_sensors, M_DEVBUF);
3838 	return 0;
3839 }
3840 
3841 static void
3842 mfii_refresh_sensor(struct sysmon_envsys *sme, envsys_data_t *edata)
3843 {
3844 	struct mfii_softc	*sc = sme->sme_cookie;
3845 
3846 	if (edata->sensor >= MFI_BBU_SENSORS + MFI_MAX_LD)
3847 		return;
3848 
3849 	if (edata->sensor < MFI_BBU_SENSORS) {
3850 		if (sc->sc_bbuok)
3851 			mfii_bbu(sc, edata);
3852 	} else {
3853 		mfii_refresh_ld_sensor(sc, edata);
3854 	}
3855 }
3856