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