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