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