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