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