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