1 /* $NetBSD: mfi.c,v 1.29 2009/08/27 09:40:39 bouyer Exp $ */
2 /* $OpenBSD: mfi.c,v 1.66 2006/11/28 23:59:45 dlg Exp $ */
4 * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/cdefs.h>
20 __KERNEL_RCSID(0, "$NetBSD: mfi.c,v 1.29 2009/08/27 09:40:39 bouyer Exp $");
24 #include <sys/param.h>
25 #include <sys/systm.h>
27 #include <sys/ioctl.h>
28 #include <sys/device.h>
29 #include <sys/kernel.h>
30 #include <sys/malloc.h>
33 #include <uvm/uvm_param.h>
37 #include <dev/scsipi/scsipi_all.h>
38 #include <dev/scsipi/scsi_all.h>
39 #include <dev/scsipi/scsi_spc.h>
40 #include <dev/scsipi/scsipi_disk.h>
41 #include <dev/scsipi/scsi_disk.h>
42 #include <dev/scsipi/scsiconf.h>
44 #include <dev/ic/mfireg.h>
45 #include <dev/ic/mfivar.h>
48 #include <dev/biovar.h>
52 uint32_t mfi_debug
= 0
64 static void mfi_scsipi_request(struct scsipi_channel
*,
65 scsipi_adapter_req_t
, void *);
66 static void mfiminphys(struct buf
*bp
);
68 static struct mfi_ccb
*mfi_get_ccb(struct mfi_softc
*);
69 static void mfi_put_ccb(struct mfi_ccb
*);
70 static int mfi_init_ccb(struct mfi_softc
*);
72 static struct mfi_mem
*mfi_allocmem(struct mfi_softc
*, size_t);
73 static void mfi_freemem(struct mfi_softc
*, struct mfi_mem
**);
75 static int mfi_transition_firmware(struct mfi_softc
*);
76 static int mfi_initialize_firmware(struct mfi_softc
*);
77 static int mfi_get_info(struct mfi_softc
*);
78 static uint32_t mfi_read(struct mfi_softc
*, bus_size_t
);
79 static void mfi_write(struct mfi_softc
*, bus_size_t
, uint32_t);
80 static int mfi_poll(struct mfi_ccb
*);
81 static int mfi_create_sgl(struct mfi_ccb
*, int);
84 static int mfi_scsi_ld(struct mfi_ccb
*, struct scsipi_xfer
*);
85 static int mfi_scsi_io(struct mfi_ccb
*, struct scsipi_xfer
*,
87 static void mfi_scsi_xs_done(struct mfi_ccb
*);
88 static int mfi_mgmt_internal(struct mfi_softc
*,
89 uint32_t, uint32_t, uint32_t, void *, uint8_t *);
90 static int mfi_mgmt(struct mfi_ccb
*,struct scsipi_xfer
*,
91 uint32_t, uint32_t, uint32_t, void *, uint8_t *);
92 static void mfi_mgmt_done(struct mfi_ccb
*);
95 static int mfi_ioctl(device_t
, u_long
, void *);
96 static int mfi_ioctl_inq(struct mfi_softc
*, struct bioc_inq
*);
97 static int mfi_ioctl_vol(struct mfi_softc
*, struct bioc_vol
*);
98 static int mfi_ioctl_disk(struct mfi_softc
*, struct bioc_disk
*);
99 static int mfi_ioctl_alarm(struct mfi_softc
*,
100 struct bioc_alarm
*);
101 static int mfi_ioctl_blink(struct mfi_softc
*sc
,
102 struct bioc_blink
*);
103 static int mfi_ioctl_setstate(struct mfi_softc
*,
104 struct bioc_setstate
*);
105 static int mfi_bio_hs(struct mfi_softc
*, int, int, void *);
106 static int mfi_create_sensors(struct mfi_softc
*);
107 static int mfi_destroy_sensors(struct mfi_softc
*);
108 static void mfi_sensor_refresh(struct sysmon_envsys
*,
110 #endif /* NBIO > 0 */
112 static uint32_t mfi_xscale_fw_state(struct mfi_softc
*sc
);
113 static void mfi_xscale_intr_ena(struct mfi_softc
*sc
);
114 static void mfi_xscale_intr_dis(struct mfi_softc
*sc
);
115 static int mfi_xscale_intr(struct mfi_softc
*sc
);
116 static void mfi_xscale_post(struct mfi_softc
*sc
, struct mfi_ccb
*ccb
);
118 static const struct mfi_iop_ops mfi_iop_xscale
= {
126 static uint32_t mfi_ppc_fw_state(struct mfi_softc
*sc
);
127 static void mfi_ppc_intr_ena(struct mfi_softc
*sc
);
128 static void mfi_ppc_intr_dis(struct mfi_softc
*sc
);
129 static int mfi_ppc_intr(struct mfi_softc
*sc
);
130 static void mfi_ppc_post(struct mfi_softc
*sc
, struct mfi_ccb
*ccb
);
132 static const struct mfi_iop_ops mfi_iop_ppc
= {
140 #define mfi_fw_state(_s) ((_s)->sc_iop->mio_fw_state(_s))
141 #define mfi_intr_enable(_s) ((_s)->sc_iop->mio_intr_ena(_s))
142 #define mfi_intr_disable(_s) ((_s)->sc_iop->mio_intr_dis(_s))
143 #define mfi_my_intr(_s) ((_s)->sc_iop->mio_intr(_s))
144 #define mfi_post(_s, _c) ((_s)->sc_iop->mio_post((_s), (_c)))
146 static struct mfi_ccb
*
147 mfi_get_ccb(struct mfi_softc
*sc
)
153 ccb
= TAILQ_FIRST(&sc
->sc_ccb_freeq
);
155 TAILQ_REMOVE(&sc
->sc_ccb_freeq
, ccb
, ccb_link
);
156 ccb
->ccb_state
= MFI_CCB_READY
;
160 DNPRINTF(MFI_D_CCB
, "%s: mfi_get_ccb: %p\n", DEVNAME(sc
), ccb
);
166 mfi_put_ccb(struct mfi_ccb
*ccb
)
168 struct mfi_softc
*sc
= ccb
->ccb_sc
;
171 DNPRINTF(MFI_D_CCB
, "%s: mfi_put_ccb: %p\n", DEVNAME(sc
), ccb
);
174 ccb
->ccb_state
= MFI_CCB_FREE
;
177 ccb
->ccb_done
= NULL
;
178 ccb
->ccb_direction
= 0;
179 ccb
->ccb_frame_size
= 0;
180 ccb
->ccb_extra_frames
= 0;
182 ccb
->ccb_data
= NULL
;
184 TAILQ_INSERT_TAIL(&sc
->sc_ccb_freeq
, ccb
, ccb_link
);
189 mfi_destroy_ccb(struct mfi_softc
*sc
)
194 DNPRINTF(MFI_D_CCB
, "%s: mfi_init_ccb\n", DEVNAME(sc
));
197 for (i
= 0; (ccb
= mfi_get_ccb(sc
)) != NULL
; i
++) {
198 /* create a dma map for transfer */
199 bus_dmamap_destroy(sc
->sc_dmat
, ccb
->ccb_dmamap
);
202 if (i
< sc
->sc_max_cmds
)
205 free(sc
->sc_ccb
, M_DEVBUF
);
211 mfi_init_ccb(struct mfi_softc
*sc
)
217 DNPRINTF(MFI_D_CCB
, "%s: mfi_init_ccb\n", DEVNAME(sc
));
219 sc
->sc_ccb
= malloc(sizeof(struct mfi_ccb
) * sc
->sc_max_cmds
,
220 M_DEVBUF
, M_WAITOK
|M_ZERO
);
222 for (i
= 0; i
< sc
->sc_max_cmds
; i
++) {
223 ccb
= &sc
->sc_ccb
[i
];
227 /* select i'th frame */
228 ccb
->ccb_frame
= (union mfi_frame
*)
229 ((char*)MFIMEM_KVA(sc
->sc_frames
) + sc
->sc_frames_size
* i
);
231 MFIMEM_DVA(sc
->sc_frames
) + sc
->sc_frames_size
* i
;
232 ccb
->ccb_frame
->mfr_header
.mfh_context
= i
;
234 /* select i'th sense */
235 ccb
->ccb_sense
= (struct mfi_sense
*)
236 ((char*)MFIMEM_KVA(sc
->sc_sense
) + MFI_SENSE_SIZE
* i
);
238 (MFIMEM_DVA(sc
->sc_sense
) + MFI_SENSE_SIZE
* i
);
240 /* create a dma map for transfer */
241 error
= bus_dmamap_create(sc
->sc_dmat
,
242 MAXPHYS
, sc
->sc_max_sgl
, MAXPHYS
, 0,
243 BUS_DMA_NOWAIT
| BUS_DMA_ALLOCNOW
, &ccb
->ccb_dmamap
);
245 printf("%s: cannot create ccb dmamap (%d)\n",
251 "ccb(%d): %p frame: %#lx (%#lx) sense: %#lx (%#lx) map: %#lx\n",
252 ccb
->ccb_frame
->mfr_header
.mfh_context
, ccb
,
253 (u_long
)ccb
->ccb_frame
, (u_long
)ccb
->ccb_pframe
,
254 (u_long
)ccb
->ccb_sense
, (u_long
)ccb
->ccb_psense
,
255 (u_long
)ccb
->ccb_dmamap
);
257 /* add ccb to queue */
263 /* free dma maps and ccb memory */
266 ccb
= &sc
->sc_ccb
[i
];
267 bus_dmamap_destroy(sc
->sc_dmat
, ccb
->ccb_dmamap
);
270 free(sc
->sc_ccb
, M_DEVBUF
);
276 mfi_read(struct mfi_softc
*sc
, bus_size_t r
)
280 bus_space_barrier(sc
->sc_iot
, sc
->sc_ioh
, r
, 4,
281 BUS_SPACE_BARRIER_READ
);
282 rv
= bus_space_read_4(sc
->sc_iot
, sc
->sc_ioh
, r
);
284 DNPRINTF(MFI_D_RW
, "%s: mr 0x%lx 0x08%x ", DEVNAME(sc
), (u_long
)r
, rv
);
289 mfi_write(struct mfi_softc
*sc
, bus_size_t r
, uint32_t v
)
291 DNPRINTF(MFI_D_RW
, "%s: mw 0x%lx 0x%08x", DEVNAME(sc
), (u_long
)r
, v
);
293 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, r
, v
);
294 bus_space_barrier(sc
->sc_iot
, sc
->sc_ioh
, r
, 4,
295 BUS_SPACE_BARRIER_WRITE
);
298 static struct mfi_mem
*
299 mfi_allocmem(struct mfi_softc
*sc
, size_t size
)
304 DNPRINTF(MFI_D_MEM
, "%s: mfi_allocmem: %ld\n", DEVNAME(sc
),
307 mm
= malloc(sizeof(struct mfi_mem
), M_DEVBUF
, M_NOWAIT
|M_ZERO
);
313 if (bus_dmamap_create(sc
->sc_dmat
, size
, 1, size
, 0,
314 BUS_DMA_NOWAIT
| BUS_DMA_ALLOCNOW
, &mm
->am_map
) != 0)
317 if (bus_dmamem_alloc(sc
->sc_dmat
, size
, PAGE_SIZE
, 0, &mm
->am_seg
, 1,
318 &nsegs
, BUS_DMA_NOWAIT
) != 0)
321 if (bus_dmamem_map(sc
->sc_dmat
, &mm
->am_seg
, nsegs
, size
, &mm
->am_kva
,
322 BUS_DMA_NOWAIT
) != 0)
325 if (bus_dmamap_load(sc
->sc_dmat
, mm
->am_map
, mm
->am_kva
, size
, NULL
,
326 BUS_DMA_NOWAIT
) != 0)
329 DNPRINTF(MFI_D_MEM
, " kva: %p dva: %p map: %p\n",
330 mm
->am_kva
, (void *)mm
->am_map
->dm_segs
[0].ds_addr
, mm
->am_map
);
332 memset(mm
->am_kva
, 0, size
);
336 bus_dmamem_unmap(sc
->sc_dmat
, mm
->am_kva
, size
);
338 bus_dmamem_free(sc
->sc_dmat
, &mm
->am_seg
, 1);
340 bus_dmamap_destroy(sc
->sc_dmat
, mm
->am_map
);
348 mfi_freemem(struct mfi_softc
*sc
, struct mfi_mem
**mmp
)
350 struct mfi_mem
*mm
= *mmp
;
357 DNPRINTF(MFI_D_MEM
, "%s: mfi_freemem: %p\n", DEVNAME(sc
), mm
);
359 bus_dmamap_unload(sc
->sc_dmat
, mm
->am_map
);
360 bus_dmamem_unmap(sc
->sc_dmat
, mm
->am_kva
, mm
->am_size
);
361 bus_dmamem_free(sc
->sc_dmat
, &mm
->am_seg
, 1);
362 bus_dmamap_destroy(sc
->sc_dmat
, mm
->am_map
);
367 mfi_transition_firmware(struct mfi_softc
*sc
)
369 uint32_t fw_state
, cur_state
;
372 fw_state
= mfi_fw_state(sc
) & MFI_STATE_MASK
;
374 DNPRINTF(MFI_D_CMD
, "%s: mfi_transition_firmware: %#x\n", DEVNAME(sc
),
377 while (fw_state
!= MFI_STATE_READY
) {
379 "%s: waiting for firmware to become ready\n",
381 cur_state
= fw_state
;
383 case MFI_STATE_FAULT
:
384 printf("%s: firmware fault\n", DEVNAME(sc
));
386 case MFI_STATE_WAIT_HANDSHAKE
:
387 mfi_write(sc
, MFI_IDB
, MFI_INIT_CLEAR_HANDSHAKE
);
390 case MFI_STATE_OPERATIONAL
:
391 mfi_write(sc
, MFI_IDB
, MFI_INIT_READY
);
394 case MFI_STATE_UNDEFINED
:
395 case MFI_STATE_BB_INIT
:
398 case MFI_STATE_FW_INIT
:
399 case MFI_STATE_DEVICE_SCAN
:
400 case MFI_STATE_FLUSH_CACHE
:
404 printf("%s: unknown firmware state %d\n",
405 DEVNAME(sc
), fw_state
);
408 for (i
= 0; i
< (max_wait
* 10); i
++) {
409 fw_state
= mfi_fw_state(sc
) & MFI_STATE_MASK
;
410 if (fw_state
== cur_state
)
415 if (fw_state
== cur_state
) {
416 printf("%s: firmware stuck in state %#x\n",
417 DEVNAME(sc
), fw_state
);
426 mfi_initialize_firmware(struct mfi_softc
*sc
)
429 struct mfi_init_frame
*init
;
430 struct mfi_init_qinfo
*qinfo
;
432 DNPRINTF(MFI_D_MISC
, "%s: mfi_initialize_firmware\n", DEVNAME(sc
));
434 if ((ccb
= mfi_get_ccb(sc
)) == NULL
)
437 init
= &ccb
->ccb_frame
->mfr_init
;
438 qinfo
= (struct mfi_init_qinfo
*)((uint8_t *)init
+ MFI_FRAME_SIZE
);
440 memset(qinfo
, 0, sizeof *qinfo
);
441 qinfo
->miq_rq_entries
= sc
->sc_max_cmds
+ 1;
442 qinfo
->miq_rq_addr_lo
= htole32(MFIMEM_DVA(sc
->sc_pcq
) +
443 offsetof(struct mfi_prod_cons
, mpc_reply_q
));
444 qinfo
->miq_pi_addr_lo
= htole32(MFIMEM_DVA(sc
->sc_pcq
) +
445 offsetof(struct mfi_prod_cons
, mpc_producer
));
446 qinfo
->miq_ci_addr_lo
= htole32(MFIMEM_DVA(sc
->sc_pcq
) +
447 offsetof(struct mfi_prod_cons
, mpc_consumer
));
449 init
->mif_header
.mfh_cmd
= MFI_CMD_INIT
;
450 init
->mif_header
.mfh_data_len
= sizeof *qinfo
;
451 init
->mif_qinfo_new_addr_lo
= htole32(ccb
->ccb_pframe
+ MFI_FRAME_SIZE
);
453 DNPRINTF(MFI_D_MISC
, "%s: entries: %#x rq: %#x pi: %#x ci: %#x\n",
455 qinfo
->miq_rq_entries
, qinfo
->miq_rq_addr_lo
,
456 qinfo
->miq_pi_addr_lo
, qinfo
->miq_ci_addr_lo
);
459 printf("%s: mfi_initialize_firmware failed\n", DEVNAME(sc
));
469 mfi_get_info(struct mfi_softc
*sc
)
474 DNPRINTF(MFI_D_MISC
, "%s: mfi_get_info\n", DEVNAME(sc
));
476 if (mfi_mgmt_internal(sc
, MR_DCMD_CTRL_GET_INFO
, MFI_DATA_IN
,
477 sizeof(sc
->sc_info
), &sc
->sc_info
, NULL
))
482 for (i
= 0; i
< sc
->sc_info
.mci_image_component_count
; i
++) {
483 printf("%s: active FW %s Version %s date %s time %s\n",
485 sc
->sc_info
.mci_image_component
[i
].mic_name
,
486 sc
->sc_info
.mci_image_component
[i
].mic_version
,
487 sc
->sc_info
.mci_image_component
[i
].mic_build_date
,
488 sc
->sc_info
.mci_image_component
[i
].mic_build_time
);
491 for (i
= 0; i
< sc
->sc_info
.mci_pending_image_component_count
; i
++) {
492 printf("%s: pending FW %s Version %s date %s time %s\n",
494 sc
->sc_info
.mci_pending_image_component
[i
].mic_name
,
495 sc
->sc_info
.mci_pending_image_component
[i
].mic_version
,
496 sc
->sc_info
.mci_pending_image_component
[i
].mic_build_date
,
497 sc
->sc_info
.mci_pending_image_component
[i
].mic_build_time
);
500 printf("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n",
502 sc
->sc_info
.mci_max_arms
,
503 sc
->sc_info
.mci_max_spans
,
504 sc
->sc_info
.mci_max_arrays
,
505 sc
->sc_info
.mci_max_lds
,
506 sc
->sc_info
.mci_product_name
);
508 printf("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n",
510 sc
->sc_info
.mci_serial_number
,
511 sc
->sc_info
.mci_hw_present
,
512 sc
->sc_info
.mci_current_fw_time
,
513 sc
->sc_info
.mci_max_cmds
,
514 sc
->sc_info
.mci_max_sg_elements
);
516 printf("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n",
518 sc
->sc_info
.mci_max_request_size
,
519 sc
->sc_info
.mci_lds_present
,
520 sc
->sc_info
.mci_lds_degraded
,
521 sc
->sc_info
.mci_lds_offline
,
522 sc
->sc_info
.mci_pd_present
);
524 printf("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n",
526 sc
->sc_info
.mci_pd_disks_present
,
527 sc
->sc_info
.mci_pd_disks_pred_failure
,
528 sc
->sc_info
.mci_pd_disks_failed
);
530 printf("%s: nvram %d mem %d flash %d\n",
532 sc
->sc_info
.mci_nvram_size
,
533 sc
->sc_info
.mci_memory_size
,
534 sc
->sc_info
.mci_flash_size
);
536 printf("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n",
538 sc
->sc_info
.mci_ram_correctable_errors
,
539 sc
->sc_info
.mci_ram_uncorrectable_errors
,
540 sc
->sc_info
.mci_cluster_allowed
,
541 sc
->sc_info
.mci_cluster_active
);
543 printf("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n",
545 sc
->sc_info
.mci_max_strips_per_io
,
546 sc
->sc_info
.mci_raid_levels
,
547 sc
->sc_info
.mci_adapter_ops
,
548 sc
->sc_info
.mci_ld_ops
);
550 printf("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n",
552 sc
->sc_info
.mci_stripe_sz_ops
.min
,
553 sc
->sc_info
.mci_stripe_sz_ops
.max
,
554 sc
->sc_info
.mci_pd_ops
,
555 sc
->sc_info
.mci_pd_mix_support
);
557 printf("%s: ecc_bucket %d pckg_prop %s\n",
559 sc
->sc_info
.mci_ecc_bucket_count
,
560 sc
->sc_info
.mci_package_version
);
562 printf("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n",
564 sc
->sc_info
.mci_properties
.mcp_seq_num
,
565 sc
->sc_info
.mci_properties
.mcp_pred_fail_poll_interval
,
566 sc
->sc_info
.mci_properties
.mcp_intr_throttle_cnt
,
567 sc
->sc_info
.mci_properties
.mcp_intr_throttle_timeout
);
569 printf("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n",
571 sc
->sc_info
.mci_properties
.mcp_rebuild_rate
,
572 sc
->sc_info
.mci_properties
.mcp_patrol_read_rate
,
573 sc
->sc_info
.mci_properties
.mcp_bgi_rate
,
574 sc
->sc_info
.mci_properties
.mcp_cc_rate
);
576 printf("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n",
578 sc
->sc_info
.mci_properties
.mcp_recon_rate
,
579 sc
->sc_info
.mci_properties
.mcp_cache_flush_interval
,
580 sc
->sc_info
.mci_properties
.mcp_spinup_drv_cnt
,
581 sc
->sc_info
.mci_properties
.mcp_spinup_delay
,
582 sc
->sc_info
.mci_properties
.mcp_cluster_enable
);
584 printf("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n",
586 sc
->sc_info
.mci_properties
.mcp_coercion_mode
,
587 sc
->sc_info
.mci_properties
.mcp_alarm_enable
,
588 sc
->sc_info
.mci_properties
.mcp_disable_auto_rebuild
,
589 sc
->sc_info
.mci_properties
.mcp_disable_battery_warn
,
590 sc
->sc_info
.mci_properties
.mcp_ecc_bucket_size
);
592 printf("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n",
594 sc
->sc_info
.mci_properties
.mcp_ecc_bucket_leak_rate
,
595 sc
->sc_info
.mci_properties
.mcp_restore_hotspare_on_insertion
,
596 sc
->sc_info
.mci_properties
.mcp_expose_encl_devices
);
598 printf("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n",
600 sc
->sc_info
.mci_pci
.mip_vendor
,
601 sc
->sc_info
.mci_pci
.mip_device
,
602 sc
->sc_info
.mci_pci
.mip_subvendor
,
603 sc
->sc_info
.mci_pci
.mip_subdevice
);
605 printf("%s: type %#x port_count %d port_addr ",
607 sc
->sc_info
.mci_host
.mih_type
,
608 sc
->sc_info
.mci_host
.mih_port_count
);
610 for (i
= 0; i
< 8; i
++)
611 printf("%.0lx ", sc
->sc_info
.mci_host
.mih_port_addr
[i
]);
614 printf("%s: type %.x port_count %d port_addr ",
616 sc
->sc_info
.mci_device
.mid_type
,
617 sc
->sc_info
.mci_device
.mid_port_count
);
619 for (i
= 0; i
< 8; i
++)
620 printf("%.0lx ", sc
->sc_info
.mci_device
.mid_port_addr
[i
]);
622 #endif /* MFI_DEBUG */
628 mfiminphys(struct buf
*bp
)
630 DNPRINTF(MFI_D_MISC
, "mfiminphys: %d\n", bp
->b_bcount
);
632 /* XXX currently using MFI_MAXFER = MAXPHYS */
633 if (bp
->b_bcount
> MFI_MAXFER
)
634 bp
->b_bcount
= MFI_MAXFER
;
639 mfi_rescan(device_t self
, const char *ifattr
, const int *locators
)
641 struct mfi_softc
*sc
= device_private(self
);
643 if (sc
->sc_child
!= NULL
)
646 sc
->sc_child
= config_found_sm_loc(self
, ifattr
, locators
, &sc
->sc_chan
,
653 mfi_childdetached(device_t self
, device_t child
)
655 struct mfi_softc
*sc
= device_private(self
);
657 KASSERT(self
== sc
->sc_dev
);
658 KASSERT(child
== sc
->sc_child
);
660 if (child
== sc
->sc_child
)
665 mfi_detach(struct mfi_softc
*sc
, int flags
)
669 DNPRINTF(MFI_D_MISC
, "%s: mfi_detach\n", DEVNAME(sc
));
671 if ((error
= config_detach_children(sc
->sc_dev
, flags
)) != 0)
675 mfi_destroy_sensors(sc
);
676 bio_unregister(sc
->sc_dev
);
677 #endif /* NBIO > 0 */
679 mfi_intr_disable(sc
);
681 /* TBD: shutdown firmware */
683 if ((error
= mfi_destroy_ccb(sc
)) != 0)
686 mfi_freemem(sc
, &sc
->sc_sense
);
688 mfi_freemem(sc
, &sc
->sc_frames
);
690 mfi_freemem(sc
, &sc
->sc_pcq
);
696 mfi_attach(struct mfi_softc
*sc
, enum mfi_iop iop
)
698 struct scsipi_adapter
*adapt
= &sc
->sc_adapt
;
699 struct scsipi_channel
*chan
= &sc
->sc_chan
;
700 uint32_t status
, frames
;
703 DNPRINTF(MFI_D_MISC
, "%s: mfi_attach\n", DEVNAME(sc
));
707 sc
->sc_iop
= &mfi_iop_xscale
;
710 sc
->sc_iop
= &mfi_iop_ppc
;
713 panic("%s: unknown iop %d", DEVNAME(sc
), iop
);
716 if (mfi_transition_firmware(sc
))
719 TAILQ_INIT(&sc
->sc_ccb_freeq
);
721 status
= mfi_fw_state(sc
);
722 sc
->sc_max_cmds
= status
& MFI_STATE_MAXCMD_MASK
;
723 sc
->sc_max_sgl
= (status
& MFI_STATE_MAXSGL_MASK
) >> 16;
724 DNPRINTF(MFI_D_MISC
, "%s: max commands: %u, max sgl: %u\n",
725 DEVNAME(sc
), sc
->sc_max_cmds
, sc
->sc_max_sgl
);
727 /* consumer/producer and reply queue memory */
728 sc
->sc_pcq
= mfi_allocmem(sc
, (sizeof(uint32_t) * sc
->sc_max_cmds
) +
729 sizeof(struct mfi_prod_cons
));
730 if (sc
->sc_pcq
== NULL
) {
731 aprint_error("%s: unable to allocate reply queue memory\n",
735 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_pcq
), 0,
736 sizeof(uint32_t) * sc
->sc_max_cmds
+ sizeof(struct mfi_prod_cons
),
737 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
740 /* we are not doing 64 bit IO so only calculate # of 32 bit frames */
741 frames
= (sizeof(struct mfi_sg32
) * sc
->sc_max_sgl
+
742 MFI_FRAME_SIZE
- 1) / MFI_FRAME_SIZE
+ 1;
743 sc
->sc_frames_size
= frames
* MFI_FRAME_SIZE
;
744 sc
->sc_frames
= mfi_allocmem(sc
, sc
->sc_frames_size
* sc
->sc_max_cmds
);
745 if (sc
->sc_frames
== NULL
) {
746 aprint_error("%s: unable to allocate frame memory\n",
750 /* XXX hack, fix this */
751 if (MFIMEM_DVA(sc
->sc_frames
) & 0x3f) {
752 aprint_error("%s: improper frame alignment (%#llx) FIXME\n",
753 DEVNAME(sc
), (long long int)MFIMEM_DVA(sc
->sc_frames
));
758 sc
->sc_sense
= mfi_allocmem(sc
, sc
->sc_max_cmds
* MFI_SENSE_SIZE
);
759 if (sc
->sc_sense
== NULL
) {
760 aprint_error("%s: unable to allocate sense memory\n",
765 /* now that we have all memory bits go initialize ccbs */
766 if (mfi_init_ccb(sc
)) {
767 aprint_error("%s: could not init ccb list\n", DEVNAME(sc
));
771 /* kickstart firmware with all addresses and pointers */
772 if (mfi_initialize_firmware(sc
)) {
773 aprint_error("%s: could not initialize firmware\n",
778 if (mfi_get_info(sc
)) {
779 aprint_error("%s: could not retrieve controller information\n",
784 aprint_normal("%s: logical drives %d, version %s, %dMB RAM\n",
786 sc
->sc_info
.mci_lds_present
,
787 sc
->sc_info
.mci_package_version
,
788 sc
->sc_info
.mci_memory_size
);
790 sc
->sc_ld_cnt
= sc
->sc_info
.mci_lds_present
;
791 sc
->sc_max_ld
= sc
->sc_ld_cnt
;
792 for (i
= 0; i
< sc
->sc_ld_cnt
; i
++)
793 sc
->sc_ld
[i
].ld_present
= 1;
795 memset(adapt
, 0, sizeof(*adapt
));
796 adapt
->adapt_dev
= sc
->sc_dev
;
797 adapt
->adapt_nchannels
= 1;
799 adapt
->adapt_openings
= sc
->sc_max_cmds
/ sc
->sc_ld_cnt
;
801 adapt
->adapt_openings
= sc
->sc_max_cmds
;
802 adapt
->adapt_max_periph
= adapt
->adapt_openings
;
803 adapt
->adapt_request
= mfi_scsipi_request
;
804 adapt
->adapt_minphys
= mfiminphys
;
806 memset(chan
, 0, sizeof(*chan
));
807 chan
->chan_adapter
= adapt
;
808 chan
->chan_bustype
= &scsi_bustype
;
809 chan
->chan_channel
= 0;
810 chan
->chan_flags
= 0;
811 chan
->chan_nluns
= 8;
812 chan
->chan_ntargets
= MFI_MAX_LD
;
813 chan
->chan_id
= MFI_MAX_LD
;
815 mfi_rescan(sc
->sc_dev
, "scsi", NULL
);
817 /* enable interrupts */
821 if (bio_register(sc
->sc_dev
, mfi_ioctl
) != 0)
822 panic("%s: controller registration failed", DEVNAME(sc
));
823 if (mfi_create_sensors(sc
) != 0)
824 aprint_error("%s: unable to create sensors\n", DEVNAME(sc
));
825 #endif /* NBIO > 0 */
829 mfi_freemem(sc
, &sc
->sc_sense
);
831 mfi_freemem(sc
, &sc
->sc_frames
);
833 mfi_freemem(sc
, &sc
->sc_pcq
);
839 mfi_poll(struct mfi_ccb
*ccb
)
841 struct mfi_softc
*sc
= ccb
->ccb_sc
;
842 struct mfi_frame_header
*hdr
;
845 DNPRINTF(MFI_D_CMD
, "%s: mfi_poll\n", DEVNAME(sc
));
847 hdr
= &ccb
->ccb_frame
->mfr_header
;
848 hdr
->mfh_cmd_status
= 0xff;
849 hdr
->mfh_flags
|= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE
;
852 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_frames
),
853 ccb
->ccb_pframe
- MFIMEM_DVA(sc
->sc_frames
),
854 sc
->sc_frames_size
, BUS_DMASYNC_POSTREAD
);
856 while (hdr
->mfh_cmd_status
== 0xff) {
858 if (to
++ > 5000) /* XXX 5 seconds busywait sucks */
860 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_frames
),
861 ccb
->ccb_pframe
- MFIMEM_DVA(sc
->sc_frames
),
862 sc
->sc_frames_size
, BUS_DMASYNC_POSTREAD
);
864 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_frames
),
865 ccb
->ccb_pframe
- MFIMEM_DVA(sc
->sc_frames
),
866 sc
->sc_frames_size
, BUS_DMASYNC_POSTREAD
| BUS_DMASYNC_POSTWRITE
);
868 if (ccb
->ccb_data
!= NULL
) {
869 DNPRINTF(MFI_D_INTR
, "%s: mfi_mgmt_done sync\n",
871 bus_dmamap_sync(sc
->sc_dmat
, ccb
->ccb_dmamap
, 0,
872 ccb
->ccb_dmamap
->dm_mapsize
,
873 (ccb
->ccb_direction
& MFI_DATA_IN
) ?
874 BUS_DMASYNC_POSTREAD
: BUS_DMASYNC_POSTWRITE
);
876 bus_dmamap_unload(sc
->sc_dmat
, ccb
->ccb_dmamap
);
879 if (hdr
->mfh_cmd_status
== 0xff) {
880 printf("%s: timeout on ccb %d\n", DEVNAME(sc
),
882 ccb
->ccb_flags
|= MFI_CCB_F_ERR
;
892 struct mfi_softc
*sc
= arg
;
893 struct mfi_prod_cons
*pcq
;
895 uint32_t producer
, consumer
, ctx
;
898 if (!mfi_my_intr(sc
))
901 pcq
= MFIMEM_KVA(sc
->sc_pcq
);
903 DNPRINTF(MFI_D_INTR
, "%s: mfi_intr %#lx %#lx\n", DEVNAME(sc
),
904 (u_long
)sc
, (u_long
)pcq
);
906 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_pcq
), 0,
907 sizeof(uint32_t) * sc
->sc_max_cmds
+ sizeof(struct mfi_prod_cons
),
908 BUS_DMASYNC_POSTREAD
| BUS_DMASYNC_POSTWRITE
);
910 producer
= pcq
->mpc_producer
;
911 consumer
= pcq
->mpc_consumer
;
913 while (consumer
!= producer
) {
914 DNPRINTF(MFI_D_INTR
, "%s: mfi_intr pi %#x ci %#x\n",
915 DEVNAME(sc
), producer
, consumer
);
917 ctx
= pcq
->mpc_reply_q
[consumer
];
918 pcq
->mpc_reply_q
[consumer
] = MFI_INVALID_CTX
;
919 if (ctx
== MFI_INVALID_CTX
)
920 printf("%s: invalid context, p: %d c: %d\n",
921 DEVNAME(sc
), producer
, consumer
);
923 /* XXX remove from queue and call scsi_done */
924 ccb
= &sc
->sc_ccb
[ctx
];
925 DNPRINTF(MFI_D_INTR
, "%s: mfi_intr context %#x\n",
927 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_frames
),
928 ccb
->ccb_pframe
- MFIMEM_DVA(sc
->sc_frames
),
930 BUS_DMASYNC_POSTREAD
| BUS_DMASYNC_POSTWRITE
);
936 if (consumer
== (sc
->sc_max_cmds
+ 1))
940 pcq
->mpc_consumer
= consumer
;
941 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_pcq
), 0,
942 sizeof(uint32_t) * sc
->sc_max_cmds
+ sizeof(struct mfi_prod_cons
),
943 BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
949 mfi_scsi_io(struct mfi_ccb
*ccb
, struct scsipi_xfer
*xs
, uint32_t blockno
,
952 struct scsipi_periph
*periph
= xs
->xs_periph
;
953 struct mfi_io_frame
*io
;
955 DNPRINTF(MFI_D_CMD
, "%s: mfi_scsi_io: %d\n",
956 device_xname(periph
->periph_channel
->chan_adapter
->adapt_dev
),
957 periph
->periph_target
);
962 io
= &ccb
->ccb_frame
->mfr_io
;
963 if (xs
->xs_control
& XS_CTL_DATA_IN
) {
964 io
->mif_header
.mfh_cmd
= MFI_CMD_LD_READ
;
965 ccb
->ccb_direction
= MFI_DATA_IN
;
967 io
->mif_header
.mfh_cmd
= MFI_CMD_LD_WRITE
;
968 ccb
->ccb_direction
= MFI_DATA_OUT
;
970 io
->mif_header
.mfh_target_id
= periph
->periph_target
;
971 io
->mif_header
.mfh_timeout
= 0;
972 io
->mif_header
.mfh_flags
= 0;
973 io
->mif_header
.mfh_sense_len
= MFI_SENSE_SIZE
;
974 io
->mif_header
.mfh_data_len
= blockcnt
;
976 io
->mif_lba_lo
= blockno
;
977 io
->mif_sense_addr_lo
= htole32(ccb
->ccb_psense
);
978 io
->mif_sense_addr_hi
= 0;
980 ccb
->ccb_done
= mfi_scsi_xs_done
;
982 ccb
->ccb_frame_size
= MFI_IO_FRAME_SIZE
;
983 ccb
->ccb_sgl
= &io
->mif_sgl
;
984 ccb
->ccb_data
= xs
->data
;
985 ccb
->ccb_len
= xs
->datalen
;
987 if (mfi_create_sgl(ccb
, (xs
->xs_control
& XS_CTL_NOSLEEP
) ?
988 BUS_DMA_NOWAIT
: BUS_DMA_WAITOK
))
995 mfi_scsi_xs_done(struct mfi_ccb
*ccb
)
997 struct scsipi_xfer
*xs
= ccb
->ccb_xs
;
998 struct mfi_softc
*sc
= ccb
->ccb_sc
;
999 struct mfi_frame_header
*hdr
= &ccb
->ccb_frame
->mfr_header
;
1001 DNPRINTF(MFI_D_INTR
, "%s: mfi_scsi_xs_done %#lx %#lx\n",
1002 DEVNAME(sc
), (u_long
)ccb
, (u_long
)ccb
->ccb_frame
);
1004 if (xs
->data
!= NULL
) {
1005 DNPRINTF(MFI_D_INTR
, "%s: mfi_scsi_xs_done sync\n",
1007 bus_dmamap_sync(sc
->sc_dmat
, ccb
->ccb_dmamap
, 0,
1008 ccb
->ccb_dmamap
->dm_mapsize
,
1009 (xs
->xs_control
& XS_CTL_DATA_IN
) ?
1010 BUS_DMASYNC_POSTREAD
: BUS_DMASYNC_POSTWRITE
);
1012 bus_dmamap_unload(sc
->sc_dmat
, ccb
->ccb_dmamap
);
1015 if (hdr
->mfh_cmd_status
!= MFI_STAT_OK
) {
1016 xs
->error
= XS_DRIVER_STUFFUP
;
1017 DNPRINTF(MFI_D_INTR
, "%s: mfi_scsi_xs_done stuffup %#x\n",
1018 DEVNAME(sc
), hdr
->mfh_cmd_status
);
1020 if (hdr
->mfh_scsi_status
!= 0) {
1021 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_sense
),
1022 ccb
->ccb_psense
- MFIMEM_DVA(sc
->sc_sense
),
1023 MFI_SENSE_SIZE
, BUS_DMASYNC_POSTREAD
);
1024 DNPRINTF(MFI_D_INTR
,
1025 "%s: mfi_scsi_xs_done sense %#x %lx %lx\n",
1026 DEVNAME(sc
), hdr
->mfh_scsi_status
,
1027 (u_long
)&xs
->sense
, (u_long
)ccb
->ccb_sense
);
1028 memset(&xs
->sense
, 0, sizeof(xs
->sense
));
1029 memcpy(&xs
->sense
, ccb
->ccb_sense
,
1030 sizeof(struct scsi_sense_data
));
1031 xs
->error
= XS_SENSE
;
1034 xs
->error
= XS_NOERROR
;
1035 xs
->status
= SCSI_OK
;
1044 mfi_scsi_ld(struct mfi_ccb
*ccb
, struct scsipi_xfer
*xs
)
1046 struct mfi_pass_frame
*pf
;
1047 struct scsipi_periph
*periph
= xs
->xs_periph
;
1049 DNPRINTF(MFI_D_CMD
, "%s: mfi_scsi_ld: %d\n",
1050 device_xname(periph
->periph_channel
->chan_adapter
->adapt_dev
),
1051 periph
->periph_target
);
1053 pf
= &ccb
->ccb_frame
->mfr_pass
;
1054 pf
->mpf_header
.mfh_cmd
= MFI_CMD_LD_SCSI_IO
;
1055 pf
->mpf_header
.mfh_target_id
= periph
->periph_target
;
1056 pf
->mpf_header
.mfh_lun_id
= 0;
1057 pf
->mpf_header
.mfh_cdb_len
= xs
->cmdlen
;
1058 pf
->mpf_header
.mfh_timeout
= 0;
1059 pf
->mpf_header
.mfh_data_len
= xs
->datalen
; /* XXX */
1060 pf
->mpf_header
.mfh_sense_len
= MFI_SENSE_SIZE
;
1062 pf
->mpf_sense_addr_hi
= 0;
1063 pf
->mpf_sense_addr_lo
= htole32(ccb
->ccb_psense
);
1065 memset(pf
->mpf_cdb
, 0, 16);
1066 memcpy(pf
->mpf_cdb
, &xs
->cmdstore
, xs
->cmdlen
);
1068 ccb
->ccb_done
= mfi_scsi_xs_done
;
1070 ccb
->ccb_frame_size
= MFI_PASS_FRAME_SIZE
;
1071 ccb
->ccb_sgl
= &pf
->mpf_sgl
;
1073 if (xs
->xs_control
& (XS_CTL_DATA_IN
| XS_CTL_DATA_OUT
))
1074 ccb
->ccb_direction
= (xs
->xs_control
& XS_CTL_DATA_IN
) ?
1075 MFI_DATA_IN
: MFI_DATA_OUT
;
1077 ccb
->ccb_direction
= MFI_DATA_NONE
;
1080 ccb
->ccb_data
= xs
->data
;
1081 ccb
->ccb_len
= xs
->datalen
;
1083 if (mfi_create_sgl(ccb
, (xs
->xs_control
& XS_CTL_NOSLEEP
) ?
1084 BUS_DMA_NOWAIT
: BUS_DMA_WAITOK
))
1092 mfi_scsipi_request(struct scsipi_channel
*chan
, scsipi_adapter_req_t req
,
1095 struct scsipi_periph
*periph
;
1096 struct scsipi_xfer
*xs
;
1097 struct scsipi_adapter
*adapt
= chan
->chan_adapter
;
1098 struct mfi_softc
*sc
= device_private(adapt
->adapt_dev
);
1099 struct mfi_ccb
*ccb
;
1100 struct scsi_rw_6
*rw
;
1101 struct scsipi_rw_10
*rwb
;
1102 uint32_t blockno
, blockcnt
;
1104 uint8_t mbox
[MFI_MBOX_SIZE
];
1108 case ADAPTER_REQ_GROW_RESOURCES
:
1109 /* Not supported. */
1111 case ADAPTER_REQ_SET_XFER_MODE
:
1112 /* Not supported. */
1114 case ADAPTER_REQ_RUN_XFER
:
1120 DNPRINTF(MFI_D_CMD
, "%s: mfi_scsipi_request req %d opcode: %#x\n",
1121 DEVNAME(sc
), req
, xs
->cmd
->opcode
);
1123 periph
= xs
->xs_periph
;
1124 target
= periph
->periph_target
;
1127 if (target
>= MFI_MAX_LD
|| !sc
->sc_ld
[target
].ld_present
||
1128 periph
->periph_lun
!= 0) {
1129 DNPRINTF(MFI_D_CMD
, "%s: invalid target %d\n",
1130 DEVNAME(sc
), target
);
1131 xs
->error
= XS_SELTIMEOUT
;
1137 if ((ccb
= mfi_get_ccb(sc
)) == NULL
) {
1138 DNPRINTF(MFI_D_CMD
, "%s: mfi_scsipi_request no ccb\n", DEVNAME(sc
));
1139 xs
->error
= XS_RESOURCE_SHORTAGE
;
1145 switch (xs
->cmd
->opcode
) {
1149 rwb
= (struct scsipi_rw_10
*)xs
->cmd
;
1150 blockno
= _4btol(rwb
->addr
);
1151 blockcnt
= _2btol(rwb
->length
);
1152 if (mfi_scsi_io(ccb
, xs
, blockno
, blockcnt
)) {
1158 case SCSI_READ_6_COMMAND
:
1159 case SCSI_WRITE_6_COMMAND
:
1160 rw
= (struct scsi_rw_6
*)xs
->cmd
;
1161 blockno
= _3btol(rw
->addr
) & (SRW_TOPADDR
<< 16 | 0xffff);
1162 blockcnt
= rw
->length
? rw
->length
: 0x100;
1163 if (mfi_scsi_io(ccb
, xs
, blockno
, blockcnt
)) {
1169 case SCSI_SYNCHRONIZE_CACHE_10
:
1170 mbox
[0] = MR_FLUSH_CTRL_CACHE
| MR_FLUSH_DISK_CACHE
;
1171 if (mfi_mgmt(ccb
, xs
,
1172 MR_DCMD_CTRL_CACHE_FLUSH
, MFI_DATA_NONE
, 0, NULL
, mbox
)) {
1178 /* hand it of to the firmware and let it deal with it */
1179 case SCSI_TEST_UNIT_READY
:
1180 /* save off sd? after autoconf */
1181 if (!cold
) /* XXX bogus */
1182 strlcpy(sc
->sc_ld
[target
].ld_dev
, device_xname(sc
->sc_dev
),
1183 sizeof(sc
->sc_ld
[target
].ld_dev
));
1187 if (mfi_scsi_ld(ccb
, xs
)) {
1194 DNPRINTF(MFI_D_CMD
, "%s: start io %d\n", DEVNAME(sc
), target
);
1196 if (xs
->xs_control
& XS_CTL_POLL
) {
1197 if (mfi_poll(ccb
)) {
1198 /* XXX check for sense in ccb->ccb_sense? */
1199 printf("%s: mfi_scsipi_request poll failed\n",
1201 memset(&xs
->sense
, 0, sizeof(xs
->sense
));
1202 xs
->sense
.scsi_sense
.response_code
=
1203 SSD_RCODE_VALID
| SSD_RCODE_CURRENT
;
1204 xs
->sense
.scsi_sense
.flags
= SKEY_ILLEGAL_REQUEST
;
1205 xs
->sense
.scsi_sense
.asc
= 0x20; /* invalid opcode */
1206 xs
->error
= XS_SENSE
;
1207 xs
->status
= SCSI_CHECK
;
1210 "%s: mfi_scsipi_request poll complete %d\n",
1211 DEVNAME(sc
), ccb
->ccb_dmamap
->dm_nsegs
);
1212 xs
->error
= XS_NOERROR
;
1213 xs
->status
= SCSI_OK
;
1224 DNPRINTF(MFI_D_DMA
, "%s: mfi_scsipi_request queued %d\n", DEVNAME(sc
),
1225 ccb
->ccb_dmamap
->dm_nsegs
);
1231 xs
->error
= XS_DRIVER_STUFFUP
;
1237 mfi_create_sgl(struct mfi_ccb
*ccb
, int flags
)
1239 struct mfi_softc
*sc
= ccb
->ccb_sc
;
1240 struct mfi_frame_header
*hdr
;
1241 bus_dma_segment_t
*sgd
;
1245 DNPRINTF(MFI_D_DMA
, "%s: mfi_create_sgl %#lx\n", DEVNAME(sc
),
1246 (u_long
)ccb
->ccb_data
);
1251 error
= bus_dmamap_load(sc
->sc_dmat
, ccb
->ccb_dmamap
,
1252 ccb
->ccb_data
, ccb
->ccb_len
, NULL
, flags
);
1255 printf("more than %d dma segs\n",
1258 printf("error %d loading dma map\n", error
);
1262 hdr
= &ccb
->ccb_frame
->mfr_header
;
1264 sgd
= ccb
->ccb_dmamap
->dm_segs
;
1265 for (i
= 0; i
< ccb
->ccb_dmamap
->dm_nsegs
; i
++) {
1266 sgl
->sg32
[i
].addr
= htole32(sgd
[i
].ds_addr
);
1267 sgl
->sg32
[i
].len
= htole32(sgd
[i
].ds_len
);
1268 DNPRINTF(MFI_D_DMA
, "%s: addr: %#x len: %#x\n",
1269 DEVNAME(sc
), sgl
->sg32
[i
].addr
, sgl
->sg32
[i
].len
);
1272 if (ccb
->ccb_direction
== MFI_DATA_IN
) {
1273 hdr
->mfh_flags
|= MFI_FRAME_DIR_READ
;
1274 bus_dmamap_sync(sc
->sc_dmat
, ccb
->ccb_dmamap
, 0,
1275 ccb
->ccb_dmamap
->dm_mapsize
, BUS_DMASYNC_PREREAD
);
1277 hdr
->mfh_flags
|= MFI_FRAME_DIR_WRITE
;
1278 bus_dmamap_sync(sc
->sc_dmat
, ccb
->ccb_dmamap
, 0,
1279 ccb
->ccb_dmamap
->dm_mapsize
, BUS_DMASYNC_PREWRITE
);
1282 hdr
->mfh_sg_count
= ccb
->ccb_dmamap
->dm_nsegs
;
1283 /* for 64 bit io make the sizeof a variable to hold whatever sg size */
1284 ccb
->ccb_frame_size
+= sizeof(struct mfi_sg32
) *
1285 ccb
->ccb_dmamap
->dm_nsegs
;
1286 ccb
->ccb_extra_frames
= (ccb
->ccb_frame_size
- 1) / MFI_FRAME_SIZE
;
1288 DNPRINTF(MFI_D_DMA
, "%s: sg_count: %d frame_size: %d frames_size: %d"
1289 " dm_nsegs: %d extra_frames: %d\n",
1292 ccb
->ccb_frame_size
,
1294 ccb
->ccb_dmamap
->dm_nsegs
,
1295 ccb
->ccb_extra_frames
);
1301 mfi_mgmt_internal(struct mfi_softc
*sc
, uint32_t opc
, uint32_t dir
,
1302 uint32_t len
, void *buf
, uint8_t *mbox
) {
1303 struct mfi_ccb
*ccb
;
1306 if ((ccb
= mfi_get_ccb(sc
)) == NULL
)
1308 rv
= mfi_mgmt(ccb
, NULL
, opc
, dir
, len
, buf
, mbox
);
1318 DNPRINTF(MFI_D_MISC
, "%s: mfi_mgmt_internal sleeping\n",
1320 while (ccb
->ccb_state
!= MFI_CCB_DONE
)
1321 tsleep(ccb
, PRIBIO
, "mfi_mgmt", 0);
1323 if (ccb
->ccb_flags
& MFI_CCB_F_ERR
)
1334 mfi_mgmt(struct mfi_ccb
*ccb
, struct scsipi_xfer
*xs
,
1335 uint32_t opc
, uint32_t dir
, uint32_t len
, void *buf
, uint8_t *mbox
)
1337 struct mfi_dcmd_frame
*dcmd
;
1339 DNPRINTF(MFI_D_MISC
, "%s: mfi_mgmt %#x\n", DEVNAME(ccb
->ccb_sc
), opc
);
1341 dcmd
= &ccb
->ccb_frame
->mfr_dcmd
;
1342 memset(dcmd
->mdf_mbox
, 0, MFI_MBOX_SIZE
);
1343 dcmd
->mdf_header
.mfh_cmd
= MFI_CMD_DCMD
;
1344 dcmd
->mdf_header
.mfh_timeout
= 0;
1346 dcmd
->mdf_opcode
= opc
;
1347 dcmd
->mdf_header
.mfh_data_len
= 0;
1348 ccb
->ccb_direction
= dir
;
1350 ccb
->ccb_done
= mfi_mgmt_done
;
1352 ccb
->ccb_frame_size
= MFI_DCMD_FRAME_SIZE
;
1354 /* handle special opcodes */
1356 memcpy(dcmd
->mdf_mbox
, mbox
, MFI_MBOX_SIZE
);
1358 if (dir
!= MFI_DATA_NONE
) {
1359 dcmd
->mdf_header
.mfh_data_len
= len
;
1360 ccb
->ccb_data
= buf
;
1362 ccb
->ccb_sgl
= &dcmd
->mdf_sgl
;
1364 if (mfi_create_sgl(ccb
, BUS_DMA_WAITOK
))
1371 mfi_mgmt_done(struct mfi_ccb
*ccb
)
1373 struct scsipi_xfer
*xs
= ccb
->ccb_xs
;
1374 struct mfi_softc
*sc
= ccb
->ccb_sc
;
1375 struct mfi_frame_header
*hdr
= &ccb
->ccb_frame
->mfr_header
;
1377 DNPRINTF(MFI_D_INTR
, "%s: mfi_mgmt_done %#lx %#lx\n",
1378 DEVNAME(sc
), (u_long
)ccb
, (u_long
)ccb
->ccb_frame
);
1380 if (ccb
->ccb_data
!= NULL
) {
1381 DNPRINTF(MFI_D_INTR
, "%s: mfi_mgmt_done sync\n",
1383 bus_dmamap_sync(sc
->sc_dmat
, ccb
->ccb_dmamap
, 0,
1384 ccb
->ccb_dmamap
->dm_mapsize
,
1385 (ccb
->ccb_direction
& MFI_DATA_IN
) ?
1386 BUS_DMASYNC_POSTREAD
: BUS_DMASYNC_POSTWRITE
);
1388 bus_dmamap_unload(sc
->sc_dmat
, ccb
->ccb_dmamap
);
1391 if (hdr
->mfh_cmd_status
!= MFI_STAT_OK
)
1392 ccb
->ccb_flags
|= MFI_CCB_F_ERR
;
1394 ccb
->ccb_state
= MFI_CCB_DONE
;
1396 if (hdr
->mfh_cmd_status
!= MFI_STAT_OK
) {
1397 xs
->error
= XS_DRIVER_STUFFUP
;
1399 xs
->error
= XS_NOERROR
;
1400 xs
->status
= SCSI_OK
;
1411 mfi_ioctl(device_t dev
, u_long cmd
, void *addr
)
1413 struct mfi_softc
*sc
= device_private(dev
);
1417 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl ", DEVNAME(sc
));
1421 DNPRINTF(MFI_D_IOCTL
, "inq\n");
1422 error
= mfi_ioctl_inq(sc
, (struct bioc_inq
*)addr
);
1426 DNPRINTF(MFI_D_IOCTL
, "vol\n");
1427 error
= mfi_ioctl_vol(sc
, (struct bioc_vol
*)addr
);
1431 DNPRINTF(MFI_D_IOCTL
, "disk\n");
1432 error
= mfi_ioctl_disk(sc
, (struct bioc_disk
*)addr
);
1436 DNPRINTF(MFI_D_IOCTL
, "alarm\n");
1437 error
= mfi_ioctl_alarm(sc
, (struct bioc_alarm
*)addr
);
1441 DNPRINTF(MFI_D_IOCTL
, "blink\n");
1442 error
= mfi_ioctl_blink(sc
, (struct bioc_blink
*)addr
);
1446 DNPRINTF(MFI_D_IOCTL
, "setstate\n");
1447 error
= mfi_ioctl_setstate(sc
, (struct bioc_setstate
*)addr
);
1451 DNPRINTF(MFI_D_IOCTL
, " invalid ioctl\n");
1456 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl return %x\n", DEVNAME(sc
), error
);
1461 mfi_ioctl_inq(struct mfi_softc
*sc
, struct bioc_inq
*bi
)
1463 struct mfi_conf
*cfg
;
1466 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_inq\n", DEVNAME(sc
));
1468 if (mfi_get_info(sc
)) {
1469 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_inq failed\n",
1475 cfg
= malloc(sizeof *cfg
, M_DEVBUF
, M_WAITOK
);
1476 if (mfi_mgmt_internal(sc
, MD_DCMD_CONF_GET
, MFI_DATA_IN
,
1477 sizeof *cfg
, cfg
, NULL
))
1480 strlcpy(bi
->bi_dev
, DEVNAME(sc
), sizeof(bi
->bi_dev
));
1481 bi
->bi_novol
= cfg
->mfc_no_ld
+ cfg
->mfc_no_hs
;
1482 bi
->bi_nodisk
= sc
->sc_info
.mci_pd_disks_present
;
1486 free(cfg
, M_DEVBUF
);
1491 mfi_ioctl_vol(struct mfi_softc
*sc
, struct bioc_vol
*bv
)
1493 int i
, per
, rv
= EINVAL
;
1494 uint8_t mbox
[MFI_MBOX_SIZE
];
1496 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_vol %#x\n",
1497 DEVNAME(sc
), bv
->bv_volid
);
1499 if (mfi_mgmt_internal(sc
, MR_DCMD_LD_GET_LIST
, MFI_DATA_IN
,
1500 sizeof(sc
->sc_ld_list
), &sc
->sc_ld_list
, NULL
))
1504 mbox
[0] = sc
->sc_ld_list
.mll_list
[i
].mll_ld
.mld_target
;
1505 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_vol target %#x\n",
1506 DEVNAME(sc
), mbox
[0]);
1508 if (mfi_mgmt_internal(sc
, MR_DCMD_LD_GET_INFO
, MFI_DATA_IN
,
1509 sizeof(sc
->sc_ld_details
), &sc
->sc_ld_details
, mbox
))
1512 if (bv
->bv_volid
>= sc
->sc_ld_list
.mll_no_ld
) {
1513 /* go do hotspares */
1514 rv
= mfi_bio_hs(sc
, bv
->bv_volid
, MFI_MGMT_VD
, bv
);
1518 strlcpy(bv
->bv_dev
, sc
->sc_ld
[i
].ld_dev
, sizeof(bv
->bv_dev
));
1520 switch(sc
->sc_ld_list
.mll_list
[i
].mll_state
) {
1521 case MFI_LD_OFFLINE
:
1522 bv
->bv_status
= BIOC_SVOFFLINE
;
1525 case MFI_LD_PART_DEGRADED
:
1526 case MFI_LD_DEGRADED
:
1527 bv
->bv_status
= BIOC_SVDEGRADED
;
1531 bv
->bv_status
= BIOC_SVONLINE
;
1535 bv
->bv_status
= BIOC_SVINVALID
;
1536 DNPRINTF(MFI_D_IOCTL
, "%s: invalid logical disk state %#x\n",
1538 sc
->sc_ld_list
.mll_list
[i
].mll_state
);
1541 /* additional status can modify MFI status */
1542 switch (sc
->sc_ld_details
.mld_progress
.mlp_in_prog
) {
1543 case MFI_LD_PROG_CC
:
1544 case MFI_LD_PROG_BGI
:
1545 bv
->bv_status
= BIOC_SVSCRUB
;
1546 per
= (int)sc
->sc_ld_details
.mld_progress
.mlp_cc
.mp_progress
;
1547 bv
->bv_percent
= (per
* 100) / 0xffff;
1549 sc
->sc_ld_details
.mld_progress
.mlp_cc
.mp_elapsed_seconds
;
1552 case MFI_LD_PROG_FGI
:
1553 case MFI_LD_PROG_RECONSTRUCT
:
1559 * The RAID levels are determined per the SNIA DDF spec, this is only
1560 * a subset that is valid for the MFI contrller.
1562 bv
->bv_level
= sc
->sc_ld_details
.mld_cfg
.mlc_parm
.mpa_pri_raid
;
1563 if (sc
->sc_ld_details
.mld_cfg
.mlc_parm
.mpa_sec_raid
==
1564 MFI_DDF_SRL_SPANNED
)
1567 bv
->bv_nodisk
= sc
->sc_ld_details
.mld_cfg
.mlc_parm
.mpa_no_drv_per_span
*
1568 sc
->sc_ld_details
.mld_cfg
.mlc_parm
.mpa_span_depth
;
1570 bv
->bv_size
= sc
->sc_ld_details
.mld_size
* 512; /* bytes per block */
1574 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_vol done %x\n",
1580 mfi_ioctl_disk(struct mfi_softc
*sc
, struct bioc_disk
*bd
)
1582 struct mfi_conf
*cfg
;
1583 struct mfi_array
*ar
;
1584 struct mfi_ld_cfg
*ld
;
1585 struct mfi_pd_details
*pd
;
1586 struct scsipi_inquiry_data
*inqbuf
;
1587 char vend
[8+16+4+1];
1591 uint8_t mbox
[MFI_MBOX_SIZE
];
1593 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_disk %#x\n",
1594 DEVNAME(sc
), bd
->bd_diskid
);
1596 pd
= malloc(sizeof *pd
, M_DEVBUF
, M_WAITOK
| M_ZERO
);
1598 /* send single element command to retrieve size for full structure */
1599 cfg
= malloc(sizeof *cfg
, M_DEVBUF
, M_WAITOK
);
1600 if (mfi_mgmt_internal(sc
, MD_DCMD_CONF_GET
, MFI_DATA_IN
,
1601 sizeof *cfg
, cfg
, NULL
))
1604 size
= cfg
->mfc_size
;
1605 free(cfg
, M_DEVBUF
);
1607 /* memory for read config */
1608 cfg
= malloc(size
, M_DEVBUF
, M_WAITOK
|M_ZERO
);
1609 if (mfi_mgmt_internal(sc
, MD_DCMD_CONF_GET
, MFI_DATA_IN
,
1613 ar
= cfg
->mfc_array
;
1615 /* calculate offset to ld structure */
1616 ld
= (struct mfi_ld_cfg
*)(
1617 ((uint8_t *)cfg
) + offsetof(struct mfi_conf
, mfc_array
) +
1618 cfg
->mfc_array_size
* cfg
->mfc_no_array
);
1622 if (vol
>= cfg
->mfc_no_ld
) {
1624 rv
= mfi_bio_hs(sc
, bd
->bd_volid
, MFI_MGMT_SD
, bd
);
1628 /* find corresponding array for ld */
1629 for (i
= 0, arr
= 0; i
< vol
; i
++)
1630 arr
+= ld
[i
].mlc_parm
.mpa_span_depth
;
1632 /* offset disk into pd list */
1633 disk
= bd
->bd_diskid
% ld
[vol
].mlc_parm
.mpa_no_drv_per_span
;
1635 /* offset array index into the next spans */
1636 arr
+= bd
->bd_diskid
/ ld
[vol
].mlc_parm
.mpa_no_drv_per_span
;
1638 bd
->bd_target
= ar
[arr
].pd
[disk
].mar_enc_slot
;
1639 switch (ar
[arr
].pd
[disk
].mar_pd_state
){
1640 case MFI_PD_UNCONFIG_GOOD
:
1641 bd
->bd_status
= BIOC_SDUNUSED
;
1644 case MFI_PD_HOTSPARE
: /* XXX dedicated hotspare part of array? */
1645 bd
->bd_status
= BIOC_SDHOTSPARE
;
1648 case MFI_PD_OFFLINE
:
1649 bd
->bd_status
= BIOC_SDOFFLINE
;
1653 bd
->bd_status
= BIOC_SDFAILED
;
1656 case MFI_PD_REBUILD
:
1657 bd
->bd_status
= BIOC_SDREBUILD
;
1661 bd
->bd_status
= BIOC_SDONLINE
;
1664 case MFI_PD_UNCONFIG_BAD
: /* XXX define new state in bio */
1666 bd
->bd_status
= BIOC_SDINVALID
;
1671 /* get the remaining fields */
1672 *((uint16_t *)&mbox
) = ar
[arr
].pd
[disk
].mar_pd
.mfp_id
;
1673 memset(pd
, 0, sizeof(*pd
));
1674 if (mfi_mgmt_internal(sc
, MR_DCMD_PD_GET_INFO
, MFI_DATA_IN
,
1675 sizeof *pd
, pd
, mbox
))
1678 bd
->bd_size
= pd
->mpd_size
* 512; /* bytes per block */
1680 /* if pd->mpd_enc_idx is 0 then it is not in an enclosure */
1681 bd
->bd_channel
= pd
->mpd_enc_idx
;
1683 inqbuf
= (struct scsipi_inquiry_data
*)&pd
->mpd_inq_data
;
1684 memcpy(vend
, inqbuf
->vendor
, sizeof vend
- 1);
1685 vend
[sizeof vend
- 1] = '\0';
1686 strlcpy(bd
->bd_vendor
, vend
, sizeof(bd
->bd_vendor
));
1688 /* XXX find a way to retrieve serial nr from drive */
1689 /* XXX find a way to get bd_procdev */
1694 free(cfg
, M_DEVBUF
);
1700 mfi_ioctl_alarm(struct mfi_softc
*sc
, struct bioc_alarm
*ba
)
1702 uint32_t opc
, dir
= MFI_DATA_NONE
;
1706 switch(ba
->ba_opcode
) {
1707 case BIOC_SADISABLE
:
1708 opc
= MR_DCMD_SPEAKER_DISABLE
;
1712 opc
= MR_DCMD_SPEAKER_ENABLE
;
1715 case BIOC_SASILENCE
:
1716 opc
= MR_DCMD_SPEAKER_SILENCE
;
1720 opc
= MR_DCMD_SPEAKER_GET
;
1725 opc
= MR_DCMD_SPEAKER_TEST
;
1729 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_alarm biocalarm invalid "
1730 "opcode %x\n", DEVNAME(sc
), ba
->ba_opcode
);
1734 if (mfi_mgmt_internal(sc
, opc
, dir
, sizeof(ret
), &ret
, NULL
))
1737 if (ba
->ba_opcode
== BIOC_GASTATUS
)
1738 ba
->ba_status
= ret
;
1746 mfi_ioctl_blink(struct mfi_softc
*sc
, struct bioc_blink
*bb
)
1748 int i
, found
, rv
= EINVAL
;
1749 uint8_t mbox
[MFI_MBOX_SIZE
];
1751 struct mfi_pd_list
*pd
;
1753 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_blink %x\n", DEVNAME(sc
),
1756 /* channel 0 means not in an enclosure so can't be blinked */
1757 if (bb
->bb_channel
== 0)
1760 pd
= malloc(MFI_PD_LIST_SIZE
, M_DEVBUF
, M_WAITOK
);
1762 if (mfi_mgmt_internal(sc
, MR_DCMD_PD_GET_LIST
, MFI_DATA_IN
,
1763 MFI_PD_LIST_SIZE
, pd
, NULL
))
1766 for (i
= 0, found
= 0; i
< pd
->mpl_no_pd
; i
++)
1767 if (bb
->bb_channel
== pd
->mpl_address
[i
].mpa_enc_index
&&
1768 bb
->bb_target
== pd
->mpl_address
[i
].mpa_enc_slot
) {
1776 memset(mbox
, 0, sizeof mbox
);
1778 *((uint16_t *)&mbox
) = pd
->mpl_address
[i
].mpa_pd_id
;
1780 switch (bb
->bb_status
) {
1781 case BIOC_SBUNBLINK
:
1782 cmd
= MR_DCMD_PD_UNBLINK
;
1786 cmd
= MR_DCMD_PD_BLINK
;
1791 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_blink biocblink invalid "
1792 "opcode %x\n", DEVNAME(sc
), bb
->bb_status
);
1797 if (mfi_mgmt_internal(sc
, cmd
, MFI_DATA_NONE
, 0, NULL
, mbox
))
1807 mfi_ioctl_setstate(struct mfi_softc
*sc
, struct bioc_setstate
*bs
)
1809 struct mfi_pd_list
*pd
;
1810 int i
, found
, rv
= EINVAL
;
1811 uint8_t mbox
[MFI_MBOX_SIZE
];
1814 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_setstate %x\n", DEVNAME(sc
),
1817 pd
= malloc(MFI_PD_LIST_SIZE
, M_DEVBUF
, M_WAITOK
);
1819 if (mfi_mgmt_internal(sc
, MR_DCMD_PD_GET_LIST
, MFI_DATA_IN
,
1820 MFI_PD_LIST_SIZE
, pd
, NULL
))
1823 for (i
= 0, found
= 0; i
< pd
->mpl_no_pd
; i
++)
1824 if (bs
->bs_channel
== pd
->mpl_address
[i
].mpa_enc_index
&&
1825 bs
->bs_target
== pd
->mpl_address
[i
].mpa_enc_slot
) {
1833 memset(mbox
, 0, sizeof mbox
);
1835 *((uint16_t *)&mbox
) = pd
->mpl_address
[i
].mpa_pd_id
;
1837 switch (bs
->bs_status
) {
1839 mbox
[2] = MFI_PD_ONLINE
;
1840 cmd
= MD_DCMD_PD_SET_STATE
;
1843 case BIOC_SSOFFLINE
:
1844 mbox
[2] = MFI_PD_OFFLINE
;
1845 cmd
= MD_DCMD_PD_SET_STATE
;
1848 case BIOC_SSHOTSPARE
:
1849 mbox
[2] = MFI_PD_HOTSPARE
;
1850 cmd
= MD_DCMD_PD_SET_STATE
;
1853 case BIOC_SSREBUILD:
1854 cmd = MD_DCMD_PD_REBUILD;
1858 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_ioctl_setstate invalid "
1859 "opcode %x\n", DEVNAME(sc
), bs
->bs_status
);
1864 if (mfi_mgmt_internal(sc
, MD_DCMD_PD_SET_STATE
, MFI_DATA_NONE
,
1875 mfi_bio_hs(struct mfi_softc
*sc
, int volid
, int type
, void *bio_hs
)
1877 struct mfi_conf
*cfg
;
1878 struct mfi_hotspare
*hs
;
1879 struct mfi_pd_details
*pd
;
1880 struct bioc_disk
*sdhs
;
1881 struct bioc_vol
*vdhs
;
1882 struct scsipi_inquiry_data
*inqbuf
;
1883 char vend
[8+16+4+1];
1886 uint8_t mbox
[MFI_MBOX_SIZE
];
1888 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_vol_hs %d\n", DEVNAME(sc
), volid
);
1893 pd
= malloc(sizeof *pd
, M_DEVBUF
, M_WAITOK
| M_ZERO
);
1895 /* send single element command to retrieve size for full structure */
1896 cfg
= malloc(sizeof *cfg
, M_DEVBUF
, M_WAITOK
);
1897 if (mfi_mgmt_internal(sc
, MD_DCMD_CONF_GET
, MFI_DATA_IN
,
1898 sizeof *cfg
, cfg
, NULL
))
1901 size
= cfg
->mfc_size
;
1902 free(cfg
, M_DEVBUF
);
1904 /* memory for read config */
1905 cfg
= malloc(size
, M_DEVBUF
, M_WAITOK
|M_ZERO
);
1906 if (mfi_mgmt_internal(sc
, MD_DCMD_CONF_GET
, MFI_DATA_IN
,
1910 /* calculate offset to hs structure */
1911 hs
= (struct mfi_hotspare
*)(
1912 ((uint8_t *)cfg
) + offsetof(struct mfi_conf
, mfc_array
) +
1913 cfg
->mfc_array_size
* cfg
->mfc_no_array
+
1914 cfg
->mfc_ld_size
* cfg
->mfc_no_ld
);
1916 if (volid
< cfg
->mfc_no_ld
)
1917 goto freeme
; /* not a hotspare */
1919 if (volid
> (cfg
->mfc_no_ld
+ cfg
->mfc_no_hs
))
1920 goto freeme
; /* not a hotspare */
1922 /* offset into hotspare structure */
1923 i
= volid
- cfg
->mfc_no_ld
;
1925 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_vol_hs i %d volid %d no_ld %d no_hs %d "
1926 "hs %p cfg %p id %02x\n", DEVNAME(sc
), i
, volid
, cfg
->mfc_no_ld
,
1927 cfg
->mfc_no_hs
, hs
, cfg
, hs
[i
].mhs_pd
.mfp_id
);
1930 memset(mbox
, 0, sizeof mbox
);
1931 *((uint16_t *)&mbox
) = hs
[i
].mhs_pd
.mfp_id
;
1932 if (mfi_mgmt_internal(sc
, MR_DCMD_PD_GET_INFO
, MFI_DATA_IN
,
1933 sizeof *pd
, pd
, mbox
)) {
1934 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_vol_hs illegal PD\n",
1942 vdhs
->bv_status
= BIOC_SVONLINE
;
1943 vdhs
->bv_size
= pd
->mpd_size
* 512; /* bytes per block */
1944 vdhs
->bv_level
= -1; /* hotspare */
1945 vdhs
->bv_nodisk
= 1;
1950 sdhs
->bd_status
= BIOC_SDHOTSPARE
;
1951 sdhs
->bd_size
= pd
->mpd_size
* 512; /* bytes per block */
1952 sdhs
->bd_channel
= pd
->mpd_enc_idx
;
1953 sdhs
->bd_target
= pd
->mpd_enc_slot
;
1954 inqbuf
= (struct scsipi_inquiry_data
*)&pd
->mpd_inq_data
;
1955 memcpy(vend
, inqbuf
->vendor
, sizeof(vend
) - 1);
1956 vend
[sizeof vend
- 1] = '\0';
1957 strlcpy(sdhs
->bd_vendor
, vend
, sizeof(sdhs
->bd_vendor
));
1964 DNPRINTF(MFI_D_IOCTL
, "%s: mfi_vol_hs 6\n", DEVNAME(sc
));
1968 free(cfg
, M_DEVBUF
);
1974 mfi_destroy_sensors(struct mfi_softc
*sc
)
1976 if (sc
->sc_sme
== NULL
)
1978 sysmon_envsys_unregister(sc
->sc_sme
);
1980 free(sc
->sc_sensor
, M_DEVBUF
);
1985 mfi_create_sensors(struct mfi_softc
*sc
)
1988 int nsensors
= sc
->sc_ld_cnt
;
1990 sc
->sc_sme
= sysmon_envsys_create();
1991 sc
->sc_sensor
= malloc(sizeof(envsys_data_t
) * nsensors
,
1992 M_DEVBUF
, M_NOWAIT
| M_ZERO
);
1993 if (sc
->sc_sensor
== NULL
) {
1994 aprint_error("%s: can't allocate envsys_data_t\n",
1999 for (i
= 0; i
< nsensors
; i
++) {
2000 sc
->sc_sensor
[i
].units
= ENVSYS_DRIVE
;
2001 sc
->sc_sensor
[i
].monitor
= true;
2002 /* Enable monitoring for drive state changes */
2003 sc
->sc_sensor
[i
].flags
|= ENVSYS_FMONSTCHANGED
;
2004 /* logical drives */
2005 snprintf(sc
->sc_sensor
[i
].desc
,
2006 sizeof(sc
->sc_sensor
[i
].desc
), "%s:%d",
2008 if (sysmon_envsys_sensor_attach(sc
->sc_sme
,
2013 sc
->sc_sme
->sme_name
= DEVNAME(sc
);
2014 sc
->sc_sme
->sme_cookie
= sc
;
2015 sc
->sc_sme
->sme_refresh
= mfi_sensor_refresh
;
2016 if (sysmon_envsys_register(sc
->sc_sme
)) {
2017 aprint_error("%s: unable to register with sysmon\n",
2024 free(sc
->sc_sensor
, M_DEVBUF
);
2025 sysmon_envsys_destroy(sc
->sc_sme
);
2030 mfi_sensor_refresh(struct sysmon_envsys
*sme
, envsys_data_t
*edata
)
2032 struct mfi_softc
*sc
= sme
->sme_cookie
;
2037 if (edata
->sensor
>= sc
->sc_ld_cnt
)
2040 memset(&bv
, 0, sizeof(bv
));
2041 bv
.bv_volid
= edata
->sensor
;
2042 KERNEL_LOCK(1, curlwp
);
2044 error
= mfi_ioctl_vol(sc
, &bv
);
2046 KERNEL_UNLOCK_ONE(curlwp
);
2050 switch(bv
.bv_status
) {
2051 case BIOC_SVOFFLINE
:
2052 edata
->value_cur
= ENVSYS_DRIVE_FAIL
;
2053 edata
->state
= ENVSYS_SCRITICAL
;
2056 case BIOC_SVDEGRADED
:
2057 edata
->value_cur
= ENVSYS_DRIVE_PFAIL
;
2058 edata
->state
= ENVSYS_SCRITICAL
;
2063 edata
->value_cur
= ENVSYS_DRIVE_ONLINE
;
2064 edata
->state
= ENVSYS_SVALID
;
2067 case BIOC_SVINVALID
:
2070 edata
->value_cur
= 0; /* unknown */
2071 edata
->state
= ENVSYS_SINVALID
;
2075 #endif /* NBIO > 0 */
2078 mfi_xscale_fw_state(struct mfi_softc
*sc
)
2080 return mfi_read(sc
, MFI_OMSG0
);
2084 mfi_xscale_intr_dis(struct mfi_softc
*sc
)
2086 mfi_write(sc
, MFI_OMSK
, 0);
2090 mfi_xscale_intr_ena(struct mfi_softc
*sc
)
2092 mfi_write(sc
, MFI_OMSK
, MFI_ENABLE_INTR
);
2096 mfi_xscale_intr(struct mfi_softc
*sc
)
2100 status
= mfi_read(sc
, MFI_OSTS
);
2101 if (!ISSET(status
, MFI_OSTS_INTR_VALID
))
2104 /* write status back to acknowledge interrupt */
2105 mfi_write(sc
, MFI_OSTS
, status
);
2110 mfi_xscale_post(struct mfi_softc
*sc
, struct mfi_ccb
*ccb
)
2112 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_frames
),
2113 ccb
->ccb_pframe
- MFIMEM_DVA(sc
->sc_frames
),
2114 sc
->sc_frames_size
, BUS_DMASYNC_PREREAD
| BUS_DMASYNC_PREWRITE
);
2115 bus_dmamap_sync(sc
->sc_dmat
, MFIMEM_MAP(sc
->sc_sense
),
2116 ccb
->ccb_psense
- MFIMEM_DVA(sc
->sc_sense
),
2117 MFI_SENSE_SIZE
, BUS_DMASYNC_PREREAD
);
2119 mfi_write(sc
, MFI_IQP
, (ccb
->ccb_pframe
>> 3) |
2120 ccb
->ccb_extra_frames
);
2124 mfi_ppc_fw_state(struct mfi_softc
*sc
)
2126 return mfi_read(sc
, MFI_OSP
);
2130 mfi_ppc_intr_dis(struct mfi_softc
*sc
)
2132 /* Taking a wild guess --dyoung */
2133 mfi_write(sc
, MFI_OMSK
, ~(uint32_t)0x0);
2134 mfi_write(sc
, MFI_ODC
, 0xffffffff);
2138 mfi_ppc_intr_ena(struct mfi_softc
*sc
)
2140 mfi_write(sc
, MFI_ODC
, 0xffffffff);
2141 mfi_write(sc
, MFI_OMSK
, ~0x80000004);
2145 mfi_ppc_intr(struct mfi_softc
*sc
)
2149 status
= mfi_read(sc
, MFI_OSTS
);
2150 if (!ISSET(status
, MFI_OSTS_PPC_INTR_VALID
))
2153 /* write status back to acknowledge interrupt */
2154 mfi_write(sc
, MFI_ODC
, status
);
2159 mfi_ppc_post(struct mfi_softc
*sc
, struct mfi_ccb
*ccb
)
2161 mfi_write(sc
, MFI_IQP
, 0x1 | ccb
->ccb_pframe
|
2162 (ccb
->ccb_extra_frames
<< 1));