Bug Summary

File:dev/pci/mfii.c
Warning:line 1356, column 3
Value stored to 'state' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

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