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