xref: /openbsd-src/sys/dev/ic/mfi.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /* $OpenBSD: mfi.c,v 1.94 2009/04/29 00:48:24 marco Exp $ */
2 /*
3  * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
4  *
5  * Permission to use, copy, modify, and distribute this software for any
6  * purpose with or without fee is hereby granted, provided that the above
7  * copyright notice and this permission notice appear in all copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16  */
17 
18 #include "bio.h"
19 
20 #include <sys/param.h>
21 #include <sys/systm.h>
22 #include <sys/buf.h>
23 #include <sys/ioctl.h>
24 #include <sys/device.h>
25 #include <sys/kernel.h>
26 #include <sys/malloc.h>
27 #include <sys/proc.h>
28 #include <sys/rwlock.h>
29 #include <sys/sensors.h>
30 
31 #include <machine/bus.h>
32 
33 #include <scsi/scsi_all.h>
34 #include <scsi/scsi_disk.h>
35 #include <scsi/scsiconf.h>
36 
37 #include <dev/biovar.h>
38 #include <dev/ic/mfireg.h>
39 #include <dev/ic/mfivar.h>
40 
41 #ifdef MFI_DEBUG
42 uint32_t	mfi_debug = 0
43 /*		    | MFI_D_CMD */
44 /*		    | MFI_D_INTR */
45 /*		    | MFI_D_MISC */
46 /*		    | MFI_D_DMA */
47 /*		    | MFI_D_IOCTL */
48 /*		    | MFI_D_RW */
49 /*		    | MFI_D_MEM */
50 /*		    | MFI_D_CCB */
51 		;
52 #endif
53 
54 struct cfdriver mfi_cd = {
55 	NULL, "mfi", DV_DULL
56 };
57 
58 int	mfi_scsi_cmd(struct scsi_xfer *);
59 int	mfi_scsi_ioctl(struct scsi_link *, u_long, caddr_t, int, struct proc *);
60 void	mfiminphys(struct buf *bp, struct scsi_link *sl);
61 
62 struct scsi_adapter mfi_switch = {
63 	mfi_scsi_cmd, mfiminphys, 0, 0, mfi_scsi_ioctl
64 };
65 
66 struct scsi_device mfi_dev = {
67 	NULL, NULL, NULL, NULL
68 };
69 
70 struct mfi_ccb	*mfi_get_ccb(struct mfi_softc *);
71 void		mfi_put_ccb(struct mfi_ccb *);
72 int		mfi_init_ccb(struct mfi_softc *);
73 
74 struct mfi_mem	*mfi_allocmem(struct mfi_softc *, size_t);
75 void		mfi_freemem(struct mfi_softc *, struct mfi_mem *);
76 
77 int		mfi_transition_firmware(struct mfi_softc *);
78 int		mfi_initialize_firmware(struct mfi_softc *);
79 int		mfi_get_info(struct mfi_softc *);
80 uint32_t	mfi_read(struct mfi_softc *, bus_size_t);
81 void		mfi_write(struct mfi_softc *, bus_size_t, uint32_t);
82 int		mfi_poll(struct mfi_ccb *);
83 int		mfi_create_sgl(struct mfi_ccb *, int);
84 
85 /* commands */
86 int		mfi_scsi_ld(struct mfi_ccb *, struct scsi_xfer *);
87 int		mfi_scsi_io(struct mfi_ccb *, struct scsi_xfer *, uint32_t,
88 		    uint32_t);
89 void		mfi_scsi_xs_done(struct mfi_ccb *);
90 int		mfi_mgmt(struct mfi_softc *, uint32_t, uint32_t, uint32_t,
91 		    void *, uint8_t *);
92 void		mfi_mgmt_done(struct mfi_ccb *);
93 
94 #if NBIO > 0
95 int		mfi_ioctl(struct device *, u_long, caddr_t);
96 int		mfi_bio_getitall(struct mfi_softc *);
97 int		mfi_ioctl_inq(struct mfi_softc *, struct bioc_inq *);
98 int		mfi_ioctl_vol(struct mfi_softc *, struct bioc_vol *);
99 int		mfi_ioctl_disk(struct mfi_softc *, struct bioc_disk *);
100 int		mfi_ioctl_alarm(struct mfi_softc *, struct bioc_alarm *);
101 int		mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *);
102 int		mfi_ioctl_setstate(struct mfi_softc *, struct bioc_setstate *);
103 int		mfi_bio_hs(struct mfi_softc *, int, int, void *);
104 #ifndef SMALL_KERNEL
105 int		mfi_create_sensors(struct mfi_softc *);
106 void		mfi_refresh_sensors(void *);
107 #endif /* SMALL_KERNEL */
108 #endif /* NBIO > 0 */
109 
110 u_int32_t	mfi_xscale_fw_state(struct mfi_softc *sc);
111 void		mfi_xscale_intr_ena(struct mfi_softc *sc);
112 int		mfi_xscale_intr(struct mfi_softc *sc);
113 void		mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
114 
115 static const struct mfi_iop_ops mfi_iop_xscale = {
116 	mfi_xscale_fw_state,
117 	mfi_xscale_intr_ena,
118 	mfi_xscale_intr,
119 	mfi_xscale_post
120 };
121 
122 u_int32_t	mfi_ppc_fw_state(struct mfi_softc *sc);
123 void		mfi_ppc_intr_ena(struct mfi_softc *sc);
124 int		mfi_ppc_intr(struct mfi_softc *sc);
125 void		mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
126 
127 static const struct mfi_iop_ops mfi_iop_ppc = {
128 	mfi_ppc_fw_state,
129 	mfi_ppc_intr_ena,
130 	mfi_ppc_intr,
131 	mfi_ppc_post
132 };
133 
134 u_int32_t	mfi_gen2_fw_state(struct mfi_softc *sc);
135 void		mfi_gen2_intr_ena(struct mfi_softc *sc);
136 int		mfi_gen2_intr(struct mfi_softc *sc);
137 void		mfi_gen2_post(struct mfi_softc *sc, struct mfi_ccb *ccb);
138 
139 static const struct mfi_iop_ops mfi_iop_gen2 = {
140 	mfi_gen2_fw_state,
141 	mfi_gen2_intr_ena,
142 	mfi_gen2_intr,
143 	mfi_gen2_post
144 };
145 
146 #define mfi_fw_state(_s)	((_s)->sc_iop->mio_fw_state(_s))
147 #define mfi_intr_enable(_s)	((_s)->sc_iop->mio_intr_ena(_s))
148 #define mfi_my_intr(_s)		((_s)->sc_iop->mio_intr(_s))
149 #define mfi_post(_s, _c)	((_s)->sc_iop->mio_post((_s), (_c)))
150 
151 struct mfi_ccb *
152 mfi_get_ccb(struct mfi_softc *sc)
153 {
154 	struct mfi_ccb		*ccb;
155 	int			s;
156 
157 	s = splbio();
158 	ccb = TAILQ_FIRST(&sc->sc_ccb_freeq);
159 	if (ccb) {
160 		TAILQ_REMOVE(&sc->sc_ccb_freeq, ccb, ccb_link);
161 		ccb->ccb_state = MFI_CCB_READY;
162 	}
163 	splx(s);
164 
165 	DNPRINTF(MFI_D_CCB, "%s: mfi_get_ccb: %p\n", DEVNAME(sc), ccb);
166 
167 	return (ccb);
168 }
169 
170 void
171 mfi_put_ccb(struct mfi_ccb *ccb)
172 {
173 	struct mfi_softc	*sc = ccb->ccb_sc;
174 	struct mfi_frame_header	*hdr = &ccb->ccb_frame->mfr_header;
175 	int			s;
176 
177 	DNPRINTF(MFI_D_CCB, "%s: mfi_put_ccb: %p\n", DEVNAME(sc), ccb);
178 
179 	hdr->mfh_cmd_status = 0x0;
180 	hdr->mfh_flags = 0x0;
181 	ccb->ccb_state = MFI_CCB_FREE;
182 	ccb->ccb_xs = NULL;
183 	ccb->ccb_flags = 0;
184 	ccb->ccb_done = NULL;
185 	ccb->ccb_direction = 0;
186 	ccb->ccb_frame_size = 0;
187 	ccb->ccb_extra_frames = 0;
188 	ccb->ccb_sgl = NULL;
189 	ccb->ccb_data = NULL;
190 	ccb->ccb_len = 0;
191 
192 	s = splbio();
193 	TAILQ_INSERT_TAIL(&sc->sc_ccb_freeq, ccb, ccb_link);
194 	splx(s);
195 }
196 
197 int
198 mfi_init_ccb(struct mfi_softc *sc)
199 {
200 	struct mfi_ccb		*ccb;
201 	uint32_t		i;
202 	int			error;
203 
204 	DNPRINTF(MFI_D_CCB, "%s: mfi_init_ccb\n", DEVNAME(sc));
205 
206 	sc->sc_ccb = malloc(sizeof(struct mfi_ccb) * sc->sc_max_cmds,
207 	    M_DEVBUF, M_WAITOK|M_ZERO);
208 
209 	for (i = 0; i < sc->sc_max_cmds; i++) {
210 		ccb = &sc->sc_ccb[i];
211 
212 		ccb->ccb_sc = sc;
213 
214 		/* select i'th frame */
215 		ccb->ccb_frame = (union mfi_frame *)
216 		    (MFIMEM_KVA(sc->sc_frames) + sc->sc_frames_size * i);
217 		ccb->ccb_pframe =
218 		    MFIMEM_DVA(sc->sc_frames) + sc->sc_frames_size * i;
219 		ccb->ccb_frame->mfr_header.mfh_context = i;
220 
221 		/* select i'th sense */
222 		ccb->ccb_sense = (struct mfi_sense *)
223 		    (MFIMEM_KVA(sc->sc_sense) + MFI_SENSE_SIZE * i);
224 		ccb->ccb_psense =
225 		    (MFIMEM_DVA(sc->sc_sense) + MFI_SENSE_SIZE * i);
226 
227 		/* create a dma map for transfer */
228 		error = bus_dmamap_create(sc->sc_dmat,
229 		    MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0,
230 		    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap);
231 		if (error) {
232 			printf("%s: cannot create ccb dmamap (%d)\n",
233 			    DEVNAME(sc), error);
234 			goto destroy;
235 		}
236 
237 		DNPRINTF(MFI_D_CCB,
238 		    "ccb(%d): %p frame: %#x (%#x) sense: %#x (%#x) map: %#x\n",
239 		    ccb->ccb_frame->mfr_header.mfh_context, ccb,
240 		    ccb->ccb_frame, ccb->ccb_pframe,
241 		    ccb->ccb_sense, ccb->ccb_psense,
242 		    ccb->ccb_dmamap);
243 
244 		/* add ccb to queue */
245 		mfi_put_ccb(ccb);
246 	}
247 
248 	return (0);
249 destroy:
250 	/* free dma maps and ccb memory */
251 	while (i) {
252 		ccb = &sc->sc_ccb[i];
253 		bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap);
254 		i--;
255 	}
256 
257 	free(sc->sc_ccb, M_DEVBUF);
258 
259 	return (1);
260 }
261 
262 uint32_t
263 mfi_read(struct mfi_softc *sc, bus_size_t r)
264 {
265 	uint32_t rv;
266 
267 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
268 	    BUS_SPACE_BARRIER_READ);
269 	rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r);
270 
271 	DNPRINTF(MFI_D_RW, "%s: mr 0x%x 0x08%x ", DEVNAME(sc), r, rv);
272 	return (rv);
273 }
274 
275 void
276 mfi_write(struct mfi_softc *sc, bus_size_t r, uint32_t v)
277 {
278 	DNPRINTF(MFI_D_RW, "%s: mw 0x%x 0x%08x", DEVNAME(sc), r, v);
279 
280 	bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v);
281 	bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4,
282 	    BUS_SPACE_BARRIER_WRITE);
283 }
284 
285 struct mfi_mem *
286 mfi_allocmem(struct mfi_softc *sc, size_t size)
287 {
288 	struct mfi_mem		*mm;
289 	int			nsegs;
290 
291 	DNPRINTF(MFI_D_MEM, "%s: mfi_allocmem: %d\n", DEVNAME(sc),
292 	    size);
293 
294 	mm = malloc(sizeof(struct mfi_mem), M_DEVBUF, M_NOWAIT|M_ZERO);
295 	if (mm == NULL)
296 		return (NULL);
297 
298 	mm->am_size = size;
299 
300 	if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0,
301 	    BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mm->am_map) != 0)
302 		goto amfree;
303 
304 	if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mm->am_seg, 1,
305 	    &nsegs, BUS_DMA_NOWAIT) != 0)
306 		goto destroy;
307 
308 	if (bus_dmamem_map(sc->sc_dmat, &mm->am_seg, nsegs, size, &mm->am_kva,
309 	    BUS_DMA_NOWAIT) != 0)
310 		goto free;
311 
312 	if (bus_dmamap_load(sc->sc_dmat, mm->am_map, mm->am_kva, size, NULL,
313 	    BUS_DMA_NOWAIT) != 0)
314 		goto unmap;
315 
316 	DNPRINTF(MFI_D_MEM, "  kva: %p  dva: %p  map: %p\n",
317 	    mm->am_kva, mm->am_map->dm_segs[0].ds_addr, mm->am_map);
318 
319 	memset(mm->am_kva, 0, size);
320 	return (mm);
321 
322 unmap:
323 	bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, size);
324 free:
325 	bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
326 destroy:
327 	bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
328 amfree:
329 	free(mm, M_DEVBUF);
330 
331 	return (NULL);
332 }
333 
334 void
335 mfi_freemem(struct mfi_softc *sc, struct mfi_mem *mm)
336 {
337 	DNPRINTF(MFI_D_MEM, "%s: mfi_freemem: %p\n", DEVNAME(sc), mm);
338 
339 	bus_dmamap_unload(sc->sc_dmat, mm->am_map);
340 	bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, mm->am_size);
341 	bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1);
342 	bus_dmamap_destroy(sc->sc_dmat, mm->am_map);
343 	free(mm, M_DEVBUF);
344 }
345 
346 int
347 mfi_transition_firmware(struct mfi_softc *sc)
348 {
349 	int32_t			fw_state, cur_state;
350 	int			max_wait, i;
351 
352 	fw_state = mfi_fw_state(sc) & MFI_STATE_MASK;
353 
354 	DNPRINTF(MFI_D_CMD, "%s: mfi_transition_firmware: %#x\n", DEVNAME(sc),
355 	    fw_state);
356 
357 	while (fw_state != MFI_STATE_READY) {
358 		DNPRINTF(MFI_D_MISC,
359 		    "%s: waiting for firmware to become ready\n",
360 		    DEVNAME(sc));
361 		cur_state = fw_state;
362 		switch (fw_state) {
363 		case MFI_STATE_FAULT:
364 			printf("%s: firmware fault\n", DEVNAME(sc));
365 			return (1);
366 		case MFI_STATE_WAIT_HANDSHAKE:
367 			mfi_write(sc, MFI_IDB, MFI_INIT_CLEAR_HANDSHAKE);
368 			max_wait = 2;
369 			break;
370 		case MFI_STATE_OPERATIONAL:
371 			mfi_write(sc, MFI_IDB, MFI_INIT_READY);
372 			max_wait = 10;
373 			break;
374 		case MFI_STATE_UNDEFINED:
375 		case MFI_STATE_BB_INIT:
376 			max_wait = 2;
377 			break;
378 		case MFI_STATE_FW_INIT:
379 		case MFI_STATE_DEVICE_SCAN:
380 		case MFI_STATE_FLUSH_CACHE:
381 			max_wait = 20;
382 			break;
383 		default:
384 			printf("%s: unknown firmware state %d\n",
385 			    DEVNAME(sc), fw_state);
386 			return (1);
387 		}
388 		for (i = 0; i < (max_wait * 10); i++) {
389 			fw_state = mfi_fw_state(sc) & MFI_STATE_MASK;
390 			if (fw_state == cur_state)
391 				DELAY(100000);
392 			else
393 				break;
394 		}
395 		if (fw_state == cur_state) {
396 			printf("%s: firmware stuck in state %#x\n",
397 			    DEVNAME(sc), fw_state);
398 			return (1);
399 		}
400 	}
401 
402 	return (0);
403 }
404 
405 int
406 mfi_initialize_firmware(struct mfi_softc *sc)
407 {
408 	struct mfi_ccb		*ccb;
409 	struct mfi_init_frame	*init;
410 	struct mfi_init_qinfo	*qinfo;
411 
412 	DNPRINTF(MFI_D_MISC, "%s: mfi_initialize_firmware\n", DEVNAME(sc));
413 
414 	if ((ccb = mfi_get_ccb(sc)) == NULL)
415 		return (1);
416 
417 	init = &ccb->ccb_frame->mfr_init;
418 	qinfo = (struct mfi_init_qinfo *)((uint8_t *)init + MFI_FRAME_SIZE);
419 
420 	memset(qinfo, 0, sizeof *qinfo);
421 	qinfo->miq_rq_entries = sc->sc_max_cmds + 1;
422 	qinfo->miq_rq_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
423 	    offsetof(struct mfi_prod_cons, mpc_reply_q));
424 	qinfo->miq_pi_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
425 	    offsetof(struct mfi_prod_cons, mpc_producer));
426 	qinfo->miq_ci_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) +
427 	    offsetof(struct mfi_prod_cons, mpc_consumer));
428 
429 	init->mif_header.mfh_cmd = MFI_CMD_INIT;
430 	init->mif_header.mfh_data_len = sizeof *qinfo;
431 	init->mif_qinfo_new_addr_lo = htole32(ccb->ccb_pframe + MFI_FRAME_SIZE);
432 
433 	DNPRINTF(MFI_D_MISC, "%s: entries: %#x rq: %#x pi: %#x ci: %#x\n",
434 	    DEVNAME(sc),
435 	    qinfo->miq_rq_entries, qinfo->miq_rq_addr_lo,
436 	    qinfo->miq_pi_addr_lo, qinfo->miq_ci_addr_lo);
437 
438 	if (mfi_poll(ccb)) {
439 		printf("%s: mfi_initialize_firmware failed\n", DEVNAME(sc));
440 		return (1);
441 	}
442 
443 	mfi_put_ccb(ccb);
444 
445 	return (0);
446 }
447 
448 int
449 mfi_get_info(struct mfi_softc *sc)
450 {
451 #ifdef MFI_DEBUG
452 	int i;
453 #endif
454 	DNPRINTF(MFI_D_MISC, "%s: mfi_get_info\n", DEVNAME(sc));
455 
456 	if (mfi_mgmt(sc, MR_DCMD_CTRL_GET_INFO, MFI_DATA_IN,
457 	    sizeof(sc->sc_info), &sc->sc_info, NULL))
458 		return (1);
459 
460 #ifdef MFI_DEBUG
461 	for (i = 0; i < sc->sc_info.mci_image_component_count; i++) {
462 		printf("%s: active FW %s Version %s date %s time %s\n",
463 		    DEVNAME(sc),
464 		    sc->sc_info.mci_image_component[i].mic_name,
465 		    sc->sc_info.mci_image_component[i].mic_version,
466 		    sc->sc_info.mci_image_component[i].mic_build_date,
467 		    sc->sc_info.mci_image_component[i].mic_build_time);
468 	}
469 
470 	for (i = 0; i < sc->sc_info.mci_pending_image_component_count; i++) {
471 		printf("%s: pending FW %s Version %s date %s time %s\n",
472 		    DEVNAME(sc),
473 		    sc->sc_info.mci_pending_image_component[i].mic_name,
474 		    sc->sc_info.mci_pending_image_component[i].mic_version,
475 		    sc->sc_info.mci_pending_image_component[i].mic_build_date,
476 		    sc->sc_info.mci_pending_image_component[i].mic_build_time);
477 	}
478 
479 	printf("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n",
480 	    DEVNAME(sc),
481 	    sc->sc_info.mci_max_arms,
482 	    sc->sc_info.mci_max_spans,
483 	    sc->sc_info.mci_max_arrays,
484 	    sc->sc_info.mci_max_lds,
485 	    sc->sc_info.mci_product_name);
486 
487 	printf("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n",
488 	    DEVNAME(sc),
489 	    sc->sc_info.mci_serial_number,
490 	    sc->sc_info.mci_hw_present,
491 	    sc->sc_info.mci_current_fw_time,
492 	    sc->sc_info.mci_max_cmds,
493 	    sc->sc_info.mci_max_sg_elements);
494 
495 	printf("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n",
496 	    DEVNAME(sc),
497 	    sc->sc_info.mci_max_request_size,
498 	    sc->sc_info.mci_lds_present,
499 	    sc->sc_info.mci_lds_degraded,
500 	    sc->sc_info.mci_lds_offline,
501 	    sc->sc_info.mci_pd_present);
502 
503 	printf("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n",
504 	    DEVNAME(sc),
505 	    sc->sc_info.mci_pd_disks_present,
506 	    sc->sc_info.mci_pd_disks_pred_failure,
507 	    sc->sc_info.mci_pd_disks_failed);
508 
509 	printf("%s: nvram %d mem %d flash %d\n",
510 	    DEVNAME(sc),
511 	    sc->sc_info.mci_nvram_size,
512 	    sc->sc_info.mci_memory_size,
513 	    sc->sc_info.mci_flash_size);
514 
515 	printf("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n",
516 	    DEVNAME(sc),
517 	    sc->sc_info.mci_ram_correctable_errors,
518 	    sc->sc_info.mci_ram_uncorrectable_errors,
519 	    sc->sc_info.mci_cluster_allowed,
520 	    sc->sc_info.mci_cluster_active);
521 
522 	printf("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n",
523 	    DEVNAME(sc),
524 	    sc->sc_info.mci_max_strips_per_io,
525 	    sc->sc_info.mci_raid_levels,
526 	    sc->sc_info.mci_adapter_ops,
527 	    sc->sc_info.mci_ld_ops);
528 
529 	printf("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n",
530 	    DEVNAME(sc),
531 	    sc->sc_info.mci_stripe_sz_ops.min,
532 	    sc->sc_info.mci_stripe_sz_ops.max,
533 	    sc->sc_info.mci_pd_ops,
534 	    sc->sc_info.mci_pd_mix_support);
535 
536 	printf("%s: ecc_bucket %d pckg_prop %s\n",
537 	    DEVNAME(sc),
538 	    sc->sc_info.mci_ecc_bucket_count,
539 	    sc->sc_info.mci_package_version);
540 
541 	printf("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n",
542 	    DEVNAME(sc),
543 	    sc->sc_info.mci_properties.mcp_seq_num,
544 	    sc->sc_info.mci_properties.mcp_pred_fail_poll_interval,
545 	    sc->sc_info.mci_properties.mcp_intr_throttle_cnt,
546 	    sc->sc_info.mci_properties.mcp_intr_throttle_timeout);
547 
548 	printf("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n",
549 	    DEVNAME(sc),
550 	    sc->sc_info.mci_properties.mcp_rebuild_rate,
551 	    sc->sc_info.mci_properties.mcp_patrol_read_rate,
552 	    sc->sc_info.mci_properties.mcp_bgi_rate,
553 	    sc->sc_info.mci_properties.mcp_cc_rate);
554 
555 	printf("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n",
556 	    DEVNAME(sc),
557 	    sc->sc_info.mci_properties.mcp_recon_rate,
558 	    sc->sc_info.mci_properties.mcp_cache_flush_interval,
559 	    sc->sc_info.mci_properties.mcp_spinup_drv_cnt,
560 	    sc->sc_info.mci_properties.mcp_spinup_delay,
561 	    sc->sc_info.mci_properties.mcp_cluster_enable);
562 
563 	printf("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n",
564 	    DEVNAME(sc),
565 	    sc->sc_info.mci_properties.mcp_coercion_mode,
566 	    sc->sc_info.mci_properties.mcp_alarm_enable,
567 	    sc->sc_info.mci_properties.mcp_disable_auto_rebuild,
568 	    sc->sc_info.mci_properties.mcp_disable_battery_warn,
569 	    sc->sc_info.mci_properties.mcp_ecc_bucket_size);
570 
571 	printf("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n",
572 	    DEVNAME(sc),
573 	    sc->sc_info.mci_properties.mcp_ecc_bucket_leak_rate,
574 	    sc->sc_info.mci_properties.mcp_restore_hotspare_on_insertion,
575 	    sc->sc_info.mci_properties.mcp_expose_encl_devices);
576 
577 	printf("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n",
578 	    DEVNAME(sc),
579 	    sc->sc_info.mci_pci.mip_vendor,
580 	    sc->sc_info.mci_pci.mip_device,
581 	    sc->sc_info.mci_pci.mip_subvendor,
582 	    sc->sc_info.mci_pci.mip_subdevice);
583 
584 	printf("%s: type %#x port_count %d port_addr ",
585 	    DEVNAME(sc),
586 	    sc->sc_info.mci_host.mih_type,
587 	    sc->sc_info.mci_host.mih_port_count);
588 
589 	for (i = 0; i < 8; i++)
590 		printf("%.0llx ", sc->sc_info.mci_host.mih_port_addr[i]);
591 	printf("\n");
592 
593 	printf("%s: type %.x port_count %d port_addr ",
594 	    DEVNAME(sc),
595 	    sc->sc_info.mci_device.mid_type,
596 	    sc->sc_info.mci_device.mid_port_count);
597 
598 	for (i = 0; i < 8; i++)
599 		printf("%.0llx ", sc->sc_info.mci_device.mid_port_addr[i]);
600 	printf("\n");
601 #endif /* MFI_DEBUG */
602 
603 	return (0);
604 }
605 
606 void
607 mfiminphys(struct buf *bp, struct scsi_link *sl)
608 {
609 	DNPRINTF(MFI_D_MISC, "mfiminphys: %d\n", bp->b_bcount);
610 
611 	/* XXX currently using MFI_MAXFER = MAXPHYS */
612 	if (bp->b_bcount > MFI_MAXFER)
613 		bp->b_bcount = MFI_MAXFER;
614 	minphys(bp);
615 }
616 
617 int
618 mfi_attach(struct mfi_softc *sc, enum mfi_iop iop)
619 {
620 	struct scsibus_attach_args saa;
621 	uint32_t		status, frames;
622 	int			i;
623 
624 	switch (iop) {
625 	case MFI_IOP_XSCALE:
626 		sc->sc_iop = &mfi_iop_xscale;
627 		break;
628 	case MFI_IOP_PPC:
629 		sc->sc_iop = &mfi_iop_ppc;
630 		break;
631 	case MFI_IOP_GEN2:
632 		sc->sc_iop = &mfi_iop_gen2;
633 		break;
634 	default:
635 		panic("%s: unknown iop %d", DEVNAME(sc), iop);
636 	}
637 
638 	DNPRINTF(MFI_D_MISC, "%s: mfi_attach\n", DEVNAME(sc));
639 
640 	if (mfi_transition_firmware(sc))
641 		return (1);
642 
643 	TAILQ_INIT(&sc->sc_ccb_freeq);
644 
645 	rw_init(&sc->sc_lock, "mfi_lock");
646 
647 	status = mfi_fw_state(sc);
648 	sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK;
649 	sc->sc_max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16;
650 	DNPRINTF(MFI_D_MISC, "%s: max commands: %u, max sgl: %u\n",
651 	    DEVNAME(sc), sc->sc_max_cmds, sc->sc_max_sgl);
652 
653 	/* consumer/producer and reply queue memory */
654 	sc->sc_pcq = mfi_allocmem(sc, (sizeof(uint32_t) * sc->sc_max_cmds) +
655 	    sizeof(struct mfi_prod_cons));
656 	if (sc->sc_pcq == NULL) {
657 		printf("%s: unable to allocate reply queue memory\n",
658 		    DEVNAME(sc));
659 		goto nopcq;
660 	}
661 
662 	/* frame memory */
663 	/* we are not doing 64 bit IO so only calculate # of 32 bit frames */
664 	frames = (sizeof(struct mfi_sg32) * sc->sc_max_sgl +
665 	    MFI_FRAME_SIZE - 1) / MFI_FRAME_SIZE + 1;
666 	sc->sc_frames_size = frames * MFI_FRAME_SIZE;
667 	sc->sc_frames = mfi_allocmem(sc, sc->sc_frames_size * sc->sc_max_cmds);
668 	if (sc->sc_frames == NULL) {
669 		printf("%s: unable to allocate frame memory\n", DEVNAME(sc));
670 		goto noframe;
671 	}
672 	/* XXX hack, fix this */
673 	if (MFIMEM_DVA(sc->sc_frames) & 0x3f) {
674 		printf("%s: improper frame alignment (%#x) FIXME\n",
675 		    DEVNAME(sc), MFIMEM_DVA(sc->sc_frames));
676 		goto noframe;
677 	}
678 
679 	/* sense memory */
680 	sc->sc_sense = mfi_allocmem(sc, sc->sc_max_cmds * MFI_SENSE_SIZE);
681 	if (sc->sc_sense == NULL) {
682 		printf("%s: unable to allocate sense memory\n", DEVNAME(sc));
683 		goto nosense;
684 	}
685 
686 	/* now that we have all memory bits go initialize ccbs */
687 	if (mfi_init_ccb(sc)) {
688 		printf("%s: could not init ccb list\n", DEVNAME(sc));
689 		goto noinit;
690 	}
691 
692 	/* kickstart firmware with all addresses and pointers */
693 	if (mfi_initialize_firmware(sc)) {
694 		printf("%s: could not initialize firmware\n", DEVNAME(sc));
695 		goto noinit;
696 	}
697 
698 	if (mfi_get_info(sc)) {
699 		printf("%s: could not retrieve controller information\n",
700 		    DEVNAME(sc));
701 		goto noinit;
702 	}
703 
704 	printf("%s: logical drives %d, version %s, %dMB RAM\n",
705 	    DEVNAME(sc),
706 	    sc->sc_info.mci_lds_present,
707 	    sc->sc_info.mci_package_version,
708 	    sc->sc_info.mci_memory_size);
709 
710 	sc->sc_ld_cnt = sc->sc_info.mci_lds_present;
711 	sc->sc_max_ld = sc->sc_ld_cnt;
712 	for (i = 0; i < sc->sc_ld_cnt; i++)
713 		sc->sc_ld[i].ld_present = 1;
714 
715 	if (sc->sc_ld_cnt)
716 		sc->sc_link.openings = sc->sc_max_cmds / sc->sc_ld_cnt;
717 	else
718 		sc->sc_link.openings = sc->sc_max_cmds;
719 
720 	sc->sc_link.device = &mfi_dev;
721 	sc->sc_link.adapter_softc = sc;
722 	sc->sc_link.adapter = &mfi_switch;
723 	sc->sc_link.adapter_target = MFI_MAX_LD;
724 	sc->sc_link.adapter_buswidth = sc->sc_max_ld;
725 
726 	bzero(&saa, sizeof(saa));
727 	saa.saa_sc_link = &sc->sc_link;
728 
729 	config_found(&sc->sc_dev, &saa, scsiprint);
730 
731 	/* enable interrupts */
732 	mfi_intr_enable(sc);
733 
734 #if NBIO > 0
735 	if (bio_register(&sc->sc_dev, mfi_ioctl) != 0)
736 		panic("%s: controller registration failed", DEVNAME(sc));
737 	else
738 		sc->sc_ioctl = mfi_ioctl;
739 
740 #ifndef SMALL_KERNEL
741 	if (mfi_create_sensors(sc) != 0)
742 		printf("%s: unable to create sensors\n", DEVNAME(sc));
743 #endif
744 #endif /* NBIO > 0 */
745 
746 	return (0);
747 noinit:
748 	mfi_freemem(sc, sc->sc_sense);
749 nosense:
750 	mfi_freemem(sc, sc->sc_frames);
751 noframe:
752 	mfi_freemem(sc, sc->sc_pcq);
753 nopcq:
754 	return (1);
755 }
756 
757 int
758 mfi_poll(struct mfi_ccb *ccb)
759 {
760 	struct mfi_softc *sc = ccb->ccb_sc;
761 	struct mfi_frame_header	*hdr;
762 	int			to = 0, rv = 0;
763 
764 	DNPRINTF(MFI_D_CMD, "%s: mfi_poll\n", DEVNAME(sc));
765 
766 	hdr = &ccb->ccb_frame->mfr_header;
767 	hdr->mfh_cmd_status = 0xff;
768 	hdr->mfh_flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
769 
770 	mfi_post(sc, ccb);
771 
772 	while (hdr->mfh_cmd_status == 0xff) {
773 		delay(1000);
774 		if (to++ > 5000) /* XXX 5 seconds busywait sucks */
775 			break;
776 	}
777 	if (hdr->mfh_cmd_status == 0xff) {
778 		printf("%s: timeout on ccb %d\n", DEVNAME(sc),
779 		    hdr->mfh_context);
780 		ccb->ccb_flags |= MFI_CCB_F_ERR;
781 		rv = 1;
782 	}
783 
784 	if (ccb->ccb_direction != MFI_DATA_NONE) {
785 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
786 		    ccb->ccb_dmamap->dm_mapsize,
787 		    (ccb->ccb_direction & MFI_DATA_IN) ?
788 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
789 
790 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
791 	}
792 
793 	return (rv);
794 }
795 
796 int
797 mfi_intr(void *arg)
798 {
799 	struct mfi_softc	*sc = arg;
800 	struct mfi_prod_cons	*pcq;
801 	struct mfi_ccb		*ccb;
802 	uint32_t		producer, consumer, ctx;
803 	int			claimed = 0;
804 
805 	if (!mfi_my_intr(sc))
806 		return (0);
807 
808 	pcq = MFIMEM_KVA(sc->sc_pcq);
809 	producer = pcq->mpc_producer;
810 	consumer = pcq->mpc_consumer;
811 
812 	DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#x %#x\n", DEVNAME(sc), sc, pcq);
813 
814 	while (consumer != producer) {
815 		DNPRINTF(MFI_D_INTR, "%s: mfi_intr pi %#x ci %#x\n",
816 		    DEVNAME(sc), producer, consumer);
817 
818 		ctx = pcq->mpc_reply_q[consumer];
819 		pcq->mpc_reply_q[consumer] = MFI_INVALID_CTX;
820 		if (ctx == MFI_INVALID_CTX)
821 			printf("%s: invalid context, p: %d c: %d\n",
822 			    DEVNAME(sc), producer, consumer);
823 		else {
824 			/* XXX remove from queue and call scsi_done */
825 			ccb = &sc->sc_ccb[ctx];
826 			DNPRINTF(MFI_D_INTR, "%s: mfi_intr context %#x\n",
827 			    DEVNAME(sc), ctx);
828 			ccb->ccb_done(ccb);
829 
830 			claimed = 1;
831 		}
832 		consumer++;
833 		if (consumer == (sc->sc_max_cmds + 1))
834 			consumer = 0;
835 	}
836 
837 	pcq->mpc_consumer = consumer;
838 
839 	return (claimed);
840 }
841 
842 int
843 mfi_scsi_io(struct mfi_ccb *ccb, struct scsi_xfer *xs, uint32_t blockno,
844     uint32_t blockcnt)
845 {
846 	struct scsi_link	*link = xs->sc_link;
847 	struct mfi_io_frame	*io;
848 
849 	DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_io: %d\n",
850 	    DEVNAME((struct mfi_softc *)link->adapter_softc), link->target);
851 
852 	if (!xs->data)
853 		return (1);
854 
855 	io = &ccb->ccb_frame->mfr_io;
856 	if (xs->flags & SCSI_DATA_IN) {
857 		io->mif_header.mfh_cmd = MFI_CMD_LD_READ;
858 		ccb->ccb_direction = MFI_DATA_IN;
859 	} else {
860 		io->mif_header.mfh_cmd = MFI_CMD_LD_WRITE;
861 		ccb->ccb_direction = MFI_DATA_OUT;
862 	}
863 	io->mif_header.mfh_target_id = link->target;
864 	io->mif_header.mfh_timeout = 0;
865 	io->mif_header.mfh_flags = 0;
866 	io->mif_header.mfh_sense_len = MFI_SENSE_SIZE;
867 	io->mif_header.mfh_data_len= blockcnt;
868 	io->mif_lba_hi = 0;
869 	io->mif_lba_lo = blockno;
870 	io->mif_sense_addr_lo = htole32(ccb->ccb_psense);
871 	io->mif_sense_addr_hi = 0;
872 
873 	ccb->ccb_done = mfi_scsi_xs_done;
874 	ccb->ccb_xs = xs;
875 	ccb->ccb_frame_size = MFI_IO_FRAME_SIZE;
876 	ccb->ccb_sgl = &io->mif_sgl;
877 	ccb->ccb_data = xs->data;
878 	ccb->ccb_len = xs->datalen;
879 
880 	if (mfi_create_sgl(ccb, (xs->flags & SCSI_NOSLEEP) ?
881 	    BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
882 		return (1);
883 
884 	return (0);
885 }
886 
887 void
888 mfi_scsi_xs_done(struct mfi_ccb *ccb)
889 {
890 	struct scsi_xfer	*xs = ccb->ccb_xs;
891 	struct mfi_softc	*sc = ccb->ccb_sc;
892 	struct mfi_frame_header	*hdr = &ccb->ccb_frame->mfr_header;
893 
894 	DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done %#x %#x\n",
895 	    DEVNAME(sc), ccb, ccb->ccb_frame);
896 
897 	if (xs->data != NULL) {
898 		DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done sync\n",
899 		    DEVNAME(sc));
900 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
901 		    ccb->ccb_dmamap->dm_mapsize,
902 		    (xs->flags & SCSI_DATA_IN) ?
903 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
904 
905 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
906 	}
907 
908 	if (hdr->mfh_cmd_status != MFI_STAT_OK) {
909 		xs->error = XS_DRIVER_STUFFUP;
910 		DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done stuffup %#x\n",
911 		    DEVNAME(sc), hdr->mfh_cmd_status);
912 
913 		if (hdr->mfh_scsi_status != 0) {
914 			DNPRINTF(MFI_D_INTR,
915 			    "%s: mfi_scsi_xs_done sense %#x %x %x\n",
916 			    DEVNAME(sc), hdr->mfh_scsi_status,
917 			    &xs->sense, ccb->ccb_sense);
918 			memset(&xs->sense, 0, sizeof(xs->sense));
919 			memcpy(&xs->sense, ccb->ccb_sense,
920 			    sizeof(struct scsi_sense_data));
921 			xs->error = XS_SENSE;
922 		}
923 	}
924 
925 	xs->resid = 0;
926 	xs->flags |= ITSDONE;
927 
928 	mfi_put_ccb(ccb);
929 	scsi_done(xs);
930 }
931 
932 int
933 mfi_scsi_ld(struct mfi_ccb *ccb, struct scsi_xfer *xs)
934 {
935 	struct scsi_link	*link = xs->sc_link;
936 	struct mfi_pass_frame	*pf;
937 
938 	DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_ld: %d\n",
939 	    DEVNAME((struct mfi_softc *)link->adapter_softc), link->target);
940 
941 	pf = &ccb->ccb_frame->mfr_pass;
942 	pf->mpf_header.mfh_cmd = MFI_CMD_LD_SCSI_IO;
943 	pf->mpf_header.mfh_target_id = link->target;
944 	pf->mpf_header.mfh_lun_id = 0;
945 	pf->mpf_header.mfh_cdb_len = xs->cmdlen;
946 	pf->mpf_header.mfh_timeout = 0;
947 	pf->mpf_header.mfh_data_len= xs->datalen; /* XXX */
948 	pf->mpf_header.mfh_sense_len = MFI_SENSE_SIZE;
949 
950 	pf->mpf_sense_addr_hi = 0;
951 	pf->mpf_sense_addr_lo = htole32(ccb->ccb_psense);
952 
953 	memset(pf->mpf_cdb, 0, 16);
954 	memcpy(pf->mpf_cdb, &xs->cmdstore, xs->cmdlen);
955 
956 	ccb->ccb_done = mfi_scsi_xs_done;
957 	ccb->ccb_xs = xs;
958 	ccb->ccb_frame_size = MFI_PASS_FRAME_SIZE;
959 	ccb->ccb_sgl = &pf->mpf_sgl;
960 
961 	if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))
962 		ccb->ccb_direction = xs->flags & SCSI_DATA_IN ?
963 		    MFI_DATA_IN : MFI_DATA_OUT;
964 	else
965 		ccb->ccb_direction = MFI_DATA_NONE;
966 
967 	if (xs->data) {
968 		ccb->ccb_data = xs->data;
969 		ccb->ccb_len = xs->datalen;
970 
971 		if (mfi_create_sgl(ccb, (xs->flags & SCSI_NOSLEEP) ?
972 		    BUS_DMA_NOWAIT : BUS_DMA_WAITOK))
973 			return (1);
974 	}
975 
976 	return (0);
977 }
978 
979 int
980 mfi_scsi_cmd(struct scsi_xfer *xs)
981 {
982 	struct scsi_link	*link = xs->sc_link;
983 	struct mfi_softc	*sc = link->adapter_softc;
984 	struct device		*dev = link->device_softc;
985 	struct mfi_ccb		*ccb;
986 	struct scsi_rw		*rw;
987 	struct scsi_rw_big	*rwb;
988 	uint32_t		blockno, blockcnt;
989 	uint8_t			target = link->target;
990 	uint8_t			mbox[MFI_MBOX_SIZE];
991 	int			s;
992 
993 	DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_cmd opcode: %#x\n",
994 	    DEVNAME(sc), xs->cmd->opcode);
995 
996 	if (target >= MFI_MAX_LD || !sc->sc_ld[target].ld_present ||
997 	    link->lun != 0) {
998 		DNPRINTF(MFI_D_CMD, "%s: invalid target %d\n",
999 		    DEVNAME(sc), target);
1000 		goto stuffup;
1001 	}
1002 
1003 	if ((ccb = mfi_get_ccb(sc)) == NULL) {
1004 		DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_cmd no ccb\n", DEVNAME(sc));
1005 		return (NO_CCB);
1006 	}
1007 
1008 	xs->error = XS_NOERROR;
1009 
1010 	switch (xs->cmd->opcode) {
1011 	/* IO path */
1012 	case READ_BIG:
1013 	case WRITE_BIG:
1014 		rwb = (struct scsi_rw_big *)xs->cmd;
1015 		blockno = _4btol(rwb->addr);
1016 		blockcnt = _2btol(rwb->length);
1017 		if (mfi_scsi_io(ccb, xs, blockno, blockcnt)) {
1018 			mfi_put_ccb(ccb);
1019 			goto stuffup;
1020 		}
1021 		break;
1022 
1023 	case READ_COMMAND:
1024 	case WRITE_COMMAND:
1025 		rw = (struct scsi_rw *)xs->cmd;
1026 		blockno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff);
1027 		blockcnt = rw->length ? rw->length : 0x100;
1028 		if (mfi_scsi_io(ccb, xs, blockno, blockcnt)) {
1029 			mfi_put_ccb(ccb);
1030 			goto stuffup;
1031 		}
1032 		break;
1033 
1034 	case SYNCHRONIZE_CACHE:
1035 		mfi_put_ccb(ccb); /* we don't need this */
1036 
1037 		mbox[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE;
1038 		if (mfi_mgmt(sc, MR_DCMD_CTRL_CACHE_FLUSH, MFI_DATA_NONE,
1039 		    0, NULL, mbox))
1040 			goto stuffup;
1041 
1042 		goto complete;
1043 		/* NOTREACHED */
1044 
1045 	/* hand it of to the firmware and let it deal with it */
1046 	case TEST_UNIT_READY:
1047 		/* save off sd? after autoconf */
1048 		if (!cold)	/* XXX bogus */
1049 			strlcpy(sc->sc_ld[target].ld_dev, dev->dv_xname,
1050 			    sizeof(sc->sc_ld[target].ld_dev));
1051 		/* FALLTHROUGH */
1052 
1053 	default:
1054 		if (mfi_scsi_ld(ccb, xs)) {
1055 			mfi_put_ccb(ccb);
1056 			goto stuffup;
1057 		}
1058 		break;
1059 	}
1060 
1061 	DNPRINTF(MFI_D_CMD, "%s: start io %d\n", DEVNAME(sc), target);
1062 
1063 	if (xs->flags & SCSI_POLL) {
1064 		if (mfi_poll(ccb)) {
1065 			/* XXX check for sense in ccb->ccb_sense? */
1066 			printf("%s: mfi_scsi_cmd poll failed\n",
1067 			    DEVNAME(sc));
1068 			bzero(&xs->sense, sizeof(xs->sense));
1069 			xs->sense.error_code = SSD_ERRCODE_VALID | 0x70;
1070 			xs->sense.flags = SKEY_ILLEGAL_REQUEST;
1071 			xs->sense.add_sense_code = 0x20; /* invalid opcode */
1072 			xs->error = XS_SENSE;
1073 		}
1074 
1075 		mfi_put_ccb(ccb);
1076 		xs->flags |= ITSDONE;
1077 		s = splbio();
1078 		scsi_done(xs);
1079 		splx(s);
1080 		return (COMPLETE);
1081 	}
1082 
1083 	mfi_post(sc, ccb);
1084 
1085 	DNPRINTF(MFI_D_DMA, "%s: mfi_scsi_cmd queued %d\n", DEVNAME(sc),
1086 	    ccb->ccb_dmamap->dm_nsegs);
1087 
1088 	return (SUCCESSFULLY_QUEUED);
1089 
1090 stuffup:
1091 	xs->error = XS_DRIVER_STUFFUP;
1092 complete:
1093 	xs->flags |= ITSDONE;
1094 	s = splbio();
1095 	scsi_done(xs);
1096 	splx(s);
1097 	return (COMPLETE);
1098 }
1099 
1100 int
1101 mfi_create_sgl(struct mfi_ccb *ccb, int flags)
1102 {
1103 	struct mfi_softc	*sc = ccb->ccb_sc;
1104 	struct mfi_frame_header	*hdr;
1105 	bus_dma_segment_t	*sgd;
1106 	union mfi_sgl		*sgl;
1107 	int			error, i;
1108 
1109 	DNPRINTF(MFI_D_DMA, "%s: mfi_create_sgl %#x\n", DEVNAME(sc),
1110 	    ccb->ccb_data);
1111 
1112 	if (!ccb->ccb_data)
1113 		return (1);
1114 
1115 	error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap,
1116 	    ccb->ccb_data, ccb->ccb_len, NULL, flags);
1117 	if (error) {
1118 		if (error == EFBIG)
1119 			printf("more than %d dma segs\n",
1120 			    sc->sc_max_sgl);
1121 		else
1122 			printf("error %d loading dma map\n", error);
1123 		return (1);
1124 	}
1125 
1126 	hdr = &ccb->ccb_frame->mfr_header;
1127 	sgl = ccb->ccb_sgl;
1128 	sgd = ccb->ccb_dmamap->dm_segs;
1129 	for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) {
1130 		sgl->sg32[i].addr = htole32(sgd[i].ds_addr);
1131 		sgl->sg32[i].len = htole32(sgd[i].ds_len);
1132 		DNPRINTF(MFI_D_DMA, "%s: addr: %#x  len: %#x\n",
1133 		    DEVNAME(sc), sgl->sg32[i].addr, sgl->sg32[i].len);
1134 	}
1135 
1136 	if (ccb->ccb_direction == MFI_DATA_IN) {
1137 		hdr->mfh_flags |= MFI_FRAME_DIR_READ;
1138 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
1139 		    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
1140 	} else {
1141 		hdr->mfh_flags |= MFI_FRAME_DIR_WRITE;
1142 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
1143 		    ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE);
1144 	}
1145 
1146 	hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs;
1147 	/* for 64 bit io make the sizeof a variable to hold whatever sg size */
1148 	ccb->ccb_frame_size += sizeof(struct mfi_sg32) *
1149 	    ccb->ccb_dmamap->dm_nsegs;
1150 	ccb->ccb_extra_frames = (ccb->ccb_frame_size - 1) / MFI_FRAME_SIZE;
1151 
1152 	DNPRINTF(MFI_D_DMA, "%s: sg_count: %d  frame_size: %d  frames_size: %d"
1153 	    "  dm_nsegs: %d  extra_frames: %d\n",
1154 	    DEVNAME(sc),
1155 	    hdr->mfh_sg_count,
1156 	    ccb->ccb_frame_size,
1157 	    sc->sc_frames_size,
1158 	    ccb->ccb_dmamap->dm_nsegs,
1159 	    ccb->ccb_extra_frames);
1160 
1161 	return (0);
1162 }
1163 
1164 int
1165 mfi_mgmt(struct mfi_softc *sc, uint32_t opc, uint32_t dir, uint32_t len,
1166     void *buf, uint8_t *mbox)
1167 {
1168 	struct mfi_ccb		*ccb;
1169 	struct mfi_dcmd_frame	*dcmd;
1170 	int			rv = 1;
1171 	int			s;
1172 
1173 	DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt %#x\n", DEVNAME(sc), opc);
1174 
1175 	if ((ccb = mfi_get_ccb(sc)) == NULL)
1176 		return (rv);
1177 
1178 	dcmd = &ccb->ccb_frame->mfr_dcmd;
1179 	memset(dcmd->mdf_mbox, 0, MFI_MBOX_SIZE);
1180 	dcmd->mdf_header.mfh_cmd = MFI_CMD_DCMD;
1181 	dcmd->mdf_header.mfh_timeout = 0;
1182 
1183 	dcmd->mdf_opcode = opc;
1184 	dcmd->mdf_header.mfh_data_len = 0;
1185 	ccb->ccb_direction = dir;
1186 	ccb->ccb_done = mfi_mgmt_done;
1187 
1188 	ccb->ccb_frame_size = MFI_DCMD_FRAME_SIZE;
1189 
1190 	/* handle special opcodes */
1191 	if (mbox)
1192 		memcpy(dcmd->mdf_mbox, mbox, MFI_MBOX_SIZE);
1193 
1194 	if (dir != MFI_DATA_NONE) {
1195 		dcmd->mdf_header.mfh_data_len = len;
1196 		ccb->ccb_data = buf;
1197 		ccb->ccb_len = len;
1198 		ccb->ccb_sgl = &dcmd->mdf_sgl;
1199 
1200 		if (mfi_create_sgl(ccb, BUS_DMA_WAITOK))
1201 			goto done;
1202 	}
1203 
1204 	if (cold) {
1205 		if (mfi_poll(ccb))
1206 			goto done;
1207 	} else {
1208 		s = splbio();
1209 		mfi_post(sc, ccb);
1210 
1211 		DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt sleeping\n", DEVNAME(sc));
1212 		while (ccb->ccb_state != MFI_CCB_DONE)
1213 			tsleep(ccb, PRIBIO, "mfi_mgmt", 0);
1214 		splx(s);
1215 
1216 		if (ccb->ccb_flags & MFI_CCB_F_ERR)
1217 			goto done;
1218 	}
1219 
1220 	rv = 0;
1221 
1222 done:
1223 	mfi_put_ccb(ccb);
1224 	return (rv);
1225 }
1226 
1227 void
1228 mfi_mgmt_done(struct mfi_ccb *ccb)
1229 {
1230 	struct mfi_softc	*sc = ccb->ccb_sc;
1231 	struct mfi_frame_header	*hdr = &ccb->ccb_frame->mfr_header;
1232 
1233 	DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done %#x %#x\n",
1234 	    DEVNAME(sc), ccb, ccb->ccb_frame);
1235 
1236 	if (ccb->ccb_data != NULL) {
1237 		DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done sync\n",
1238 		    DEVNAME(sc));
1239 		bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0,
1240 		    ccb->ccb_dmamap->dm_mapsize,
1241 		    (ccb->ccb_direction & MFI_DATA_IN) ?
1242 		    BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
1243 
1244 		bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmamap);
1245 	}
1246 
1247 	if (hdr->mfh_cmd_status != MFI_STAT_OK)
1248 		ccb->ccb_flags |= MFI_CCB_F_ERR;
1249 
1250 	ccb->ccb_state = MFI_CCB_DONE;
1251 
1252 	wakeup(ccb);
1253 }
1254 
1255 int
1256 mfi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag,
1257     struct proc *p)
1258 {
1259 	struct mfi_softc	*sc = (struct mfi_softc *)link->adapter_softc;
1260 
1261 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_scsi_ioctl\n", DEVNAME(sc));
1262 
1263 	if (sc->sc_ioctl)
1264 		return (sc->sc_ioctl(link->adapter_softc, cmd, addr));
1265 	else
1266 		return (ENOTTY);
1267 }
1268 
1269 #if NBIO > 0
1270 int
1271 mfi_ioctl(struct device *dev, u_long cmd, caddr_t addr)
1272 {
1273 	struct mfi_softc	*sc = (struct mfi_softc *)dev;
1274 	int error = 0;
1275 
1276 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl ", DEVNAME(sc));
1277 
1278 	rw_enter_write(&sc->sc_lock);
1279 
1280 	switch (cmd) {
1281 	case BIOCINQ:
1282 		DNPRINTF(MFI_D_IOCTL, "inq\n");
1283 		error = mfi_ioctl_inq(sc, (struct bioc_inq *)addr);
1284 		break;
1285 
1286 	case BIOCVOL:
1287 		DNPRINTF(MFI_D_IOCTL, "vol\n");
1288 		error = mfi_ioctl_vol(sc, (struct bioc_vol *)addr);
1289 		break;
1290 
1291 	case BIOCDISK:
1292 		DNPRINTF(MFI_D_IOCTL, "disk\n");
1293 		error = mfi_ioctl_disk(sc, (struct bioc_disk *)addr);
1294 		break;
1295 
1296 	case BIOCALARM:
1297 		DNPRINTF(MFI_D_IOCTL, "alarm\n");
1298 		error = mfi_ioctl_alarm(sc, (struct bioc_alarm *)addr);
1299 		break;
1300 
1301 	case BIOCBLINK:
1302 		DNPRINTF(MFI_D_IOCTL, "blink\n");
1303 		error = mfi_ioctl_blink(sc, (struct bioc_blink *)addr);
1304 		break;
1305 
1306 	case BIOCSETSTATE:
1307 		DNPRINTF(MFI_D_IOCTL, "setstate\n");
1308 		error = mfi_ioctl_setstate(sc, (struct bioc_setstate *)addr);
1309 		break;
1310 
1311 	default:
1312 		DNPRINTF(MFI_D_IOCTL, " invalid ioctl\n");
1313 		error = EINVAL;
1314 	}
1315 
1316 	rw_exit_write(&sc->sc_lock);
1317 
1318 	return (error);
1319 }
1320 
1321 int
1322 mfi_bio_getitall(struct mfi_softc *sc)
1323 {
1324 	int			i, d, size, rv = EINVAL;
1325 	uint8_t			mbox[MFI_MBOX_SIZE];
1326 	struct mfi_conf		*cfg = NULL;
1327 	struct mfi_ld_details	*ld_det = NULL;
1328 
1329 	/* get info */
1330 	if (mfi_get_info(sc)) {
1331 		DNPRINTF(MFI_D_IOCTL, "%s: mfi_get_info failed\n",
1332 		    DEVNAME(sc));
1333 		goto done;
1334 	}
1335 
1336 	/* send single element command to retrieve size for full structure */
1337 	cfg = malloc(sizeof *cfg, M_DEVBUF, M_NOWAIT | M_ZERO);
1338 	if (cfg == NULL)
1339 		goto done;
1340 	if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg, NULL))
1341 		goto done;
1342 
1343 	size = cfg->mfc_size;
1344 	free(cfg, M_DEVBUF);
1345 
1346 	/* memory for read config */
1347 	cfg = malloc(size, M_DEVBUF, M_NOWAIT | M_ZERO);
1348 	if (cfg == NULL)
1349 		goto done;
1350 	if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, size, cfg, NULL))
1351 		goto done;
1352 
1353 	/* replace current pointer with enw one */
1354 	if (sc->sc_cfg)
1355 		free(sc->sc_cfg, M_DEVBUF);
1356 	sc->sc_cfg = cfg;
1357 
1358 	/* get all ld info */
1359 	if (mfi_mgmt(sc, MR_DCMD_LD_GET_LIST, MFI_DATA_IN,
1360 	    sizeof(sc->sc_ld_list), &sc->sc_ld_list, NULL))
1361 		goto done;
1362 
1363 	/* get memory for all ld structures */
1364 	size = cfg->mfc_no_ld * sizeof(struct mfi_ld_details);
1365 	if (sc->sc_ld_sz != size) {
1366 		if (sc->sc_ld_details)
1367 			free(sc->sc_ld_details, M_DEVBUF);
1368 
1369 		ld_det = malloc( size, M_DEVBUF, M_NOWAIT | M_ZERO);
1370 		if (ld_det == NULL)
1371 			goto done;
1372 		sc->sc_ld_sz = size;
1373 		sc->sc_ld_details = ld_det;
1374 	}
1375 
1376 	/* find used physical disks */
1377 	size = sizeof(struct mfi_ld_details);
1378 	for (i = 0, d = 0; i < cfg->mfc_no_ld; i++) {
1379 		mbox[0] = sc->sc_ld_list.mll_list[i].mll_ld.mld_target;
1380 		if (mfi_mgmt(sc, MR_DCMD_LD_GET_INFO, MFI_DATA_IN, size,
1381 		    &sc->sc_ld_details[i], mbox))
1382 			goto done;
1383 
1384 		d += sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
1385 		    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
1386 	}
1387 	sc->sc_no_pd = d;
1388 
1389 	rv = 0;
1390 done:
1391 	return (rv);
1392 }
1393 
1394 int
1395 mfi_ioctl_inq(struct mfi_softc *sc, struct bioc_inq *bi)
1396 {
1397 	int			rv = EINVAL;
1398 	struct mfi_conf		*cfg = NULL;
1399 
1400 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_inq\n", DEVNAME(sc));
1401 
1402 	if (mfi_bio_getitall(sc)) {
1403 		DNPRINTF(MFI_D_IOCTL, "%s: mfi_bio_getitall failed\n",
1404 		    DEVNAME(sc));
1405 		goto done;
1406 	}
1407 
1408 	/* count unused disks as volumes */
1409 	if (sc->sc_cfg == NULL)
1410 		goto done;
1411 	cfg = sc->sc_cfg;
1412 
1413 	bi->bi_nodisk = sc->sc_info.mci_pd_disks_present;
1414 	bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs;
1415 #if notyet
1416 	bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs +
1417 	    (bi->bi_nodisk - sc->sc_no_pd);
1418 #endif
1419 	/* tell bio who we are */
1420 	strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev));
1421 
1422 	rv = 0;
1423 done:
1424 	return (rv);
1425 }
1426 
1427 int
1428 mfi_ioctl_vol(struct mfi_softc *sc, struct bioc_vol *bv)
1429 {
1430 	int			i, per, rv = EINVAL;
1431 
1432 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol %#x\n",
1433 	    DEVNAME(sc), bv->bv_volid);
1434 
1435 	/* we really could skip and expect that inq took care of it */
1436 	if (mfi_bio_getitall(sc)) {
1437 		DNPRINTF(MFI_D_IOCTL, "%s: mfi_bio_getitall failed\n",
1438 		    DEVNAME(sc));
1439 		goto done;
1440 	}
1441 
1442 	if (bv->bv_volid >= sc->sc_ld_list.mll_no_ld) {
1443 		/* go do hotspares & unused disks */
1444 		rv = mfi_bio_hs(sc, bv->bv_volid, MFI_MGMT_VD, bv);
1445 		goto done;
1446 	}
1447 
1448 	i = bv->bv_volid;
1449 	strlcpy(bv->bv_dev, sc->sc_ld[i].ld_dev, sizeof(bv->bv_dev));
1450 
1451 	switch(sc->sc_ld_list.mll_list[i].mll_state) {
1452 	case MFI_LD_OFFLINE:
1453 		bv->bv_status = BIOC_SVOFFLINE;
1454 		break;
1455 
1456 	case MFI_LD_PART_DEGRADED:
1457 	case MFI_LD_DEGRADED:
1458 		bv->bv_status = BIOC_SVDEGRADED;
1459 		break;
1460 
1461 	case MFI_LD_ONLINE:
1462 		bv->bv_status = BIOC_SVONLINE;
1463 		break;
1464 
1465 	default:
1466 		bv->bv_status = BIOC_SVINVALID;
1467 		DNPRINTF(MFI_D_IOCTL, "%s: invalid logical disk state %#x\n",
1468 		    DEVNAME(sc),
1469 		    sc->sc_ld_list.mll_list[i].mll_state);
1470 	}
1471 
1472 	/* additional status can modify MFI status */
1473 	switch (sc->sc_ld_details[i].mld_progress.mlp_in_prog) {
1474 	case MFI_LD_PROG_CC:
1475 	case MFI_LD_PROG_BGI:
1476 		bv->bv_status = BIOC_SVSCRUB;
1477 		per = (int)sc->sc_ld_details[i].mld_progress.mlp_cc.mp_progress;
1478 		bv->bv_percent = (per * 100) / 0xffff;
1479 		bv->bv_seconds =
1480 		    sc->sc_ld_details[i].mld_progress.mlp_cc.mp_elapsed_seconds;
1481 		break;
1482 
1483 	case MFI_LD_PROG_FGI:
1484 	case MFI_LD_PROG_RECONSTRUCT:
1485 		/* nothing yet */
1486 		break;
1487 	}
1488 
1489 	/*
1490 	 * The RAID levels are determined per the SNIA DDF spec, this is only
1491 	 * a subset that is valid for the MFI controller.
1492 	 */
1493 	bv->bv_level = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_pri_raid;
1494 	if (sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_sec_raid ==
1495 	    MFI_DDF_SRL_SPANNED)
1496 		bv->bv_level *= 10;
1497 
1498 	bv->bv_nodisk = sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_no_drv_per_span *
1499 	    sc->sc_ld_details[i].mld_cfg.mlc_parm.mpa_span_depth;
1500 
1501 	bv->bv_size = sc->sc_ld_details[i].mld_size * 512; /* bytes per block */
1502 
1503 	rv = 0;
1504 done:
1505 	return (rv);
1506 }
1507 
1508 int
1509 mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd)
1510 {
1511 	struct mfi_conf		*cfg;
1512 	struct mfi_array	*ar;
1513 	struct mfi_ld_cfg	*ld;
1514 	struct mfi_pd_details	*pd;
1515 	struct scsi_inquiry_data *inqbuf;
1516 	char			vend[8+16+4+1];
1517 	int			rv = EINVAL;
1518 	int			arr, vol, disk, span;
1519 	uint8_t			mbox[MFI_MBOX_SIZE];
1520 
1521 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_disk %#x\n",
1522 	    DEVNAME(sc), bd->bd_diskid);
1523 
1524 	/* we really could skip and expect that inq took care of it */
1525 	if (mfi_bio_getitall(sc)) {
1526 		DNPRINTF(MFI_D_IOCTL, "%s: mfi_bio_getitall failed\n",
1527 		    DEVNAME(sc));
1528 		return (rv);
1529 	}
1530 	cfg = sc->sc_cfg;
1531 
1532 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
1533 
1534 	ar = cfg->mfc_array;
1535 	vol = bd->bd_volid;
1536 	if (vol >= cfg->mfc_no_ld) {
1537 		/* do hotspares */
1538 		rv = mfi_bio_hs(sc, bd->bd_volid, MFI_MGMT_SD, bd);
1539 		goto freeme;
1540 	}
1541 
1542 	/* calculate offset to ld structure */
1543 	ld = (struct mfi_ld_cfg *)(
1544 	    ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
1545 	    cfg->mfc_array_size * cfg->mfc_no_array);
1546 
1547 	/* use span 0 only when raid group is not spanned */
1548 	if (ld[vol].mlc_parm.mpa_span_depth > 1)
1549 		span = bd->bd_diskid / ld[vol].mlc_parm.mpa_no_drv_per_span;
1550 	else
1551 		span = 0;
1552 	arr = ld[vol].mlc_span[span].mls_index;
1553 
1554 	/* offset disk into pd list */
1555 	disk = bd->bd_diskid % ld[vol].mlc_parm.mpa_no_drv_per_span;
1556 	bd->bd_target = ar[arr].pd[disk].mar_enc_slot;
1557 
1558 	/* get status */
1559 	switch (ar[arr].pd[disk].mar_pd_state){
1560 	case MFI_PD_UNCONFIG_GOOD:
1561 	case MFI_PD_FAILED:
1562 		bd->bd_status = BIOC_SDFAILED;
1563 		break;
1564 
1565 	case MFI_PD_HOTSPARE: /* XXX dedicated hotspare part of array? */
1566 		bd->bd_status = BIOC_SDHOTSPARE;
1567 		break;
1568 
1569 	case MFI_PD_OFFLINE:
1570 		bd->bd_status = BIOC_SDOFFLINE;
1571 		break;
1572 
1573 	case MFI_PD_REBUILD:
1574 		bd->bd_status = BIOC_SDREBUILD;
1575 		break;
1576 
1577 	case MFI_PD_ONLINE:
1578 		bd->bd_status = BIOC_SDONLINE;
1579 		break;
1580 
1581 	case MFI_PD_UNCONFIG_BAD: /* XXX define new state in bio */
1582 	default:
1583 		bd->bd_status = BIOC_SDINVALID;
1584 		break;
1585 	}
1586 
1587 	/* get the remaining fields */
1588 	*((uint16_t *)&mbox) = ar[arr].pd[disk].mar_pd.mfp_id;
1589 	if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
1590 	    sizeof *pd, pd, mbox)) {
1591 		/* disk is missing but succeed command */
1592 		rv = 0;
1593 		goto freeme;
1594 	}
1595 
1596 	bd->bd_size = pd->mpd_size * 512; /* bytes per block */
1597 
1598 	/* if pd->mpd_enc_idx is 0 then it is not in an enclosure */
1599 	bd->bd_channel = pd->mpd_enc_idx;
1600 
1601 	inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
1602 	memcpy(vend, inqbuf->vendor, sizeof vend - 1);
1603 	vend[sizeof vend - 1] = '\0';
1604 	strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor));
1605 
1606 	/* XXX find a way to retrieve serial nr from drive */
1607 	/* XXX find a way to get bd_procdev */
1608 
1609 	rv = 0;
1610 freeme:
1611 	free(pd, M_DEVBUF);
1612 
1613 	return (rv);
1614 }
1615 
1616 int
1617 mfi_ioctl_alarm(struct mfi_softc *sc, struct bioc_alarm *ba)
1618 {
1619 	uint32_t		opc, dir = MFI_DATA_NONE;
1620 	int			rv = 0;
1621 	int8_t			ret;
1622 
1623 	switch(ba->ba_opcode) {
1624 	case BIOC_SADISABLE:
1625 		opc = MR_DCMD_SPEAKER_DISABLE;
1626 		break;
1627 
1628 	case BIOC_SAENABLE:
1629 		opc = MR_DCMD_SPEAKER_ENABLE;
1630 		break;
1631 
1632 	case BIOC_SASILENCE:
1633 		opc = MR_DCMD_SPEAKER_SILENCE;
1634 		break;
1635 
1636 	case BIOC_GASTATUS:
1637 		opc = MR_DCMD_SPEAKER_GET;
1638 		dir = MFI_DATA_IN;
1639 		break;
1640 
1641 	case BIOC_SATEST:
1642 		opc = MR_DCMD_SPEAKER_TEST;
1643 		break;
1644 
1645 	default:
1646 		DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_alarm biocalarm invalid "
1647 		    "opcode %x\n", DEVNAME(sc), ba->ba_opcode);
1648 		return (EINVAL);
1649 	}
1650 
1651 	if (mfi_mgmt(sc, opc, dir, sizeof(ret), &ret, NULL))
1652 		rv = EINVAL;
1653 	else
1654 		if (ba->ba_opcode == BIOC_GASTATUS)
1655 			ba->ba_status = ret;
1656 		else
1657 			ba->ba_status = 0;
1658 
1659 	return (rv);
1660 }
1661 
1662 int
1663 mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *bb)
1664 {
1665 	int			i, found, rv = EINVAL;
1666 	uint8_t			mbox[MFI_MBOX_SIZE];
1667 	uint32_t		cmd;
1668 	struct mfi_pd_list	*pd;
1669 
1670 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink %x\n", DEVNAME(sc),
1671 	    bb->bb_status);
1672 
1673 	/* channel 0 means not in an enclosure so can't be blinked */
1674 	if (bb->bb_channel == 0)
1675 		return (EINVAL);
1676 
1677 	pd = malloc(MFI_PD_LIST_SIZE, M_DEVBUF, M_WAITOK);
1678 
1679 	if (mfi_mgmt(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
1680 	    MFI_PD_LIST_SIZE, pd, NULL))
1681 		goto done;
1682 
1683 	for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
1684 		if (bb->bb_channel == pd->mpl_address[i].mpa_enc_index &&
1685 		    bb->bb_target == pd->mpl_address[i].mpa_enc_slot) {
1686 		    	found = 1;
1687 			break;
1688 		}
1689 
1690 	if (!found)
1691 		goto done;
1692 
1693 	memset(mbox, 0, sizeof mbox);
1694 
1695 	*((uint16_t *)&mbox) = pd->mpl_address[i].mpa_pd_id;
1696 
1697 	switch (bb->bb_status) {
1698 	case BIOC_SBUNBLINK:
1699 		cmd = MR_DCMD_PD_UNBLINK;
1700 		break;
1701 
1702 	case BIOC_SBBLINK:
1703 		cmd = MR_DCMD_PD_BLINK;
1704 		break;
1705 
1706 	case BIOC_SBALARM:
1707 	default:
1708 		DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink biocblink invalid "
1709 		    "opcode %x\n", DEVNAME(sc), bb->bb_status);
1710 		goto done;
1711 	}
1712 
1713 
1714 	if (mfi_mgmt(sc, cmd, MFI_DATA_NONE, 0, NULL, mbox))
1715 		goto done;
1716 
1717 	rv = 0;
1718 done:
1719 	free(pd, M_DEVBUF);
1720 	return (rv);
1721 }
1722 
1723 int
1724 mfi_ioctl_setstate(struct mfi_softc *sc, struct bioc_setstate *bs)
1725 {
1726 	struct mfi_pd_list	*pd;
1727 	int			i, found, rv = EINVAL;
1728 	uint8_t			mbox[MFI_MBOX_SIZE];
1729 	uint32_t		cmd;
1730 
1731 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate %x\n", DEVNAME(sc),
1732 	    bs->bs_status);
1733 
1734 	pd = malloc(MFI_PD_LIST_SIZE, M_DEVBUF, M_WAITOK);
1735 
1736 	if (mfi_mgmt(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN,
1737 	    MFI_PD_LIST_SIZE, pd, NULL))
1738 		goto done;
1739 
1740 	for (i = 0, found = 0; i < pd->mpl_no_pd; i++)
1741 		if (bs->bs_channel == pd->mpl_address[i].mpa_enc_index &&
1742 		    bs->bs_target == pd->mpl_address[i].mpa_enc_slot) {
1743 		    	found = 1;
1744 			break;
1745 		}
1746 
1747 	if (!found)
1748 		goto done;
1749 
1750 	memset(mbox, 0, sizeof mbox);
1751 
1752 	*((uint16_t *)&mbox) = pd->mpl_address[i].mpa_pd_id;
1753 
1754 	switch (bs->bs_status) {
1755 	case BIOC_SSONLINE:
1756 		mbox[2] = MFI_PD_ONLINE;
1757 		cmd = MD_DCMD_PD_SET_STATE;
1758 		break;
1759 
1760 	case BIOC_SSOFFLINE:
1761 		mbox[2] = MFI_PD_OFFLINE;
1762 		cmd = MD_DCMD_PD_SET_STATE;
1763 		break;
1764 
1765 	case BIOC_SSHOTSPARE:
1766 		mbox[2] = MFI_PD_HOTSPARE;
1767 		cmd = MD_DCMD_PD_SET_STATE;
1768 		break;
1769 /*
1770 	case BIOC_SSREBUILD:
1771 		cmd = MD_DCMD_PD_REBUILD;
1772 		break;
1773 */
1774 	default:
1775 		DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate invalid "
1776 		    "opcode %x\n", DEVNAME(sc), bs->bs_status);
1777 		goto done;
1778 	}
1779 
1780 
1781 	if (mfi_mgmt(sc, MD_DCMD_PD_SET_STATE, MFI_DATA_NONE, 0, NULL, mbox))
1782 		goto done;
1783 
1784 	rv = 0;
1785 done:
1786 	free(pd, M_DEVBUF);
1787 	return (rv);
1788 }
1789 
1790 int
1791 mfi_bio_hs(struct mfi_softc *sc, int volid, int type, void *bio_hs)
1792 {
1793 	struct mfi_conf		*cfg;
1794 	struct mfi_hotspare	*hs;
1795 	struct mfi_pd_details	*pd;
1796 	struct bioc_disk	*sdhs;
1797 	struct bioc_vol		*vdhs;
1798 	struct scsi_inquiry_data *inqbuf;
1799 	char			vend[8+16+4+1];
1800 	int			i, rv = EINVAL;
1801 	uint32_t		size;
1802 	uint8_t			mbox[MFI_MBOX_SIZE];
1803 
1804 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs %d\n", DEVNAME(sc), volid);
1805 
1806 	if (!bio_hs)
1807 		return (EINVAL);
1808 
1809 	pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK);
1810 
1811 	/* send single element command to retrieve size for full structure */
1812 	cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK);
1813 	if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, sizeof *cfg, cfg, NULL))
1814 		goto freeme;
1815 
1816 	size = cfg->mfc_size;
1817 	free(cfg, M_DEVBUF);
1818 
1819 	/* memory for read config */
1820 	cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO);
1821 	if (mfi_mgmt(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, size, cfg, NULL))
1822 		goto freeme;
1823 
1824 	/* calculate offset to hs structure */
1825 	hs = (struct mfi_hotspare *)(
1826 	    ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) +
1827 	    cfg->mfc_array_size * cfg->mfc_no_array +
1828 	    cfg->mfc_ld_size * cfg->mfc_no_ld);
1829 
1830 	if (volid < cfg->mfc_no_ld)
1831 		goto freeme; /* not a hotspare */
1832 
1833 	if (volid > (cfg->mfc_no_ld + cfg->mfc_no_hs))
1834 		goto freeme; /* not a hotspare */
1835 
1836 	/* offset into hotspare structure */
1837 	i = volid - cfg->mfc_no_ld;
1838 
1839 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs i %d volid %d no_ld %d no_hs %d "
1840 	    "hs %p cfg %p id %02x\n", DEVNAME(sc), i, volid, cfg->mfc_no_ld,
1841 	    cfg->mfc_no_hs, hs, cfg, hs[i].mhs_pd.mfp_id);
1842 
1843 	/* get pd fields */
1844 	memset(mbox, 0, sizeof mbox);
1845 	*((uint16_t *)&mbox) = hs[i].mhs_pd.mfp_id;
1846 	if (mfi_mgmt(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN,
1847 	    sizeof *pd, pd, mbox)) {
1848 		DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs illegal PD\n",
1849 		    DEVNAME(sc));
1850 		goto freeme;
1851 	}
1852 
1853 	switch (type) {
1854 	case MFI_MGMT_VD:
1855 		vdhs = bio_hs;
1856 		vdhs->bv_status = BIOC_SVONLINE;
1857 		vdhs->bv_size = pd->mpd_size / 2 * 1024; /* XXX why? */
1858 		vdhs->bv_level = -1; /* hotspare */
1859 		vdhs->bv_nodisk = 1;
1860 		break;
1861 
1862 	case MFI_MGMT_SD:
1863 		sdhs = bio_hs;
1864 		sdhs->bd_status = BIOC_SDHOTSPARE;
1865 		sdhs->bd_size = pd->mpd_size / 2 * 1024; /* XXX why? */
1866 		sdhs->bd_channel = pd->mpd_enc_idx;
1867 		sdhs->bd_target = pd->mpd_enc_slot;
1868 		inqbuf = (struct scsi_inquiry_data *)&pd->mpd_inq_data;
1869 		memcpy(vend, inqbuf->vendor, sizeof vend - 1);
1870 		vend[sizeof vend - 1] = '\0';
1871 		strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor));
1872 		break;
1873 
1874 	default:
1875 		goto freeme;
1876 	}
1877 
1878 	DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs 6\n", DEVNAME(sc));
1879 	rv = 0;
1880 freeme:
1881 	free(pd, M_DEVBUF);
1882 	free(cfg, M_DEVBUF);
1883 
1884 	return (rv);
1885 }
1886 
1887 #ifndef SMALL_KERNEL
1888 int
1889 mfi_create_sensors(struct mfi_softc *sc)
1890 {
1891 	struct device		*dev;
1892 	struct scsibus_softc	*ssc = NULL;
1893 	int			i;
1894 
1895 	TAILQ_FOREACH(dev, &alldevs, dv_list) {
1896 		if (dev->dv_parent != &sc->sc_dev)
1897 			continue;
1898 
1899 		/* check if this is the scsibus for the logical disks */
1900 		ssc = (struct scsibus_softc *)dev;
1901 		if (ssc->adapter_link == &sc->sc_link)
1902 			break;
1903 	}
1904 
1905 	if (ssc == NULL)
1906 		return (1);
1907 
1908 	sc->sc_sensors = malloc(sizeof(struct ksensor) * sc->sc_ld_cnt,
1909 	    M_DEVBUF, M_WAITOK|M_ZERO);
1910 	if (sc->sc_sensors == NULL)
1911 		return (1);
1912 
1913 	strlcpy(sc->sc_sensordev.xname, DEVNAME(sc),
1914 	    sizeof(sc->sc_sensordev.xname));
1915 
1916 	for (i = 0; i < sc->sc_ld_cnt; i++) {
1917 		if (ssc->sc_link[i][0] == NULL)
1918 			goto bad;
1919 
1920 		dev = ssc->sc_link[i][0]->device_softc;
1921 
1922 		sc->sc_sensors[i].type = SENSOR_DRIVE;
1923 		sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
1924 
1925 		strlcpy(sc->sc_sensors[i].desc, dev->dv_xname,
1926 		    sizeof(sc->sc_sensors[i].desc));
1927 
1928 		sensor_attach(&sc->sc_sensordev, &sc->sc_sensors[i]);
1929 	}
1930 
1931 	if (sensor_task_register(sc, mfi_refresh_sensors, 10) == NULL)
1932 		goto bad;
1933 
1934 	sensordev_install(&sc->sc_sensordev);
1935 
1936 	return (0);
1937 
1938 bad:
1939 	free(sc->sc_sensors, M_DEVBUF);
1940 
1941 	return (1);
1942 }
1943 
1944 void
1945 mfi_refresh_sensors(void *arg)
1946 {
1947 	struct mfi_softc	*sc = arg;
1948 	int			i;
1949 	struct bioc_vol		bv;
1950 
1951 
1952 	for (i = 0; i < sc->sc_ld_cnt; i++) {
1953 		bzero(&bv, sizeof(bv));
1954 		bv.bv_volid = i;
1955 		if (mfi_ioctl_vol(sc, &bv))
1956 			return;
1957 
1958 		switch(bv.bv_status) {
1959 		case BIOC_SVOFFLINE:
1960 			sc->sc_sensors[i].value = SENSOR_DRIVE_FAIL;
1961 			sc->sc_sensors[i].status = SENSOR_S_CRIT;
1962 			break;
1963 
1964 		case BIOC_SVDEGRADED:
1965 			sc->sc_sensors[i].value = SENSOR_DRIVE_PFAIL;
1966 			sc->sc_sensors[i].status = SENSOR_S_WARN;
1967 			break;
1968 
1969 		case BIOC_SVSCRUB:
1970 		case BIOC_SVONLINE:
1971 			sc->sc_sensors[i].value = SENSOR_DRIVE_ONLINE;
1972 			sc->sc_sensors[i].status = SENSOR_S_OK;
1973 			break;
1974 
1975 		case BIOC_SVINVALID:
1976 			/* FALLTRHOUGH */
1977 		default:
1978 			sc->sc_sensors[i].value = 0; /* unknown */
1979 			sc->sc_sensors[i].status = SENSOR_S_UNKNOWN;
1980 		}
1981 
1982 	}
1983 }
1984 #endif /* SMALL_KERNEL */
1985 #endif /* NBIO > 0 */
1986 
1987 u_int32_t
1988 mfi_xscale_fw_state(struct mfi_softc *sc)
1989 {
1990 	return (mfi_read(sc, MFI_OMSG0));
1991 }
1992 
1993 void
1994 mfi_xscale_intr_ena(struct mfi_softc *sc)
1995 {
1996 	mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR);
1997 }
1998 
1999 int
2000 mfi_xscale_intr(struct mfi_softc *sc)
2001 {
2002 	u_int32_t status;
2003 
2004 	status = mfi_read(sc, MFI_OSTS);
2005 	if (!ISSET(status, MFI_OSTS_INTR_VALID))
2006 		return (0);
2007 
2008 	/* write status back to acknowledge interrupt */
2009 	mfi_write(sc, MFI_OSTS, status);
2010 
2011 	return (1);
2012 }
2013 
2014 void
2015 mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
2016 {
2017 	mfi_write(sc, MFI_IQP, (ccb->ccb_pframe >> 3) |
2018 	    ccb->ccb_extra_frames);
2019 }
2020 
2021 u_int32_t
2022 mfi_ppc_fw_state(struct mfi_softc *sc)
2023 {
2024 	return (mfi_read(sc, MFI_OSP));
2025 }
2026 
2027 void
2028 mfi_ppc_intr_ena(struct mfi_softc *sc)
2029 {
2030 	mfi_write(sc, MFI_ODC, 0xffffffff);
2031 	mfi_write(sc, MFI_OMSK, ~0x80000004);
2032 }
2033 
2034 int
2035 mfi_ppc_intr(struct mfi_softc *sc)
2036 {
2037 	u_int32_t status;
2038 
2039 	status = mfi_read(sc, MFI_OSTS);
2040 	if (!ISSET(status, MFI_OSTS_PPC_INTR_VALID))
2041 		return (0);
2042 
2043 	/* write status back to acknowledge interrupt */
2044 	mfi_write(sc, MFI_ODC, status);
2045 
2046 	return (1);
2047 }
2048 
2049 void
2050 mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
2051 {
2052 	mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe |
2053 	    (ccb->ccb_extra_frames << 1));
2054 }
2055 
2056 u_int32_t
2057 mfi_gen2_fw_state(struct mfi_softc *sc)
2058 {
2059 	return (mfi_read(sc, MFI_OSP));
2060 }
2061 
2062 void
2063 mfi_gen2_intr_ena(struct mfi_softc *sc)
2064 {
2065 	mfi_write(sc, MFI_ODC, 0xffffffff);
2066 	mfi_write(sc, MFI_OMSK, ~MFI_OSTS_GEN2_INTR_VALID);
2067 }
2068 
2069 int
2070 mfi_gen2_intr(struct mfi_softc *sc)
2071 {
2072 	u_int32_t status;
2073 
2074 	status = mfi_read(sc, MFI_OSTS);
2075 	if (!ISSET(status, MFI_OSTS_GEN2_INTR_VALID))
2076 		return (0);
2077 
2078 	/* write status back to acknowledge interrupt */
2079 	mfi_write(sc, MFI_ODC, status);
2080 
2081 	return (1);
2082 }
2083 
2084 void
2085 mfi_gen2_post(struct mfi_softc *sc, struct mfi_ccb *ccb)
2086 {
2087 	mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe |
2088 	    (ccb->ccb_extra_frames << 1));
2089 }
2090