1 1.31 andvar /* $NetBSD: mpii.c,v 1.31 2024/02/04 20:50:30 andvar Exp $ */ 2 1.15 bouyer /* $OpenBSD: mpii.c,v 1.115 2018/08/14 05:22:21 jmatthew Exp $ */ 3 1.1 bouyer /* 4 1.15 bouyer * Copyright (c) 2010, 2012 Mike Belopuhov 5 1.1 bouyer * Copyright (c) 2009 James Giannoules 6 1.1 bouyer * Copyright (c) 2005 - 2010 David Gwynne <dlg (at) openbsd.org> 7 1.1 bouyer * Copyright (c) 2005 - 2010 Marco Peereboom <marco (at) openbsd.org> 8 1.1 bouyer * 9 1.1 bouyer * Permission to use, copy, modify, and distribute this software for any 10 1.1 bouyer * purpose with or without fee is hereby granted, provided that the above 11 1.1 bouyer * copyright notice and this permission notice appear in all copies. 12 1.1 bouyer * 13 1.1 bouyer * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14 1.1 bouyer * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15 1.1 bouyer * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16 1.1 bouyer * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17 1.1 bouyer * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18 1.1 bouyer * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19 1.1 bouyer * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20 1.1 bouyer */ 21 1.1 bouyer 22 1.1 bouyer #include <sys/cdefs.h> 23 1.31 andvar __KERNEL_RCSID(0, "$NetBSD: mpii.c,v 1.31 2024/02/04 20:50:30 andvar Exp $"); 24 1.1 bouyer 25 1.1 bouyer #include "bio.h" 26 1.1 bouyer 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/device.h> 31 1.1 bouyer #include <sys/ioctl.h> 32 1.1 bouyer #include <sys/malloc.h> 33 1.1 bouyer #include <sys/kernel.h> 34 1.1 bouyer #include <sys/mutex.h> 35 1.1 bouyer #include <sys/condvar.h> 36 1.1 bouyer #include <sys/dkio.h> 37 1.1 bouyer #include <sys/tree.h> 38 1.1 bouyer 39 1.1 bouyer #include <dev/pci/pcireg.h> 40 1.1 bouyer #include <dev/pci/pcivar.h> 41 1.1 bouyer #include <dev/pci/pcidevs.h> 42 1.1 bouyer 43 1.1 bouyer #include <dev/scsipi/scsipi_all.h> 44 1.1 bouyer #include <dev/scsipi/scsi_all.h> 45 1.1 bouyer #include <dev/scsipi/scsiconf.h> 46 1.1 bouyer 47 1.13 bouyer #if NBIO > 0 48 1.1 bouyer #include <dev/biovar.h> 49 1.27 skrll #include <dev/sysmon/sysmonvar.h> 50 1.1 bouyer #include <sys/envsys.h> 51 1.13 bouyer #endif 52 1.1 bouyer 53 1.15 bouyer #include <dev/pci/mpiireg.h> 54 1.15 bouyer 55 1.15 bouyer // #define MPII_DEBUG 56 1.1 bouyer #ifdef MPII_DEBUG 57 1.1 bouyer #define DPRINTF(x...) do { if (mpii_debug) printf(x); } while(0) 58 1.1 bouyer #define DNPRINTF(n,x...) do { if (mpii_debug & (n)) printf(x); } while(0) 59 1.1 bouyer #define MPII_D_CMD (0x0001) 60 1.1 bouyer #define MPII_D_INTR (0x0002) 61 1.1 bouyer #define MPII_D_MISC (0x0004) 62 1.1 bouyer #define MPII_D_DMA (0x0008) 63 1.1 bouyer #define MPII_D_IOCTL (0x0010) 64 1.1 bouyer #define MPII_D_RW (0x0020) 65 1.1 bouyer #define MPII_D_MEM (0x0040) 66 1.1 bouyer #define MPII_D_CCB (0x0080) 67 1.1 bouyer #define MPII_D_PPR (0x0100) 68 1.1 bouyer #define MPII_D_RAID (0x0200) 69 1.1 bouyer #define MPII_D_EVT (0x0400) 70 1.1 bouyer #define MPII_D_CFG (0x0800) 71 1.1 bouyer #define MPII_D_MAP (0x1000) 72 1.15 bouyer 73 1.1 bouyer u_int32_t mpii_debug = 0 74 1.15 bouyer // | MPII_D_CMD 75 1.15 bouyer // | MPII_D_INTR 76 1.15 bouyer // | MPII_D_MISC 77 1.15 bouyer // | MPII_D_DMA 78 1.15 bouyer // | MPII_D_IOCTL 79 1.15 bouyer // | MPII_D_RW 80 1.15 bouyer // | MPII_D_MEM 81 1.15 bouyer // | MPII_D_CCB 82 1.15 bouyer // | MPII_D_PPR 83 1.15 bouyer // | MPII_D_RAID 84 1.15 bouyer // | MPII_D_EVT 85 1.15 bouyer // | MPII_D_CFG 86 1.15 bouyer // | MPII_D_MAP 87 1.1 bouyer ; 88 1.1 bouyer #else 89 1.1 bouyer #define DPRINTF(x...) 90 1.1 bouyer #define DNPRINTF(n,x...) 91 1.1 bouyer #endif 92 1.1 bouyer 93 1.15 bouyer #define MPII_REQUEST_SIZE (512) 94 1.15 bouyer #define MPII_REQUEST_CREDIT (128) 95 1.1 bouyer 96 1.1 bouyer struct mpii_dmamem { 97 1.1 bouyer bus_dmamap_t mdm_map; 98 1.1 bouyer bus_dma_segment_t mdm_seg; 99 1.1 bouyer size_t mdm_size; 100 1.1 bouyer void *mdm_kva; 101 1.1 bouyer }; 102 1.15 bouyer #define MPII_DMA_MAP(_mdm) ((_mdm)->mdm_map) 103 1.15 bouyer #define MPII_DMA_DVA(_mdm) ((uint64_t)(_mdm)->mdm_map->dm_segs[0].ds_addr) 104 1.15 bouyer #define MPII_DMA_KVA(_mdm) ((_mdm)->mdm_kva) 105 1.1 bouyer 106 1.1 bouyer struct mpii_softc; 107 1.1 bouyer 108 1.1 bouyer struct mpii_rcb { 109 1.15 bouyer SIMPLEQ_ENTRY(mpii_rcb) rcb_link; 110 1.1 bouyer void *rcb_reply; 111 1.1 bouyer u_int32_t rcb_reply_dva; 112 1.1 bouyer }; 113 1.1 bouyer 114 1.1 bouyer SIMPLEQ_HEAD(mpii_rcb_list, mpii_rcb); 115 1.1 bouyer 116 1.1 bouyer struct mpii_device { 117 1.1 bouyer int flags; 118 1.1 bouyer #define MPII_DF_ATTACH (0x0001) 119 1.1 bouyer #define MPII_DF_DETACH (0x0002) 120 1.1 bouyer #define MPII_DF_HIDDEN (0x0004) 121 1.1 bouyer #define MPII_DF_UNUSED (0x0008) 122 1.1 bouyer #define MPII_DF_VOLUME (0x0010) 123 1.1 bouyer #define MPII_DF_VOLUME_DISK (0x0020) 124 1.1 bouyer #define MPII_DF_HOT_SPARE (0x0040) 125 1.1 bouyer short slot; 126 1.1 bouyer short percent; 127 1.1 bouyer u_int16_t dev_handle; 128 1.1 bouyer u_int16_t enclosure; 129 1.1 bouyer u_int16_t expander; 130 1.1 bouyer u_int8_t phy_num; 131 1.1 bouyer u_int8_t physical_port; 132 1.1 bouyer }; 133 1.1 bouyer 134 1.1 bouyer struct mpii_ccb { 135 1.1 bouyer struct mpii_softc *ccb_sc; 136 1.1 bouyer 137 1.1 bouyer void * ccb_cookie; 138 1.15 bouyer kmutex_t ccb_mtx; 139 1.15 bouyer kcondvar_t ccb_cv; 140 1.15 bouyer 141 1.1 bouyer bus_dmamap_t ccb_dmamap; 142 1.1 bouyer 143 1.1 bouyer bus_addr_t ccb_offset; 144 1.1 bouyer void *ccb_cmd; 145 1.1 bouyer bus_addr_t ccb_cmd_dva; 146 1.1 bouyer u_int16_t ccb_dev_handle; 147 1.15 bouyer u_int16_t ccb_smid; 148 1.1 bouyer 149 1.1 bouyer volatile enum { 150 1.1 bouyer MPII_CCB_FREE, 151 1.1 bouyer MPII_CCB_READY, 152 1.1 bouyer MPII_CCB_QUEUED, 153 1.1 bouyer MPII_CCB_TIMEOUT 154 1.1 bouyer } ccb_state; 155 1.1 bouyer 156 1.1 bouyer void (*ccb_done)(struct mpii_ccb *); 157 1.1 bouyer struct mpii_rcb *ccb_rcb; 158 1.1 bouyer 159 1.15 bouyer SIMPLEQ_ENTRY(mpii_ccb) ccb_link; 160 1.1 bouyer }; 161 1.1 bouyer 162 1.1 bouyer SIMPLEQ_HEAD(mpii_ccb_list, mpii_ccb); 163 1.1 bouyer 164 1.1 bouyer struct mpii_softc { 165 1.1 bouyer device_t sc_dev; 166 1.1 bouyer 167 1.1 bouyer pci_chipset_tag_t sc_pc; 168 1.1 bouyer pcitag_t sc_tag; 169 1.1 bouyer 170 1.1 bouyer void *sc_ih; 171 1.15 bouyer pci_intr_handle_t *sc_pihp; 172 1.1 bouyer 173 1.1 bouyer struct scsipi_adapter sc_adapt; 174 1.1 bouyer struct scsipi_channel sc_chan; 175 1.1 bouyer device_t sc_child; /* our scsibus */ 176 1.1 bouyer 177 1.15 bouyer int sc_flags; 178 1.15 bouyer #define MPII_F_RAID (1<<1) 179 1.15 bouyer #define MPII_F_SAS3 (1<<2) 180 1.15 bouyer 181 1.1 bouyer struct mpii_device **sc_devs; 182 1.15 bouyer kmutex_t sc_devs_mtx; 183 1.1 bouyer 184 1.1 bouyer bus_space_tag_t sc_iot; 185 1.1 bouyer bus_space_handle_t sc_ioh; 186 1.1 bouyer bus_size_t sc_ios; 187 1.1 bouyer bus_dma_tag_t sc_dmat; 188 1.1 bouyer 189 1.1 bouyer kmutex_t sc_req_mtx; 190 1.1 bouyer kmutex_t sc_rep_mtx; 191 1.1 bouyer 192 1.15 bouyer ushort sc_reply_size; 193 1.15 bouyer ushort sc_request_size; 194 1.15 bouyer 195 1.15 bouyer ushort sc_max_cmds; 196 1.15 bouyer ushort sc_num_reply_frames; 197 1.15 bouyer u_int sc_reply_free_qdepth; 198 1.15 bouyer u_int sc_reply_post_qdepth; 199 1.15 bouyer 200 1.15 bouyer ushort sc_chain_sge; 201 1.15 bouyer ushort sc_max_sgl; 202 1.1 bouyer 203 1.1 bouyer u_int8_t sc_ioc_event_replay; 204 1.15 bouyer 205 1.15 bouyer u_int8_t sc_porttype; 206 1.1 bouyer u_int8_t sc_max_volumes; 207 1.1 bouyer u_int16_t sc_max_devices; 208 1.1 bouyer u_int16_t sc_vd_count; 209 1.1 bouyer u_int16_t sc_vd_id_low; 210 1.1 bouyer u_int16_t sc_pd_id_start; 211 1.1 bouyer int sc_ioc_number; 212 1.1 bouyer u_int8_t sc_vf_id; 213 1.1 bouyer 214 1.1 bouyer struct mpii_ccb *sc_ccbs; 215 1.1 bouyer struct mpii_ccb_list sc_ccb_free; 216 1.1 bouyer kmutex_t sc_ccb_free_mtx; 217 1.1 bouyer kcondvar_t sc_ccb_free_cv; 218 1.1 bouyer 219 1.15 bouyer struct mpii_ccb_list sc_ccb_tmos; 220 1.15 bouyer kmutex_t sc_ssb_tmomtx; 221 1.1 bouyer struct workqueue *sc_ssb_tmowk; 222 1.15 bouyer struct work sc_ssb_tmowork; 223 1.1 bouyer 224 1.1 bouyer struct mpii_dmamem *sc_requests; 225 1.1 bouyer 226 1.1 bouyer struct mpii_dmamem *sc_replies; 227 1.1 bouyer struct mpii_rcb *sc_rcbs; 228 1.1 bouyer 229 1.1 bouyer struct mpii_dmamem *sc_reply_postq; 230 1.1 bouyer struct mpii_reply_descr *sc_reply_postq_kva; 231 1.15 bouyer u_int sc_reply_post_host_index; 232 1.1 bouyer 233 1.1 bouyer struct mpii_dmamem *sc_reply_freeq; 234 1.15 bouyer u_int sc_reply_free_host_index; 235 1.15 bouyer kmutex_t sc_reply_free_mtx; 236 1.1 bouyer 237 1.15 bouyer struct mpii_rcb_list sc_evt_sas_queue; 238 1.15 bouyer kmutex_t sc_evt_sas_mtx; 239 1.15 bouyer struct workqueue *sc_evt_sas_wq; 240 1.15 bouyer struct work sc_evt_sas_work; 241 1.15 bouyer 242 1.15 bouyer struct mpii_rcb_list sc_evt_ack_queue; 243 1.15 bouyer kmutex_t sc_evt_ack_mtx; 244 1.15 bouyer struct workqueue *sc_evt_ack_wq; 245 1.15 bouyer struct work sc_evt_ack_work; 246 1.1 bouyer 247 1.25 jnemeth #if NBIO > 0 248 1.1 bouyer struct sysmon_envsys *sc_sme; 249 1.1 bouyer envsys_data_t *sc_sensors; 250 1.25 jnemeth #endif 251 1.1 bouyer }; 252 1.1 bouyer 253 1.24 maxv static int mpii_match(device_t, cfdata_t, void *); 254 1.24 maxv static void mpii_attach(device_t, device_t, void *); 255 1.24 maxv static int mpii_detach(device_t, int); 256 1.24 maxv static void mpii_childdetached(device_t, device_t); 257 1.24 maxv static int mpii_rescan(device_t, const char *, const int *); 258 1.1 bouyer 259 1.24 maxv static int mpii_intr(void *); 260 1.1 bouyer 261 1.1 bouyer CFATTACH_DECL3_NEW(mpii, sizeof(struct mpii_softc), 262 1.1 bouyer mpii_match, mpii_attach, mpii_detach, NULL, mpii_rescan, 263 1.1 bouyer mpii_childdetached, DVF_DETACH_SHUTDOWN); 264 1.1 bouyer 265 1.24 maxv static void mpii_scsipi_request(struct scsipi_channel *, 266 1.15 bouyer scsipi_adapter_req_t, void *); 267 1.24 maxv static void mpii_scsi_cmd_done(struct mpii_ccb *); 268 1.15 bouyer 269 1.24 maxv static struct mpii_dmamem * 270 1.15 bouyer mpii_dmamem_alloc(struct mpii_softc *, size_t); 271 1.24 maxv static void mpii_dmamem_free(struct mpii_softc *, 272 1.15 bouyer struct mpii_dmamem *); 273 1.24 maxv static int mpii_alloc_ccbs(struct mpii_softc *); 274 1.24 maxv static struct mpii_ccb *mpii_get_ccb(struct mpii_softc *); 275 1.24 maxv static void mpii_put_ccb(struct mpii_softc *, struct mpii_ccb *); 276 1.24 maxv static int mpii_alloc_replies(struct mpii_softc *); 277 1.24 maxv static int mpii_alloc_queues(struct mpii_softc *); 278 1.24 maxv static void mpii_push_reply(struct mpii_softc *, struct mpii_rcb *); 279 1.24 maxv static void mpii_push_replies(struct mpii_softc *); 280 1.24 maxv 281 1.24 maxv static void mpii_scsi_cmd_tmo(void *); 282 1.24 maxv static void mpii_scsi_cmd_tmo_handler(struct work *, void *); 283 1.24 maxv static void mpii_scsi_cmd_tmo_done(struct mpii_ccb *); 284 1.24 maxv 285 1.24 maxv static int mpii_insert_dev(struct mpii_softc *, struct mpii_device *); 286 1.24 maxv static int mpii_remove_dev(struct mpii_softc *, struct mpii_device *); 287 1.24 maxv static struct mpii_device * 288 1.15 bouyer mpii_find_dev(struct mpii_softc *, u_int16_t); 289 1.15 bouyer 290 1.24 maxv static void mpii_start(struct mpii_softc *, struct mpii_ccb *); 291 1.24 maxv static int mpii_poll(struct mpii_softc *, struct mpii_ccb *); 292 1.24 maxv static void mpii_poll_done(struct mpii_ccb *); 293 1.24 maxv static struct mpii_rcb * 294 1.15 bouyer mpii_reply(struct mpii_softc *, struct mpii_reply_descr *); 295 1.15 bouyer 296 1.24 maxv static void mpii_wait(struct mpii_softc *, struct mpii_ccb *); 297 1.24 maxv static void mpii_wait_done(struct mpii_ccb *); 298 1.15 bouyer 299 1.24 maxv static void mpii_init_queues(struct mpii_softc *); 300 1.15 bouyer 301 1.24 maxv static int mpii_load_xs(struct mpii_ccb *); 302 1.24 maxv static int mpii_load_xs_sas3(struct mpii_ccb *); 303 1.15 bouyer 304 1.24 maxv static u_int32_t mpii_read(struct mpii_softc *, bus_size_t); 305 1.24 maxv static void mpii_write(struct mpii_softc *, bus_size_t, u_int32_t); 306 1.24 maxv static int mpii_wait_eq(struct mpii_softc *, bus_size_t, u_int32_t, 307 1.1 bouyer u_int32_t); 308 1.24 maxv static int mpii_wait_ne(struct mpii_softc *, bus_size_t, u_int32_t, 309 1.1 bouyer u_int32_t); 310 1.1 bouyer 311 1.24 maxv static int mpii_init(struct mpii_softc *); 312 1.24 maxv static int mpii_reset_soft(struct mpii_softc *); 313 1.24 maxv static int mpii_reset_hard(struct mpii_softc *); 314 1.1 bouyer 315 1.24 maxv static int mpii_handshake_send(struct mpii_softc *, void *, size_t); 316 1.24 maxv static int mpii_handshake_recv_dword(struct mpii_softc *, 317 1.1 bouyer u_int32_t *); 318 1.24 maxv static int mpii_handshake_recv(struct mpii_softc *, void *, size_t); 319 1.1 bouyer 320 1.24 maxv static void mpii_empty_done(struct mpii_ccb *); 321 1.1 bouyer 322 1.24 maxv static int mpii_iocinit(struct mpii_softc *); 323 1.24 maxv static int mpii_iocfacts(struct mpii_softc *); 324 1.24 maxv static int mpii_portfacts(struct mpii_softc *); 325 1.24 maxv static int mpii_portenable(struct mpii_softc *); 326 1.24 maxv static int mpii_cfg_coalescing(struct mpii_softc *); 327 1.24 maxv static int mpii_board_info(struct mpii_softc *); 328 1.24 maxv static int mpii_target_map(struct mpii_softc *); 329 1.24 maxv 330 1.24 maxv static int mpii_eventnotify(struct mpii_softc *); 331 1.24 maxv static void mpii_eventnotify_done(struct mpii_ccb *); 332 1.24 maxv static void mpii_eventack(struct work *, void *); 333 1.24 maxv static void mpii_eventack_done(struct mpii_ccb *); 334 1.24 maxv static void mpii_event_process(struct mpii_softc *, struct mpii_rcb *); 335 1.24 maxv static void mpii_event_done(struct mpii_softc *, struct mpii_rcb *); 336 1.24 maxv static void mpii_event_sas(struct mpii_softc *, struct mpii_rcb *); 337 1.24 maxv static void mpii_event_sas_work(struct work *, void *); 338 1.24 maxv static void mpii_event_raid(struct mpii_softc *, 339 1.1 bouyer struct mpii_msg_event_reply *); 340 1.24 maxv static void mpii_event_discovery(struct mpii_softc *, 341 1.1 bouyer struct mpii_msg_event_reply *); 342 1.1 bouyer 343 1.24 maxv static void mpii_sas_remove_device(struct mpii_softc *, u_int16_t); 344 1.1 bouyer 345 1.24 maxv static int mpii_req_cfg_header(struct mpii_softc *, u_int8_t, 346 1.1 bouyer u_int8_t, u_int32_t, int, void *); 347 1.24 maxv static int mpii_req_cfg_page(struct mpii_softc *, u_int32_t, int, 348 1.1 bouyer void *, int, void *, size_t); 349 1.1 bouyer 350 1.1 bouyer #if 0 351 1.15 bouyer int mpii_ioctl_cache(struct scsi_link *, u_long, struct dk_cache *); 352 1.1 bouyer #endif 353 1.1 bouyer 354 1.1 bouyer #if NBIO > 0 355 1.24 maxv static int mpii_ioctl(device_t, u_long, void *); 356 1.24 maxv static int mpii_ioctl_inq(struct mpii_softc *, struct bioc_inq *); 357 1.24 maxv static int mpii_ioctl_vol(struct mpii_softc *, struct bioc_vol *); 358 1.24 maxv static int mpii_ioctl_disk(struct mpii_softc *, struct bioc_disk *); 359 1.24 maxv static int mpii_bio_hs(struct mpii_softc *, struct bioc_disk *, int, 360 1.1 bouyer int, int *); 361 1.24 maxv static int mpii_bio_disk(struct mpii_softc *, struct bioc_disk *, 362 1.1 bouyer u_int8_t); 363 1.24 maxv static struct mpii_device * 364 1.15 bouyer mpii_find_vol(struct mpii_softc *, int); 365 1.15 bouyer #ifndef SMALL_KERNEL 366 1.24 maxv static int mpii_bio_volstate(struct mpii_softc *, struct bioc_vol *); 367 1.24 maxv static int mpii_create_sensors(struct mpii_softc *); 368 1.24 maxv static void mpii_refresh_sensors(struct sysmon_envsys *, envsys_data_t *); 369 1.24 maxv static int mpii_destroy_sensors(struct mpii_softc *); 370 1.15 bouyer #endif /* SMALL_KERNEL */ 371 1.1 bouyer #endif /* NBIO > 0 */ 372 1.1 bouyer 373 1.15 bouyer #define DEVNAME(s) (device_xname((s)->sc_dev)) 374 1.1 bouyer 375 1.1 bouyer #define dwordsof(s) (sizeof(s) / sizeof(u_int32_t)) 376 1.1 bouyer 377 1.1 bouyer #define mpii_read_db(s) mpii_read((s), MPII_DOORBELL) 378 1.1 bouyer #define mpii_write_db(s, v) mpii_write((s), MPII_DOORBELL, (v)) 379 1.1 bouyer #define mpii_read_intr(s) mpii_read((s), MPII_INTR_STATUS) 380 1.1 bouyer #define mpii_write_intr(s, v) mpii_write((s), MPII_INTR_STATUS, (v)) 381 1.1 bouyer #define mpii_reply_waiting(s) ((mpii_read_intr((s)) & MPII_INTR_STATUS_REPLY)\ 382 1.1 bouyer == MPII_INTR_STATUS_REPLY) 383 1.1 bouyer 384 1.15 bouyer #define mpii_write_reply_free(s, v) \ 385 1.15 bouyer bus_space_write_4((s)->sc_iot, (s)->sc_ioh, \ 386 1.15 bouyer MPII_REPLY_FREE_HOST_INDEX, (v)) 387 1.15 bouyer #define mpii_write_reply_post(s, v) \ 388 1.15 bouyer bus_space_write_4((s)->sc_iot, (s)->sc_ioh, \ 389 1.15 bouyer MPII_REPLY_POST_HOST_INDEX, (v)) 390 1.1 bouyer 391 1.1 bouyer #define mpii_wait_db_int(s) mpii_wait_ne((s), MPII_INTR_STATUS, \ 392 1.1 bouyer MPII_INTR_STATUS_IOC2SYSDB, 0) 393 1.1 bouyer #define mpii_wait_db_ack(s) mpii_wait_eq((s), MPII_INTR_STATUS, \ 394 1.1 bouyer MPII_INTR_STATUS_SYS2IOCDB, 0) 395 1.1 bouyer 396 1.15 bouyer static inline void 397 1.15 bouyer mpii_dvatosge(struct mpii_sge *sge, u_int64_t dva) 398 1.15 bouyer { 399 1.15 bouyer sge->sg_addr_lo = htole32(dva); 400 1.15 bouyer sge->sg_addr_hi = htole32(dva >> 32); 401 1.15 bouyer } 402 1.15 bouyer 403 1.1 bouyer #define MPII_PG_EXTENDED (1<<0) 404 1.1 bouyer #define MPII_PG_POLL (1<<1) 405 1.1 bouyer #define MPII_PG_FMT "\020" "\002POLL" "\001EXTENDED" 406 1.1 bouyer 407 1.1 bouyer static const struct mpii_pci_product { 408 1.1 bouyer pci_vendor_id_t mpii_vendor; 409 1.1 bouyer pci_product_id_t mpii_product; 410 1.1 bouyer } mpii_devices[] = { 411 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2004 }, 412 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2008 }, 413 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2108_3 }, 414 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2108_4 }, 415 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2108_5 }, 416 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2116_1 }, 417 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2116_2 }, 418 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2208_1 }, 419 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2208_2 }, 420 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2208_3 }, 421 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2208_4 }, 422 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2208_5 }, 423 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2208_6 }, 424 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2308_1 }, 425 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2308_2 }, 426 1.1 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS2308_3 }, 427 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3004 }, 428 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3008 }, 429 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3108_1 }, 430 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3108_2 }, 431 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3108_3 }, 432 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3108_4 }, 433 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3408 }, 434 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3416 }, 435 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3508 }, 436 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3508_1 }, 437 1.15 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3516 }, 438 1.17 bouyer { PCI_VENDOR_SYMBIOS, PCI_PRODUCT_SYMBIOS_SAS3516_1 }, 439 1.17 bouyer { 0, 0} 440 1.1 bouyer }; 441 1.1 bouyer 442 1.24 maxv static int 443 1.1 bouyer mpii_match(device_t parent, cfdata_t match, void *aux) 444 1.1 bouyer { 445 1.1 bouyer struct pci_attach_args *pa = aux; 446 1.1 bouyer const struct mpii_pci_product *mpii; 447 1.1 bouyer 448 1.27 skrll for (mpii = mpii_devices; mpii->mpii_vendor != 0; mpii++) { 449 1.27 skrll if (PCI_VENDOR(pa->pa_id) == mpii->mpii_vendor && 450 1.27 skrll PCI_PRODUCT(pa->pa_id) == mpii->mpii_product) 451 1.27 skrll return (1); 452 1.1 bouyer } 453 1.1 bouyer return (0); 454 1.1 bouyer } 455 1.1 bouyer 456 1.24 maxv static void 457 1.1 bouyer mpii_attach(device_t parent, device_t self, void *aux) 458 1.1 bouyer { 459 1.1 bouyer struct mpii_softc *sc = device_private(self); 460 1.1 bouyer struct pci_attach_args *pa = aux; 461 1.1 bouyer pcireg_t memtype; 462 1.1 bouyer int r; 463 1.1 bouyer struct mpii_ccb *ccb; 464 1.1 bouyer struct scsipi_adapter *adapt = &sc->sc_adapt; 465 1.1 bouyer struct scsipi_channel *chan = &sc->sc_chan; 466 1.5 christos char intrbuf[PCI_INTRSTR_LEN]; 467 1.15 bouyer const char *intrstr; 468 1.1 bouyer 469 1.1 bouyer pci_aprint_devinfo(pa, NULL); 470 1.1 bouyer 471 1.1 bouyer sc->sc_pc = pa->pa_pc; 472 1.1 bouyer sc->sc_tag = pa->pa_tag; 473 1.1 bouyer sc->sc_dmat = pa->pa_dmat; 474 1.1 bouyer sc->sc_dev = self; 475 1.15 bouyer 476 1.1 bouyer mutex_init(&sc->sc_req_mtx, MUTEX_DEFAULT, IPL_BIO); 477 1.1 bouyer mutex_init(&sc->sc_rep_mtx, MUTEX_DEFAULT, IPL_BIO); 478 1.1 bouyer 479 1.1 bouyer /* find the appropriate memory base */ 480 1.1 bouyer for (r = PCI_MAPREG_START; r < PCI_MAPREG_END; r += sizeof(memtype)) { 481 1.1 bouyer memtype = pci_mapreg_type(sc->sc_pc, sc->sc_tag, r); 482 1.26 skrll if (PCI_MAPREG_TYPE(memtype) == PCI_MAPREG_TYPE_MEM) 483 1.1 bouyer break; 484 1.1 bouyer } 485 1.1 bouyer if (r >= PCI_MAPREG_END) { 486 1.1 bouyer aprint_error_dev(self, 487 1.1 bouyer "unable to locate system interface registers\n"); 488 1.1 bouyer return; 489 1.1 bouyer } 490 1.1 bouyer 491 1.1 bouyer if (pci_mapreg_map(pa, r, memtype, 0, &sc->sc_iot, &sc->sc_ioh, 492 1.1 bouyer NULL, &sc->sc_ios) != 0) { 493 1.1 bouyer aprint_error_dev(self, 494 1.1 bouyer "unable to map system interface registers\n"); 495 1.1 bouyer return; 496 1.1 bouyer } 497 1.1 bouyer 498 1.1 bouyer /* disable the expansion rom */ 499 1.15 bouyer pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_MAPREG_ROM, 500 1.15 bouyer pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_MAPREG_ROM) & 501 1.15 bouyer ~PCI_MAPREG_ROM_ENABLE); 502 1.1 bouyer 503 1.1 bouyer /* disable interrupts */ 504 1.1 bouyer mpii_write(sc, MPII_INTR_MASK, 505 1.1 bouyer MPII_INTR_MASK_RESET | MPII_INTR_MASK_REPLY | 506 1.1 bouyer MPII_INTR_MASK_DOORBELL); 507 1.1 bouyer 508 1.1 bouyer /* hook up the interrupt */ 509 1.15 bouyer if (pci_intr_alloc(pa, &sc->sc_pihp, NULL, 0)) { 510 1.1 bouyer aprint_error_dev(self, "unable to map interrupt\n"); 511 1.1 bouyer goto unmap; 512 1.1 bouyer } 513 1.15 bouyer intrstr = pci_intr_string(pa->pa_pc, sc->sc_pihp[0], 514 1.15 bouyer intrbuf, sizeof(intrbuf)); 515 1.15 bouyer pci_intr_setattr(pa->pa_pc, &sc->sc_pihp[0], PCI_INTR_MPSAFE, true); 516 1.15 bouyer sc->sc_ih = pci_intr_establish_xname(pa->pa_pc, sc->sc_pihp[0], IPL_BIO, 517 1.15 bouyer mpii_intr, sc, device_xname(self)); 518 1.15 bouyer if (sc->sc_ih == NULL) { 519 1.15 bouyer aprint_error_dev(self, "couldn't establish interrupt"); 520 1.15 bouyer if (intrstr != NULL) 521 1.15 bouyer aprint_error(" at %s", intrstr); 522 1.15 bouyer aprint_error("\n"); 523 1.15 bouyer return; 524 1.15 bouyer } 525 1.15 bouyer aprint_normal_dev(self, "interrupting at %s\n", intrstr); 526 1.15 bouyer aprint_naive("\n"); 527 1.1 bouyer 528 1.15 bouyer if (mpii_iocfacts(sc) != 0) { 529 1.15 bouyer aprint_error_dev(self, "unable to get iocfacts\n"); 530 1.1 bouyer goto unmap; 531 1.1 bouyer } 532 1.1 bouyer 533 1.15 bouyer if (mpii_init(sc) != 0) { 534 1.15 bouyer aprint_error_dev(self, "unable to initialize ioc\n"); 535 1.1 bouyer goto unmap; 536 1.1 bouyer } 537 1.1 bouyer 538 1.1 bouyer if (mpii_alloc_ccbs(sc) != 0) { 539 1.1 bouyer /* error already printed */ 540 1.1 bouyer goto unmap; 541 1.1 bouyer } 542 1.1 bouyer 543 1.1 bouyer if (mpii_alloc_replies(sc) != 0) { 544 1.1 bouyer aprint_error_dev(self, "unable to allocated reply space\n"); 545 1.1 bouyer goto free_ccbs; 546 1.1 bouyer } 547 1.1 bouyer 548 1.1 bouyer if (mpii_alloc_queues(sc) != 0) { 549 1.1 bouyer aprint_error_dev(self, "unable to allocate reply queues\n"); 550 1.1 bouyer goto free_replies; 551 1.1 bouyer } 552 1.1 bouyer 553 1.1 bouyer if (mpii_iocinit(sc) != 0) { 554 1.1 bouyer aprint_error_dev(self, "unable to send iocinit\n"); 555 1.1 bouyer goto free_queues; 556 1.1 bouyer } 557 1.1 bouyer 558 1.1 bouyer if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE, 559 1.1 bouyer MPII_DOORBELL_STATE_OPER) != 0) { 560 1.1 bouyer aprint_error_dev(self, "state: 0x%08x\n", 561 1.1 bouyer mpii_read_db(sc) & MPII_DOORBELL_STATE); 562 1.1 bouyer aprint_error_dev(self, "operational state timeout\n"); 563 1.1 bouyer goto free_queues; 564 1.1 bouyer } 565 1.1 bouyer 566 1.1 bouyer mpii_push_replies(sc); 567 1.1 bouyer mpii_init_queues(sc); 568 1.1 bouyer 569 1.15 bouyer if (mpii_board_info(sc) != 0) { 570 1.15 bouyer aprint_error_dev(self, "unable to get manufacturing page 0\n"); 571 1.15 bouyer goto free_queues; 572 1.15 bouyer } 573 1.15 bouyer 574 1.1 bouyer if (mpii_portfacts(sc) != 0) { 575 1.1 bouyer aprint_error_dev(self, "unable to get portfacts\n"); 576 1.1 bouyer goto free_queues; 577 1.1 bouyer } 578 1.1 bouyer 579 1.15 bouyer if (mpii_target_map(sc) != 0) { 580 1.15 bouyer aprint_error_dev(self, "unable to setup target mappings\n"); 581 1.1 bouyer goto free_queues; 582 1.1 bouyer } 583 1.1 bouyer 584 1.1 bouyer if (mpii_cfg_coalescing(sc) != 0) { 585 1.1 bouyer aprint_error_dev(self, "unable to configure coalescing\n"); 586 1.1 bouyer goto free_queues; 587 1.1 bouyer } 588 1.1 bouyer 589 1.1 bouyer /* XXX bail on unsupported porttype? */ 590 1.1 bouyer if ((sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_PHYSICAL) || 591 1.15 bouyer (sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_SAS_VIRTUAL) || 592 1.15 bouyer (sc->sc_porttype == MPII_PORTFACTS_PORTTYPE_TRI_MODE)) { 593 1.1 bouyer if (mpii_eventnotify(sc) != 0) { 594 1.1 bouyer aprint_error_dev(self, "unable to enable events\n"); 595 1.1 bouyer goto free_queues; 596 1.1 bouyer } 597 1.1 bouyer } 598 1.1 bouyer 599 1.15 bouyer mutex_init(&sc->sc_devs_mtx, MUTEX_DEFAULT, IPL_BIO); 600 1.15 bouyer sc->sc_devs = malloc(sc->sc_max_devices * sizeof(struct mpii_device *), 601 1.23 chs M_DEVBUF, M_WAITOK | M_ZERO); 602 1.1 bouyer 603 1.1 bouyer if (mpii_portenable(sc) != 0) { 604 1.1 bouyer aprint_error_dev(self, "unable to enable port\n"); 605 1.15 bouyer goto free_devs; 606 1.1 bouyer } 607 1.1 bouyer 608 1.15 bouyer /* we should be good to go now, attach scsibus */ 609 1.1 bouyer memset(adapt, 0, sizeof(*adapt)); 610 1.1 bouyer adapt->adapt_dev = sc->sc_dev; 611 1.1 bouyer adapt->adapt_nchannels = 1; 612 1.15 bouyer adapt->adapt_openings = sc->sc_max_cmds - 4; 613 1.1 bouyer adapt->adapt_max_periph = adapt->adapt_openings; 614 1.1 bouyer adapt->adapt_request = mpii_scsipi_request; 615 1.15 bouyer adapt->adapt_minphys = minphys; 616 1.16 bouyer adapt->adapt_flags = SCSIPI_ADAPT_MPSAFE; 617 1.1 bouyer 618 1.1 bouyer memset(chan, 0, sizeof(*chan)); 619 1.1 bouyer chan->chan_adapter = adapt; 620 1.1 bouyer chan->chan_bustype = &scsi_sas_bustype; 621 1.27 skrll chan->chan_channel = 0; 622 1.1 bouyer chan->chan_flags = 0; 623 1.2 kardel chan->chan_nluns = 8; 624 1.1 bouyer chan->chan_ntargets = sc->sc_max_devices; 625 1.1 bouyer chan->chan_id = -1; 626 1.1 bouyer 627 1.28 thorpej mpii_rescan(self, NULL, NULL); 628 1.1 bouyer 629 1.1 bouyer /* enable interrupts */ 630 1.1 bouyer mpii_write(sc, MPII_INTR_MASK, MPII_INTR_MASK_DOORBELL 631 1.1 bouyer | MPII_INTR_MASK_RESET); 632 1.1 bouyer 633 1.1 bouyer #if NBIO > 0 634 1.1 bouyer if (ISSET(sc->sc_flags, MPII_F_RAID)) { 635 1.1 bouyer if (bio_register(sc->sc_dev, mpii_ioctl) != 0) 636 1.1 bouyer panic("%s: controller registration failed", 637 1.1 bouyer DEVNAME(sc)); 638 1.1 bouyer if (mpii_create_sensors(sc) != 0) 639 1.1 bouyer aprint_error_dev(self, "unable to create sensors\n"); 640 1.1 bouyer } 641 1.1 bouyer #endif 642 1.1 bouyer 643 1.1 bouyer return; 644 1.1 bouyer 645 1.15 bouyer free_devs: 646 1.15 bouyer free(sc->sc_devs, M_DEVBUF); 647 1.15 bouyer sc->sc_devs = NULL; 648 1.1 bouyer 649 1.1 bouyer free_queues: 650 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq), 651 1.15 bouyer 0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD); 652 1.1 bouyer mpii_dmamem_free(sc, sc->sc_reply_freeq); 653 1.1 bouyer 654 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq), 655 1.1 bouyer 0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD); 656 1.1 bouyer mpii_dmamem_free(sc, sc->sc_reply_postq); 657 1.1 bouyer 658 1.1 bouyer free_replies: 659 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies), 660 1.1 bouyer 0, PAGE_SIZE, BUS_DMASYNC_POSTREAD); 661 1.1 bouyer mpii_dmamem_free(sc, sc->sc_replies); 662 1.1 bouyer 663 1.1 bouyer free_ccbs: 664 1.15 bouyer while ((ccb = mpii_get_ccb(sc)) != NULL) 665 1.1 bouyer bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 666 1.1 bouyer mpii_dmamem_free(sc, sc->sc_requests); 667 1.1 bouyer free(sc->sc_ccbs, M_DEVBUF); 668 1.1 bouyer 669 1.1 bouyer unmap: 670 1.1 bouyer bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 671 1.1 bouyer sc->sc_ios = 0; 672 1.1 bouyer } 673 1.1 bouyer 674 1.24 maxv static int 675 1.1 bouyer mpii_detach(device_t self, int flags) 676 1.1 bouyer { 677 1.15 bouyer struct mpii_softc *sc = device_private(self); 678 1.1 bouyer int error; 679 1.1 bouyer struct mpii_ccb *ccb; 680 1.1 bouyer 681 1.1 bouyer if ((error = config_detach_children(sc->sc_dev, flags)) != 0) 682 1.1 bouyer return error; 683 1.1 bouyer 684 1.1 bouyer #if NBIO > 0 685 1.1 bouyer mpii_destroy_sensors(sc); 686 1.1 bouyer bio_unregister(sc->sc_dev); 687 1.1 bouyer #endif /* NBIO > 0 */ 688 1.1 bouyer 689 1.1 bouyer if (sc->sc_ih != NULL) { 690 1.15 bouyer pci_intr_disestablish(sc->sc_pc, sc->sc_ih); 691 1.15 bouyer sc->sc_ih = NULL; 692 1.15 bouyer } 693 1.15 bouyer if (sc->sc_ios != 0) { 694 1.15 bouyer bus_space_unmap(sc->sc_iot, sc->sc_ioh, sc->sc_ios); 695 1.15 bouyer free(sc->sc_devs, M_DEVBUF); 696 1.15 bouyer sc->sc_devs = NULL; 697 1.1 bouyer 698 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_freeq), 699 1.1 bouyer 0, sc->sc_reply_free_qdepth * 4, BUS_DMASYNC_POSTREAD); 700 1.1 bouyer mpii_dmamem_free(sc, sc->sc_reply_freeq); 701 1.1 bouyer 702 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq), 703 1.1 bouyer 0, sc->sc_reply_post_qdepth * 8, BUS_DMASYNC_POSTREAD); 704 1.1 bouyer mpii_dmamem_free(sc, sc->sc_reply_postq); 705 1.1 bouyer 706 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies), 707 1.1 bouyer 0, PAGE_SIZE, BUS_DMASYNC_POSTREAD); 708 1.1 bouyer mpii_dmamem_free(sc, sc->sc_replies); 709 1.1 bouyer 710 1.15 bouyer while ((ccb = mpii_get_ccb(sc)) != NULL) 711 1.1 bouyer bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 712 1.1 bouyer mpii_dmamem_free(sc, sc->sc_requests); 713 1.1 bouyer free(sc->sc_ccbs, M_DEVBUF); 714 1.1 bouyer 715 1.1 bouyer sc->sc_ios = 0; 716 1.1 bouyer } 717 1.1 bouyer 718 1.1 bouyer return (0); 719 1.1 bouyer } 720 1.1 bouyer 721 1.24 maxv static int 722 1.27 skrll mpii_rescan(device_t self, const char *ifattr, const int *locators) 723 1.1 bouyer { 724 1.1 bouyer struct mpii_softc *sc = device_private(self); 725 1.1 bouyer 726 1.1 bouyer if (sc->sc_child != NULL) 727 1.1 bouyer return 0; 728 1.1 bouyer 729 1.29 thorpej sc->sc_child = config_found(self, &sc->sc_chan, scsiprint, CFARGS_NONE); 730 1.1 bouyer 731 1.1 bouyer return 0; 732 1.1 bouyer } 733 1.1 bouyer 734 1.24 maxv static void 735 1.1 bouyer mpii_childdetached(device_t self, device_t child) 736 1.1 bouyer { 737 1.15 bouyer struct mpii_softc *sc = device_private(self); 738 1.1 bouyer 739 1.27 skrll KASSERT(self == sc->sc_dev); 740 1.15 bouyer KASSERT(child == sc->sc_child); 741 1.1 bouyer 742 1.27 skrll if (child == sc->sc_child) 743 1.27 skrll sc->sc_child = NULL; 744 1.1 bouyer } 745 1.1 bouyer 746 1.15 bouyer 747 1.24 maxv static int 748 1.1 bouyer mpii_intr(void *arg) 749 1.1 bouyer { 750 1.1 bouyer struct mpii_rcb_list evts = SIMPLEQ_HEAD_INITIALIZER(evts); 751 1.1 bouyer struct mpii_ccb_list ccbs = SIMPLEQ_HEAD_INITIALIZER(ccbs); 752 1.1 bouyer struct mpii_softc *sc = arg; 753 1.1 bouyer struct mpii_reply_descr *postq = sc->sc_reply_postq_kva, *rdp; 754 1.1 bouyer struct mpii_ccb *ccb; 755 1.1 bouyer struct mpii_rcb *rcb; 756 1.1 bouyer int smid; 757 1.15 bouyer u_int idx; 758 1.1 bouyer int rv = 0; 759 1.1 bouyer 760 1.1 bouyer mutex_enter(&sc->sc_rep_mtx); 761 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, 762 1.1 bouyer MPII_DMA_MAP(sc->sc_reply_postq), 763 1.15 bouyer 0, sc->sc_reply_post_qdepth * sizeof(*rdp), 764 1.1 bouyer BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 765 1.1 bouyer 766 1.15 bouyer idx = sc->sc_reply_post_host_index; 767 1.1 bouyer for (;;) { 768 1.15 bouyer rdp = &postq[idx]; 769 1.1 bouyer if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) == 770 1.1 bouyer MPII_REPLY_DESCR_UNUSED) 771 1.1 bouyer break; 772 1.1 bouyer if (rdp->data == 0xffffffff) { 773 1.1 bouyer /* 774 1.1 bouyer * ioc is still writing to the reply post queue 775 1.1 bouyer * race condition - bail! 776 1.1 bouyer */ 777 1.1 bouyer break; 778 1.1 bouyer } 779 1.1 bouyer 780 1.1 bouyer smid = le16toh(rdp->smid); 781 1.1 bouyer rcb = mpii_reply(sc, rdp); 782 1.1 bouyer 783 1.1 bouyer if (smid) { 784 1.1 bouyer ccb = &sc->sc_ccbs[smid - 1]; 785 1.1 bouyer ccb->ccb_state = MPII_CCB_READY; 786 1.1 bouyer ccb->ccb_rcb = rcb; 787 1.15 bouyer SIMPLEQ_INSERT_TAIL(&ccbs, ccb, ccb_link); 788 1.1 bouyer } else 789 1.15 bouyer SIMPLEQ_INSERT_TAIL(&evts, rcb, rcb_link); 790 1.15 bouyer 791 1.15 bouyer if (++idx >= sc->sc_reply_post_qdepth) 792 1.15 bouyer idx = 0; 793 1.1 bouyer 794 1.1 bouyer rv = 1; 795 1.1 bouyer } 796 1.1 bouyer 797 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, 798 1.1 bouyer MPII_DMA_MAP(sc->sc_reply_postq), 799 1.15 bouyer 0, sc->sc_reply_post_qdepth * sizeof(*rdp), 800 1.1 bouyer BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 801 1.1 bouyer 802 1.1 bouyer if (rv) 803 1.15 bouyer mpii_write_reply_post(sc, sc->sc_reply_post_host_index = idx); 804 1.1 bouyer 805 1.1 bouyer mutex_exit(&sc->sc_rep_mtx); 806 1.1 bouyer 807 1.1 bouyer if (rv == 0) 808 1.1 bouyer return (0); 809 1.1 bouyer 810 1.1 bouyer while ((ccb = SIMPLEQ_FIRST(&ccbs)) != NULL) { 811 1.15 bouyer SIMPLEQ_REMOVE_HEAD(&ccbs, ccb_link); 812 1.1 bouyer ccb->ccb_done(ccb); 813 1.1 bouyer } 814 1.1 bouyer while ((rcb = SIMPLEQ_FIRST(&evts)) != NULL) { 815 1.15 bouyer SIMPLEQ_REMOVE_HEAD(&evts, rcb_link); 816 1.1 bouyer mpii_event_process(sc, rcb); 817 1.1 bouyer } 818 1.1 bouyer 819 1.1 bouyer return (1); 820 1.1 bouyer } 821 1.1 bouyer 822 1.24 maxv static int 823 1.15 bouyer mpii_load_xs_sas3(struct mpii_ccb *ccb) 824 1.1 bouyer { 825 1.1 bouyer struct mpii_softc *sc = ccb->ccb_sc; 826 1.1 bouyer struct scsipi_xfer *xs = ccb->ccb_cookie; 827 1.15 bouyer struct mpii_msg_scsi_io *io = ccb->ccb_cmd; 828 1.15 bouyer struct mpii_ieee_sge *csge, *nsge, *sge; 829 1.1 bouyer bus_dmamap_t dmap = ccb->ccb_dmamap; 830 1.1 bouyer int i, error; 831 1.1 bouyer 832 1.15 bouyer /* Request frame structure is described in the mpii_iocfacts */ 833 1.15 bouyer nsge = (struct mpii_ieee_sge *)(io + 1); 834 1.15 bouyer csge = nsge + sc->sc_chain_sge; 835 1.15 bouyer 836 1.1 bouyer /* zero length transfer still requires an SGE */ 837 1.1 bouyer if (xs->datalen == 0) { 838 1.15 bouyer nsge->sg_flags = MPII_IEEE_SGE_END_OF_LIST; 839 1.1 bouyer return (0); 840 1.1 bouyer } 841 1.1 bouyer 842 1.15 bouyer error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL, 843 1.15 bouyer (xs->xs_control & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 844 1.1 bouyer if (error) { 845 1.15 bouyer printf("%s: error %d loading dmamap\n", DEVNAME(sc), error); 846 1.1 bouyer return (1); 847 1.1 bouyer } 848 1.1 bouyer 849 1.15 bouyer sge = nsge; 850 1.15 bouyer for (i = 0; i < dmap->dm_nsegs; i++, nsge++) { 851 1.15 bouyer if (nsge == csge) { 852 1.15 bouyer nsge++; 853 1.15 bouyer /* offset to the chain sge from the beginning */ 854 1.15 bouyer io->chain_offset = ((uintptr_t)csge - (uintptr_t)io) / 4; 855 1.15 bouyer csge->sg_flags = MPII_IEEE_SGE_CHAIN_ELEMENT | 856 1.15 bouyer MPII_IEEE_SGE_ADDR_SYSTEM; 857 1.15 bouyer /* address of the next sge */ 858 1.15 bouyer csge->sg_addr = htole64(ccb->ccb_cmd_dva + 859 1.15 bouyer ((uintptr_t)nsge - (uintptr_t)io)); 860 1.15 bouyer csge->sg_len = htole32((dmap->dm_nsegs - i) * 861 1.15 bouyer sizeof(*sge)); 862 1.15 bouyer } 863 1.1 bouyer 864 1.15 bouyer sge = nsge; 865 1.15 bouyer sge->sg_flags = MPII_IEEE_SGE_ADDR_SYSTEM; 866 1.15 bouyer sge->sg_len = htole32(dmap->dm_segs[i].ds_len); 867 1.15 bouyer sge->sg_addr = htole64(dmap->dm_segs[i].ds_addr); 868 1.1 bouyer } 869 1.1 bouyer 870 1.15 bouyer /* terminate list */ 871 1.15 bouyer sge->sg_flags |= MPII_IEEE_SGE_END_OF_LIST; 872 1.1 bouyer 873 1.15 bouyer bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 874 1.15 bouyer (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD : 875 1.15 bouyer BUS_DMASYNC_PREWRITE); 876 1.1 bouyer 877 1.15 bouyer return (0); 878 1.15 bouyer } 879 1.1 bouyer 880 1.24 maxv static int 881 1.15 bouyer mpii_load_xs(struct mpii_ccb *ccb) 882 1.15 bouyer { 883 1.15 bouyer struct mpii_softc *sc = ccb->ccb_sc; 884 1.15 bouyer struct scsipi_xfer *xs = ccb->ccb_cookie; 885 1.15 bouyer struct mpii_msg_scsi_io *io = ccb->ccb_cmd; 886 1.15 bouyer struct mpii_sge *csge, *nsge, *sge; 887 1.15 bouyer bus_dmamap_t dmap = ccb->ccb_dmamap; 888 1.15 bouyer u_int32_t flags; 889 1.15 bouyer u_int16_t len; 890 1.15 bouyer int i, error; 891 1.1 bouyer 892 1.15 bouyer /* Request frame structure is described in the mpii_iocfacts */ 893 1.15 bouyer nsge = (struct mpii_sge *)(io + 1); 894 1.15 bouyer csge = nsge + sc->sc_chain_sge; 895 1.1 bouyer 896 1.15 bouyer /* zero length transfer still requires an SGE */ 897 1.15 bouyer if (xs->datalen == 0) { 898 1.15 bouyer nsge->sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE | 899 1.15 bouyer MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL); 900 1.15 bouyer return (0); 901 1.15 bouyer } 902 1.15 bouyer 903 1.15 bouyer error = bus_dmamap_load(sc->sc_dmat, dmap, xs->data, xs->datalen, NULL, 904 1.15 bouyer (xs->xs_control & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 905 1.15 bouyer if (error) { 906 1.15 bouyer printf("%s: error %d loading dmamap\n", DEVNAME(sc), error); 907 1.15 bouyer return (1); 908 1.15 bouyer } 909 1.1 bouyer 910 1.15 bouyer /* safe default starting flags */ 911 1.15 bouyer flags = MPII_SGE_FL_TYPE_SIMPLE | MPII_SGE_FL_SIZE_64; 912 1.15 bouyer if (xs->xs_control & XS_CTL_DATA_OUT) 913 1.15 bouyer flags |= MPII_SGE_FL_DIR_OUT; 914 1.15 bouyer 915 1.15 bouyer sge = nsge; 916 1.15 bouyer for (i = 0; i < dmap->dm_nsegs; i++, nsge++) { 917 1.15 bouyer if (nsge == csge) { 918 1.15 bouyer nsge++; 919 1.15 bouyer /* offset to the chain sge from the beginning */ 920 1.15 bouyer io->chain_offset = ((uintptr_t)csge - (uintptr_t)io) / 4; 921 1.15 bouyer /* length of the sgl segment we're pointing to */ 922 1.15 bouyer len = (dmap->dm_nsegs - i) * sizeof(*sge); 923 1.15 bouyer csge->sg_hdr = htole32(MPII_SGE_FL_TYPE_CHAIN | 924 1.15 bouyer MPII_SGE_FL_SIZE_64 | len); 925 1.15 bouyer /* address of the next sge */ 926 1.15 bouyer mpii_dvatosge(csge, ccb->ccb_cmd_dva + 927 1.15 bouyer ((uintptr_t)nsge - (uintptr_t)io)); 928 1.1 bouyer } 929 1.1 bouyer 930 1.1 bouyer sge = nsge; 931 1.1 bouyer sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len); 932 1.15 bouyer mpii_dvatosge(sge, dmap->dm_segs[i].ds_addr); 933 1.1 bouyer } 934 1.1 bouyer 935 1.1 bouyer /* terminate list */ 936 1.1 bouyer sge->sg_hdr |= htole32(MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | 937 1.1 bouyer MPII_SGE_FL_EOL); 938 1.1 bouyer 939 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 940 1.1 bouyer (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD : 941 1.1 bouyer BUS_DMASYNC_PREWRITE); 942 1.1 bouyer 943 1.1 bouyer return (0); 944 1.1 bouyer } 945 1.1 bouyer 946 1.24 maxv static u_int32_t 947 1.1 bouyer mpii_read(struct mpii_softc *sc, bus_size_t r) 948 1.1 bouyer { 949 1.1 bouyer u_int32_t rv; 950 1.1 bouyer 951 1.1 bouyer bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 952 1.1 bouyer BUS_SPACE_BARRIER_READ); 953 1.1 bouyer rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r); 954 1.1 bouyer 955 1.15 bouyer DNPRINTF(MPII_D_RW, "%s: mpii_read %#lx %#x\n", DEVNAME(sc), r, rv); 956 1.1 bouyer 957 1.1 bouyer return (rv); 958 1.1 bouyer } 959 1.1 bouyer 960 1.24 maxv static void 961 1.1 bouyer mpii_write(struct mpii_softc *sc, bus_size_t r, u_int32_t v) 962 1.1 bouyer { 963 1.15 bouyer DNPRINTF(MPII_D_RW, "%s: mpii_write %#lx %#x\n", DEVNAME(sc), r, v); 964 1.1 bouyer 965 1.1 bouyer bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v); 966 1.1 bouyer bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 967 1.1 bouyer BUS_SPACE_BARRIER_WRITE); 968 1.1 bouyer } 969 1.1 bouyer 970 1.1 bouyer 971 1.24 maxv static int 972 1.1 bouyer mpii_wait_eq(struct mpii_softc *sc, bus_size_t r, u_int32_t mask, 973 1.1 bouyer u_int32_t target) 974 1.1 bouyer { 975 1.1 bouyer int i; 976 1.1 bouyer 977 1.15 bouyer DNPRINTF(MPII_D_RW, "%s: mpii_wait_eq %#lx %#x %#x\n", DEVNAME(sc), r, 978 1.15 bouyer mask, target); 979 1.1 bouyer 980 1.1 bouyer for (i = 0; i < 15000; i++) { 981 1.1 bouyer if ((mpii_read(sc, r) & mask) == target) 982 1.1 bouyer return (0); 983 1.1 bouyer delay(1000); 984 1.1 bouyer } 985 1.1 bouyer 986 1.1 bouyer return (1); 987 1.1 bouyer } 988 1.1 bouyer 989 1.24 maxv static int 990 1.1 bouyer mpii_wait_ne(struct mpii_softc *sc, bus_size_t r, u_int32_t mask, 991 1.1 bouyer u_int32_t target) 992 1.1 bouyer { 993 1.1 bouyer int i; 994 1.1 bouyer 995 1.15 bouyer DNPRINTF(MPII_D_RW, "%s: mpii_wait_ne %#lx %#x %#x\n", DEVNAME(sc), r, 996 1.15 bouyer mask, target); 997 1.1 bouyer 998 1.1 bouyer for (i = 0; i < 15000; i++) { 999 1.1 bouyer if ((mpii_read(sc, r) & mask) != target) 1000 1.1 bouyer return (0); 1001 1.1 bouyer delay(1000); 1002 1.1 bouyer } 1003 1.1 bouyer 1004 1.1 bouyer return (1); 1005 1.1 bouyer } 1006 1.1 bouyer 1007 1.24 maxv static int 1008 1.1 bouyer mpii_init(struct mpii_softc *sc) 1009 1.1 bouyer { 1010 1.1 bouyer u_int32_t db; 1011 1.1 bouyer int i; 1012 1.1 bouyer 1013 1.1 bouyer /* spin until the ioc leaves the reset state */ 1014 1.1 bouyer if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE, 1015 1.1 bouyer MPII_DOORBELL_STATE_RESET) != 0) { 1016 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_init timeout waiting to leave " 1017 1.1 bouyer "reset state\n", DEVNAME(sc)); 1018 1.1 bouyer return (1); 1019 1.1 bouyer } 1020 1.1 bouyer 1021 1.1 bouyer /* check current ownership */ 1022 1.1 bouyer db = mpii_read_db(sc); 1023 1.1 bouyer if ((db & MPII_DOORBELL_WHOINIT) == MPII_DOORBELL_WHOINIT_PCIPEER) { 1024 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_init initialised by pci peer\n", 1025 1.1 bouyer DEVNAME(sc)); 1026 1.1 bouyer return (0); 1027 1.1 bouyer } 1028 1.1 bouyer 1029 1.1 bouyer for (i = 0; i < 5; i++) { 1030 1.1 bouyer switch (db & MPII_DOORBELL_STATE) { 1031 1.1 bouyer case MPII_DOORBELL_STATE_READY: 1032 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is ready\n", 1033 1.1 bouyer DEVNAME(sc)); 1034 1.1 bouyer return (0); 1035 1.1 bouyer 1036 1.1 bouyer case MPII_DOORBELL_STATE_OPER: 1037 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is oper\n", 1038 1.1 bouyer DEVNAME(sc)); 1039 1.1 bouyer if (sc->sc_ioc_event_replay) 1040 1.1 bouyer mpii_reset_soft(sc); 1041 1.1 bouyer else 1042 1.1 bouyer mpii_reset_hard(sc); 1043 1.1 bouyer break; 1044 1.1 bouyer 1045 1.1 bouyer case MPII_DOORBELL_STATE_FAULT: 1046 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_init ioc is being " 1047 1.1 bouyer "reset hard\n" , DEVNAME(sc)); 1048 1.1 bouyer mpii_reset_hard(sc); 1049 1.1 bouyer break; 1050 1.1 bouyer 1051 1.1 bouyer case MPII_DOORBELL_STATE_RESET: 1052 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_init waiting to come " 1053 1.1 bouyer "out of reset\n", DEVNAME(sc)); 1054 1.1 bouyer if (mpii_wait_ne(sc, MPII_DOORBELL, MPII_DOORBELL_STATE, 1055 1.1 bouyer MPII_DOORBELL_STATE_RESET) != 0) 1056 1.1 bouyer return (1); 1057 1.1 bouyer break; 1058 1.1 bouyer } 1059 1.1 bouyer db = mpii_read_db(sc); 1060 1.1 bouyer } 1061 1.1 bouyer 1062 1.1 bouyer return (1); 1063 1.1 bouyer } 1064 1.1 bouyer 1065 1.24 maxv static int 1066 1.1 bouyer mpii_reset_soft(struct mpii_softc *sc) 1067 1.1 bouyer { 1068 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_reset_soft\n", DEVNAME(sc)); 1069 1.1 bouyer 1070 1.1 bouyer if (mpii_read_db(sc) & MPII_DOORBELL_INUSE) { 1071 1.1 bouyer return (1); 1072 1.1 bouyer } 1073 1.1 bouyer 1074 1.1 bouyer mpii_write_db(sc, 1075 1.1 bouyer MPII_DOORBELL_FUNCTION(MPII_FUNCTION_IOC_MESSAGE_UNIT_RESET)); 1076 1.15 bouyer 1077 1.1 bouyer /* XXX LSI waits 15 sec */ 1078 1.1 bouyer if (mpii_wait_db_ack(sc) != 0) 1079 1.1 bouyer return (1); 1080 1.1 bouyer 1081 1.1 bouyer /* XXX LSI waits 15 sec */ 1082 1.1 bouyer if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_STATE, 1083 1.1 bouyer MPII_DOORBELL_STATE_READY) != 0) 1084 1.1 bouyer return (1); 1085 1.1 bouyer 1086 1.1 bouyer /* XXX wait for Sys2IOCDB bit to clear in HIS?? */ 1087 1.1 bouyer 1088 1.1 bouyer return (0); 1089 1.1 bouyer } 1090 1.1 bouyer 1091 1.24 maxv static int 1092 1.1 bouyer mpii_reset_hard(struct mpii_softc *sc) 1093 1.1 bouyer { 1094 1.1 bouyer u_int16_t i; 1095 1.1 bouyer 1096 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard\n", DEVNAME(sc)); 1097 1.1 bouyer 1098 1.1 bouyer mpii_write_intr(sc, 0); 1099 1.1 bouyer 1100 1.1 bouyer /* enable diagnostic register */ 1101 1.1 bouyer mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_FLUSH); 1102 1.1 bouyer mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_1); 1103 1.1 bouyer mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_2); 1104 1.1 bouyer mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_3); 1105 1.1 bouyer mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_4); 1106 1.1 bouyer mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_5); 1107 1.1 bouyer mpii_write(sc, MPII_WRITESEQ, MPII_WRITESEQ_6); 1108 1.1 bouyer 1109 1.1 bouyer delay(100); 1110 1.1 bouyer 1111 1.1 bouyer if ((mpii_read(sc, MPII_HOSTDIAG) & MPII_HOSTDIAG_DWRE) == 0) { 1112 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_reset_hard failure to enable " 1113 1.1 bouyer "diagnostic read/write\n", DEVNAME(sc)); 1114 1.1 bouyer return(1); 1115 1.1 bouyer } 1116 1.1 bouyer 1117 1.1 bouyer /* reset ioc */ 1118 1.1 bouyer mpii_write(sc, MPII_HOSTDIAG, MPII_HOSTDIAG_RESET_ADAPTER); 1119 1.1 bouyer 1120 1.1 bouyer /* 240 milliseconds */ 1121 1.1 bouyer delay(240000); 1122 1.1 bouyer 1123 1.1 bouyer 1124 1.1 bouyer /* XXX this whole function should be more robust */ 1125 1.15 bouyer 1126 1.1 bouyer /* XXX read the host diagnostic reg until reset adapter bit clears ? */ 1127 1.1 bouyer for (i = 0; i < 30000; i++) { 1128 1.1 bouyer if ((mpii_read(sc, MPII_HOSTDIAG) & 1129 1.1 bouyer MPII_HOSTDIAG_RESET_ADAPTER) == 0) 1130 1.1 bouyer break; 1131 1.1 bouyer delay(10000); 1132 1.1 bouyer } 1133 1.1 bouyer 1134 1.1 bouyer /* disable diagnostic register */ 1135 1.1 bouyer mpii_write(sc, MPII_WRITESEQ, 0xff); 1136 1.1 bouyer 1137 1.1 bouyer /* XXX what else? */ 1138 1.1 bouyer 1139 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: done with mpii_reset_hard\n", DEVNAME(sc)); 1140 1.1 bouyer 1141 1.1 bouyer return(0); 1142 1.1 bouyer } 1143 1.1 bouyer 1144 1.24 maxv static int 1145 1.1 bouyer mpii_handshake_send(struct mpii_softc *sc, void *buf, size_t dwords) 1146 1.1 bouyer { 1147 1.1 bouyer u_int32_t *query = buf; 1148 1.1 bouyer int i; 1149 1.1 bouyer 1150 1.1 bouyer /* make sure the doorbell is not in use. */ 1151 1.1 bouyer if (mpii_read_db(sc) & MPII_DOORBELL_INUSE) 1152 1.1 bouyer return (1); 1153 1.1 bouyer 1154 1.1 bouyer /* clear pending doorbell interrupts */ 1155 1.1 bouyer if (mpii_read_intr(sc) & MPII_INTR_STATUS_IOC2SYSDB) 1156 1.1 bouyer mpii_write_intr(sc, 0); 1157 1.1 bouyer 1158 1.1 bouyer /* 1159 1.1 bouyer * first write the doorbell with the handshake function and the 1160 1.1 bouyer * dword count. 1161 1.1 bouyer */ 1162 1.1 bouyer mpii_write_db(sc, MPII_DOORBELL_FUNCTION(MPII_FUNCTION_HANDSHAKE) | 1163 1.1 bouyer MPII_DOORBELL_DWORDS(dwords)); 1164 1.1 bouyer 1165 1.1 bouyer /* 1166 1.1 bouyer * the doorbell used bit will be set because a doorbell function has 1167 1.1 bouyer * started. wait for the interrupt and then ack it. 1168 1.1 bouyer */ 1169 1.1 bouyer if (mpii_wait_db_int(sc) != 0) 1170 1.1 bouyer return (1); 1171 1.1 bouyer mpii_write_intr(sc, 0); 1172 1.1 bouyer 1173 1.1 bouyer /* poll for the acknowledgement. */ 1174 1.1 bouyer if (mpii_wait_db_ack(sc) != 0) 1175 1.1 bouyer return (1); 1176 1.1 bouyer 1177 1.1 bouyer /* write the query through the doorbell. */ 1178 1.1 bouyer for (i = 0; i < dwords; i++) { 1179 1.1 bouyer mpii_write_db(sc, htole32(query[i])); 1180 1.1 bouyer if (mpii_wait_db_ack(sc) != 0) 1181 1.1 bouyer return (1); 1182 1.1 bouyer } 1183 1.1 bouyer 1184 1.1 bouyer return (0); 1185 1.1 bouyer } 1186 1.1 bouyer 1187 1.24 maxv static int 1188 1.1 bouyer mpii_handshake_recv_dword(struct mpii_softc *sc, u_int32_t *dword) 1189 1.1 bouyer { 1190 1.1 bouyer u_int16_t *words = (u_int16_t *)dword; 1191 1.1 bouyer int i; 1192 1.1 bouyer 1193 1.1 bouyer for (i = 0; i < 2; i++) { 1194 1.1 bouyer if (mpii_wait_db_int(sc) != 0) 1195 1.1 bouyer return (1); 1196 1.1 bouyer words[i] = le16toh(mpii_read_db(sc) & MPII_DOORBELL_DATA_MASK); 1197 1.1 bouyer mpii_write_intr(sc, 0); 1198 1.1 bouyer } 1199 1.1 bouyer 1200 1.1 bouyer return (0); 1201 1.1 bouyer } 1202 1.1 bouyer 1203 1.24 maxv static int 1204 1.1 bouyer mpii_handshake_recv(struct mpii_softc *sc, void *buf, size_t dwords) 1205 1.1 bouyer { 1206 1.1 bouyer struct mpii_msg_reply *reply = buf; 1207 1.1 bouyer u_int32_t *dbuf = buf, dummy; 1208 1.1 bouyer int i; 1209 1.1 bouyer 1210 1.1 bouyer /* get the first dword so we can read the length out of the header. */ 1211 1.1 bouyer if (mpii_handshake_recv_dword(sc, &dbuf[0]) != 0) 1212 1.1 bouyer return (1); 1213 1.1 bouyer 1214 1.15 bouyer DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dwords: %lu reply: %d\n", 1215 1.1 bouyer DEVNAME(sc), dwords, reply->msg_length); 1216 1.1 bouyer 1217 1.1 bouyer /* 1218 1.1 bouyer * the total length, in dwords, is in the message length field of the 1219 1.1 bouyer * reply header. 1220 1.1 bouyer */ 1221 1.1 bouyer for (i = 1; i < MIN(dwords, reply->msg_length); i++) { 1222 1.1 bouyer if (mpii_handshake_recv_dword(sc, &dbuf[i]) != 0) 1223 1.1 bouyer return (1); 1224 1.1 bouyer } 1225 1.1 bouyer 1226 1.1 bouyer /* if there's extra stuff to come off the ioc, discard it */ 1227 1.1 bouyer while (i++ < reply->msg_length) { 1228 1.1 bouyer if (mpii_handshake_recv_dword(sc, &dummy) != 0) 1229 1.1 bouyer return (1); 1230 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: mpii_handshake_recv dummy read: " 1231 1.1 bouyer "0x%08x\n", DEVNAME(sc), dummy); 1232 1.1 bouyer } 1233 1.1 bouyer 1234 1.1 bouyer /* wait for the doorbell used bit to be reset and clear the intr */ 1235 1.1 bouyer if (mpii_wait_db_int(sc) != 0) 1236 1.1 bouyer return (1); 1237 1.15 bouyer 1238 1.1 bouyer if (mpii_wait_eq(sc, MPII_DOORBELL, MPII_DOORBELL_INUSE, 0) != 0) 1239 1.1 bouyer return (1); 1240 1.15 bouyer 1241 1.1 bouyer mpii_write_intr(sc, 0); 1242 1.1 bouyer 1243 1.1 bouyer return (0); 1244 1.1 bouyer } 1245 1.1 bouyer 1246 1.24 maxv static void 1247 1.1 bouyer mpii_empty_done(struct mpii_ccb *ccb) 1248 1.1 bouyer { 1249 1.1 bouyer /* nothing to do */ 1250 1.1 bouyer } 1251 1.1 bouyer 1252 1.24 maxv static int 1253 1.1 bouyer mpii_iocfacts(struct mpii_softc *sc) 1254 1.1 bouyer { 1255 1.1 bouyer struct mpii_msg_iocfacts_request ifq; 1256 1.1 bouyer struct mpii_msg_iocfacts_reply ifp; 1257 1.15 bouyer int irs; 1258 1.15 bouyer int sge_size; 1259 1.15 bouyer u_int qdepth; 1260 1.1 bouyer 1261 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts\n", DEVNAME(sc)); 1262 1.1 bouyer 1263 1.15 bouyer memset(&ifq, 0, sizeof(ifq)); 1264 1.15 bouyer memset(&ifp, 0, sizeof(ifp)); 1265 1.1 bouyer 1266 1.1 bouyer ifq.function = MPII_FUNCTION_IOC_FACTS; 1267 1.1 bouyer 1268 1.1 bouyer if (mpii_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) { 1269 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts send failed\n", 1270 1.1 bouyer DEVNAME(sc)); 1271 1.1 bouyer return (1); 1272 1.1 bouyer } 1273 1.1 bouyer 1274 1.1 bouyer if (mpii_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) { 1275 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_iocfacts recv failed\n", 1276 1.1 bouyer DEVNAME(sc)); 1277 1.1 bouyer return (1); 1278 1.1 bouyer } 1279 1.1 bouyer 1280 1.1 bouyer sc->sc_ioc_number = ifp.ioc_number; 1281 1.1 bouyer sc->sc_vf_id = ifp.vf_id; 1282 1.1 bouyer 1283 1.1 bouyer sc->sc_max_volumes = ifp.max_volumes; 1284 1.1 bouyer sc->sc_max_devices = ifp.max_volumes + le16toh(ifp.max_targets); 1285 1.1 bouyer 1286 1.1 bouyer if (ISSET(le32toh(ifp.ioc_capabilities), 1287 1.1 bouyer MPII_IOCFACTS_CAPABILITY_INTEGRATED_RAID)) 1288 1.1 bouyer SET(sc->sc_flags, MPII_F_RAID); 1289 1.15 bouyer if (ISSET(le32toh(ifp.ioc_capabilities), 1290 1.15 bouyer MPII_IOCFACTS_CAPABILITY_EVENT_REPLAY)) 1291 1.15 bouyer sc->sc_ioc_event_replay = 1; 1292 1.15 bouyer 1293 1.15 bouyer sc->sc_max_cmds = MIN(le16toh(ifp.request_credit), 1294 1.15 bouyer MPII_REQUEST_CREDIT); 1295 1.1 bouyer 1296 1.15 bouyer /* SAS3 and 3.5 controllers have different sgl layouts */ 1297 1.15 bouyer if (ifp.msg_version_maj == 2 && ((ifp.msg_version_min == 5) 1298 1.15 bouyer || (ifp.msg_version_min == 6))) 1299 1.15 bouyer SET(sc->sc_flags, MPII_F_SAS3); 1300 1.1 bouyer 1301 1.15 bouyer /* 1302 1.15 bouyer * The host driver must ensure that there is at least one 1303 1.15 bouyer * unused entry in the Reply Free Queue. One way to ensure 1304 1.15 bouyer * that this requirement is met is to never allocate a number 1305 1.15 bouyer * of reply frames that is a multiple of 16. 1306 1.15 bouyer */ 1307 1.15 bouyer sc->sc_num_reply_frames = sc->sc_max_cmds + 32; 1308 1.1 bouyer if (!(sc->sc_num_reply_frames % 16)) 1309 1.1 bouyer sc->sc_num_reply_frames--; 1310 1.1 bouyer 1311 1.1 bouyer /* must be multiple of 16 */ 1312 1.15 bouyer sc->sc_reply_post_qdepth = sc->sc_max_cmds + 1313 1.15 bouyer sc->sc_num_reply_frames; 1314 1.15 bouyer sc->sc_reply_post_qdepth += 16 - (sc->sc_reply_post_qdepth % 16); 1315 1.15 bouyer 1316 1.15 bouyer qdepth = le16toh(ifp.max_reply_descriptor_post_queue_depth); 1317 1.15 bouyer if (sc->sc_reply_post_qdepth > qdepth) { 1318 1.15 bouyer sc->sc_reply_post_qdepth = qdepth; 1319 1.15 bouyer if (sc->sc_reply_post_qdepth < 16) { 1320 1.15 bouyer printf("%s: RDPQ is too shallow\n", DEVNAME(sc)); 1321 1.15 bouyer return (1); 1322 1.15 bouyer } 1323 1.15 bouyer sc->sc_max_cmds = sc->sc_reply_post_qdepth / 2 - 4; 1324 1.15 bouyer sc->sc_num_reply_frames = sc->sc_max_cmds + 4; 1325 1.15 bouyer } 1326 1.15 bouyer 1327 1.1 bouyer sc->sc_reply_free_qdepth = sc->sc_num_reply_frames + 1328 1.15 bouyer 16 - (sc->sc_num_reply_frames % 16); 1329 1.1 bouyer 1330 1.1 bouyer /* 1331 1.15 bouyer * Our request frame for an I/O operation looks like this: 1332 1.15 bouyer * 1333 1.15 bouyer * +-------------------+ -. 1334 1.15 bouyer * | mpii_msg_scsi_io | | 1335 1.15 bouyer * +-------------------| | 1336 1.15 bouyer * | mpii_sge | | 1337 1.15 bouyer * + - - - - - - - - - + | 1338 1.15 bouyer * | ... | > ioc_request_frame_size 1339 1.15 bouyer * + - - - - - - - - - + | 1340 1.15 bouyer * | mpii_sge (tail) | | 1341 1.15 bouyer * + - - - - - - - - - + | 1342 1.15 bouyer * | mpii_sge (csge) | | --. 1343 1.15 bouyer * + - - - - - - - - - + -' | chain sge points to the next sge 1344 1.15 bouyer * | mpii_sge |<-----' 1345 1.15 bouyer * + - - - - - - - - - + 1346 1.15 bouyer * | ... | 1347 1.15 bouyer * + - - - - - - - - - + 1348 1.15 bouyer * | mpii_sge (tail) | 1349 1.15 bouyer * +-------------------+ 1350 1.15 bouyer * | | 1351 1.15 bouyer * ~~~~~~~~~~~~~~~~~~~~~ 1352 1.15 bouyer * | | 1353 1.15 bouyer * +-------------------+ <- sc_request_size - sizeof(scsi_sense_data) 1354 1.15 bouyer * | scsi_sense_data | 1355 1.15 bouyer * +-------------------+ 1356 1.1 bouyer */ 1357 1.1 bouyer 1358 1.15 bouyer /* both sizes are in 32-bit words */ 1359 1.15 bouyer sc->sc_reply_size = ifp.reply_frame_size * 4; 1360 1.15 bouyer irs = le16toh(ifp.ioc_request_frame_size) * 4; 1361 1.15 bouyer sc->sc_request_size = MPII_REQUEST_SIZE; 1362 1.15 bouyer /* make sure we have enough space for scsi sense data */ 1363 1.15 bouyer if (irs > sc->sc_request_size) { 1364 1.15 bouyer sc->sc_request_size = irs + sizeof(struct scsi_sense_data); 1365 1.15 bouyer sc->sc_request_size += 16 - (sc->sc_request_size % 16); 1366 1.15 bouyer } 1367 1.15 bouyer 1368 1.15 bouyer if (ISSET(sc->sc_flags, MPII_F_SAS3)) { 1369 1.15 bouyer sge_size = sizeof(struct mpii_ieee_sge); 1370 1.15 bouyer } else { 1371 1.15 bouyer sge_size = sizeof(struct mpii_sge); 1372 1.15 bouyer } 1373 1.1 bouyer 1374 1.15 bouyer /* offset to the chain sge */ 1375 1.15 bouyer sc->sc_chain_sge = (irs - sizeof(struct mpii_msg_scsi_io)) / 1376 1.15 bouyer sge_size - 1; 1377 1.1 bouyer 1378 1.15 bouyer /* 1379 1.15 bouyer * A number of simple scatter-gather elements we can fit into the 1380 1.15 bouyer * request buffer after the I/O command minus the chain element. 1381 1.15 bouyer */ 1382 1.15 bouyer sc->sc_max_sgl = (sc->sc_request_size - 1383 1.15 bouyer sizeof(struct mpii_msg_scsi_io) - sizeof(struct scsi_sense_data)) / 1384 1.15 bouyer sge_size - 1; 1385 1.1 bouyer 1386 1.15 bouyer return (0); 1387 1.1 bouyer } 1388 1.1 bouyer 1389 1.24 maxv static int 1390 1.1 bouyer mpii_iocinit(struct mpii_softc *sc) 1391 1.1 bouyer { 1392 1.1 bouyer struct mpii_msg_iocinit_request iiq; 1393 1.1 bouyer struct mpii_msg_iocinit_reply iip; 1394 1.1 bouyer 1395 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit\n", DEVNAME(sc)); 1396 1.1 bouyer 1397 1.15 bouyer memset(&iiq, 0, sizeof(iiq)); 1398 1.15 bouyer memset(&iip, 0, sizeof(iip)); 1399 1.1 bouyer 1400 1.1 bouyer iiq.function = MPII_FUNCTION_IOC_INIT; 1401 1.1 bouyer iiq.whoinit = MPII_WHOINIT_HOST_DRIVER; 1402 1.15 bouyer 1403 1.1 bouyer /* XXX JPG do something about vf_id */ 1404 1.1 bouyer iiq.vf_id = 0; 1405 1.1 bouyer 1406 1.1 bouyer iiq.msg_version_maj = 0x02; 1407 1.1 bouyer iiq.msg_version_min = 0x00; 1408 1.1 bouyer 1409 1.1 bouyer /* XXX JPG ensure compliance with some level and hard-code? */ 1410 1.1 bouyer iiq.hdr_version_unit = 0x00; 1411 1.1 bouyer iiq.hdr_version_dev = 0x00; 1412 1.1 bouyer 1413 1.15 bouyer iiq.system_request_frame_size = htole16(sc->sc_request_size / 4); 1414 1.1 bouyer 1415 1.1 bouyer iiq.reply_descriptor_post_queue_depth = 1416 1.1 bouyer htole16(sc->sc_reply_post_qdepth); 1417 1.1 bouyer 1418 1.1 bouyer iiq.reply_free_queue_depth = htole16(sc->sc_reply_free_qdepth); 1419 1.1 bouyer 1420 1.15 bouyer iiq.sense_buffer_address_high = 1421 1.15 bouyer htole32(MPII_DMA_DVA(sc->sc_requests) >> 32); 1422 1.1 bouyer 1423 1.15 bouyer iiq.system_reply_address_high = 1424 1.15 bouyer htole32(MPII_DMA_DVA(sc->sc_replies) >> 32); 1425 1.1 bouyer 1426 1.15 bouyer iiq.system_request_frame_base_address_lo = 1427 1.15 bouyer htole32(MPII_DMA_DVA(sc->sc_requests)); 1428 1.15 bouyer iiq.system_request_frame_base_address_hi = 1429 1.15 bouyer htole32(MPII_DMA_DVA(sc->sc_requests) >> 32); 1430 1.15 bouyer 1431 1.15 bouyer iiq.reply_descriptor_post_queue_address_lo = 1432 1.15 bouyer htole32(MPII_DMA_DVA(sc->sc_reply_postq)); 1433 1.15 bouyer iiq.reply_descriptor_post_queue_address_hi = 1434 1.15 bouyer htole32(MPII_DMA_DVA(sc->sc_reply_postq) >> 32); 1435 1.15 bouyer 1436 1.15 bouyer iiq.reply_free_queue_address_lo = 1437 1.15 bouyer htole32(MPII_DMA_DVA(sc->sc_reply_freeq)); 1438 1.15 bouyer iiq.reply_free_queue_address_hi = 1439 1.15 bouyer htole32(MPII_DMA_DVA(sc->sc_reply_freeq) >> 32); 1440 1.1 bouyer 1441 1.1 bouyer if (mpii_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) { 1442 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit send failed\n", 1443 1.1 bouyer DEVNAME(sc)); 1444 1.1 bouyer return (1); 1445 1.1 bouyer } 1446 1.1 bouyer 1447 1.1 bouyer if (mpii_handshake_recv(sc, &iip, dwordsof(iip)) != 0) { 1448 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_iocinit recv failed\n", 1449 1.1 bouyer DEVNAME(sc)); 1450 1.1 bouyer return (1); 1451 1.1 bouyer } 1452 1.1 bouyer 1453 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: function: 0x%02x msg_length: %d " 1454 1.1 bouyer "whoinit: 0x%02x\n", DEVNAME(sc), iip.function, 1455 1.1 bouyer iip.msg_length, iip.whoinit); 1456 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: msg_flags: 0x%02x\n", DEVNAME(sc), 1457 1.1 bouyer iip.msg_flags); 1458 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: vf_id: 0x%02x vp_id: 0x%02x\n", DEVNAME(sc), 1459 1.1 bouyer iip.vf_id, iip.vp_id); 1460 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1461 1.1 bouyer le16toh(iip.ioc_status)); 1462 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1463 1.1 bouyer le32toh(iip.ioc_loginfo)); 1464 1.1 bouyer 1465 1.15 bouyer if (le16toh(iip.ioc_status) != MPII_IOCSTATUS_SUCCESS || 1466 1.15 bouyer le32toh(iip.ioc_loginfo)) 1467 1.1 bouyer return (1); 1468 1.1 bouyer 1469 1.1 bouyer return (0); 1470 1.1 bouyer } 1471 1.1 bouyer 1472 1.24 maxv static void 1473 1.1 bouyer mpii_push_reply(struct mpii_softc *sc, struct mpii_rcb *rcb) 1474 1.1 bouyer { 1475 1.1 bouyer u_int32_t *rfp; 1476 1.15 bouyer u_int idx; 1477 1.1 bouyer 1478 1.1 bouyer if (rcb == NULL) 1479 1.1 bouyer return; 1480 1.1 bouyer 1481 1.15 bouyer mutex_enter(&sc->sc_reply_free_mtx); 1482 1.15 bouyer idx = sc->sc_reply_free_host_index; 1483 1.15 bouyer 1484 1.1 bouyer rfp = MPII_DMA_KVA(sc->sc_reply_freeq); 1485 1.15 bouyer rfp[idx] = htole32(rcb->rcb_reply_dva); 1486 1.1 bouyer 1487 1.15 bouyer if (++idx >= sc->sc_reply_free_qdepth) 1488 1.15 bouyer idx = 0; 1489 1.1 bouyer 1490 1.15 bouyer mpii_write_reply_free(sc, sc->sc_reply_free_host_index = idx); 1491 1.15 bouyer mutex_exit(&sc->sc_reply_free_mtx); 1492 1.1 bouyer } 1493 1.1 bouyer 1494 1.24 maxv static int 1495 1.1 bouyer mpii_portfacts(struct mpii_softc *sc) 1496 1.1 bouyer { 1497 1.1 bouyer struct mpii_msg_portfacts_request *pfq; 1498 1.1 bouyer struct mpii_msg_portfacts_reply *pfp; 1499 1.1 bouyer struct mpii_ccb *ccb; 1500 1.1 bouyer int rv = 1; 1501 1.1 bouyer 1502 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts\n", DEVNAME(sc)); 1503 1.1 bouyer 1504 1.15 bouyer ccb = mpii_get_ccb(sc); 1505 1.1 bouyer if (ccb == NULL) { 1506 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts mpii_get_ccb fail\n", 1507 1.1 bouyer DEVNAME(sc)); 1508 1.1 bouyer return (rv); 1509 1.1 bouyer } 1510 1.1 bouyer 1511 1.1 bouyer ccb->ccb_done = mpii_empty_done; 1512 1.1 bouyer pfq = ccb->ccb_cmd; 1513 1.1 bouyer 1514 1.15 bouyer memset(pfq, 0, sizeof(*pfq)); 1515 1.1 bouyer 1516 1.1 bouyer pfq->function = MPII_FUNCTION_PORT_FACTS; 1517 1.1 bouyer pfq->chain_offset = 0; 1518 1.1 bouyer pfq->msg_flags = 0; 1519 1.1 bouyer pfq->port_number = 0; 1520 1.1 bouyer pfq->vp_id = 0; 1521 1.1 bouyer pfq->vf_id = 0; 1522 1.1 bouyer 1523 1.1 bouyer if (mpii_poll(sc, ccb) != 0) { 1524 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_portfacts poll\n", 1525 1.1 bouyer DEVNAME(sc)); 1526 1.1 bouyer goto err; 1527 1.1 bouyer } 1528 1.1 bouyer 1529 1.1 bouyer if (ccb->ccb_rcb == NULL) { 1530 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: empty portfacts reply\n", 1531 1.1 bouyer DEVNAME(sc)); 1532 1.1 bouyer goto err; 1533 1.1 bouyer } 1534 1.1 bouyer 1535 1.1 bouyer pfp = ccb->ccb_rcb->rcb_reply; 1536 1.1 bouyer sc->sc_porttype = pfp->port_type; 1537 1.1 bouyer 1538 1.1 bouyer mpii_push_reply(sc, ccb->ccb_rcb); 1539 1.1 bouyer rv = 0; 1540 1.1 bouyer err: 1541 1.1 bouyer mpii_put_ccb(sc, ccb); 1542 1.1 bouyer 1543 1.1 bouyer return (rv); 1544 1.1 bouyer } 1545 1.1 bouyer 1546 1.24 maxv static void 1547 1.15 bouyer mpii_eventack(struct work *wk, void * cookie) 1548 1.1 bouyer { 1549 1.1 bouyer struct mpii_softc *sc = cookie; 1550 1.1 bouyer struct mpii_ccb *ccb; 1551 1.15 bouyer struct mpii_rcb *rcb, *next; 1552 1.1 bouyer struct mpii_msg_event_reply *enp; 1553 1.1 bouyer struct mpii_msg_eventack_request *eaq; 1554 1.1 bouyer 1555 1.15 bouyer mutex_enter(&sc->sc_evt_ack_mtx); 1556 1.15 bouyer next = SIMPLEQ_FIRST(&sc->sc_evt_ack_queue); 1557 1.15 bouyer SIMPLEQ_INIT(&sc->sc_evt_ack_queue); 1558 1.15 bouyer mutex_exit(&sc->sc_evt_ack_mtx); 1559 1.1 bouyer 1560 1.15 bouyer while (next != NULL) { 1561 1.15 bouyer rcb = next; 1562 1.15 bouyer next = SIMPLEQ_NEXT(rcb, rcb_link); 1563 1.1 bouyer 1564 1.15 bouyer enp = (struct mpii_msg_event_reply *)rcb->rcb_reply; 1565 1.1 bouyer 1566 1.15 bouyer ccb = mpii_get_ccb(sc); 1567 1.15 bouyer ccb->ccb_done = mpii_eventack_done; 1568 1.15 bouyer eaq = ccb->ccb_cmd; 1569 1.1 bouyer 1570 1.15 bouyer eaq->function = MPII_FUNCTION_EVENT_ACK; 1571 1.1 bouyer 1572 1.15 bouyer eaq->event = enp->event; 1573 1.15 bouyer eaq->event_context = enp->event_context; 1574 1.1 bouyer 1575 1.15 bouyer mpii_push_reply(sc, rcb); 1576 1.1 bouyer 1577 1.15 bouyer mpii_start(sc, ccb); 1578 1.15 bouyer } 1579 1.1 bouyer } 1580 1.1 bouyer 1581 1.24 maxv static void 1582 1.1 bouyer mpii_eventack_done(struct mpii_ccb *ccb) 1583 1.1 bouyer { 1584 1.1 bouyer struct mpii_softc *sc = ccb->ccb_sc; 1585 1.1 bouyer 1586 1.1 bouyer DNPRINTF(MPII_D_EVT, "%s: event ack done\n", DEVNAME(sc)); 1587 1.1 bouyer 1588 1.1 bouyer mpii_push_reply(sc, ccb->ccb_rcb); 1589 1.1 bouyer mpii_put_ccb(sc, ccb); 1590 1.1 bouyer } 1591 1.1 bouyer 1592 1.24 maxv static int 1593 1.1 bouyer mpii_portenable(struct mpii_softc *sc) 1594 1.1 bouyer { 1595 1.1 bouyer struct mpii_msg_portenable_request *peq; 1596 1.1 bouyer struct mpii_ccb *ccb; 1597 1.1 bouyer 1598 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_portenable\n", DEVNAME(sc)); 1599 1.1 bouyer 1600 1.15 bouyer ccb = mpii_get_ccb(sc); 1601 1.1 bouyer if (ccb == NULL) { 1602 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_portenable ccb_get\n", 1603 1.1 bouyer DEVNAME(sc)); 1604 1.1 bouyer return (1); 1605 1.1 bouyer } 1606 1.1 bouyer 1607 1.1 bouyer ccb->ccb_done = mpii_empty_done; 1608 1.1 bouyer peq = ccb->ccb_cmd; 1609 1.1 bouyer 1610 1.1 bouyer peq->function = MPII_FUNCTION_PORT_ENABLE; 1611 1.1 bouyer peq->vf_id = sc->sc_vf_id; 1612 1.1 bouyer 1613 1.1 bouyer if (mpii_poll(sc, ccb) != 0) { 1614 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_portenable poll\n", 1615 1.1 bouyer DEVNAME(sc)); 1616 1.1 bouyer return (1); 1617 1.1 bouyer } 1618 1.1 bouyer 1619 1.1 bouyer if (ccb->ccb_rcb == NULL) { 1620 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: empty portenable reply\n", 1621 1.1 bouyer DEVNAME(sc)); 1622 1.1 bouyer return (1); 1623 1.1 bouyer } 1624 1.1 bouyer 1625 1.1 bouyer mpii_push_reply(sc, ccb->ccb_rcb); 1626 1.1 bouyer mpii_put_ccb(sc, ccb); 1627 1.1 bouyer 1628 1.1 bouyer return (0); 1629 1.1 bouyer } 1630 1.1 bouyer 1631 1.24 maxv static int 1632 1.1 bouyer mpii_cfg_coalescing(struct mpii_softc *sc) 1633 1.1 bouyer { 1634 1.15 bouyer struct mpii_cfg_hdr hdr; 1635 1.15 bouyer struct mpii_cfg_ioc_pg1 ipg; 1636 1.1 bouyer 1637 1.15 bouyer hdr.page_version = 0; 1638 1.15 bouyer hdr.page_length = sizeof(ipg) / 4; 1639 1.15 bouyer hdr.page_number = 1; 1640 1.15 bouyer hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_IOC; 1641 1.15 bouyer memset(&ipg, 0, sizeof(ipg)); 1642 1.15 bouyer if (mpii_req_cfg_page(sc, 0, MPII_PG_POLL, &hdr, 1, &ipg, 1643 1.15 bouyer sizeof(ipg)) != 0) { 1644 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: unable to fetch IOC page 1\n" 1645 1.1 bouyer "page 1\n", DEVNAME(sc)); 1646 1.1 bouyer return (1); 1647 1.1 bouyer } 1648 1.1 bouyer 1649 1.15 bouyer if (!ISSET(le32toh(ipg.flags), MPII_CFG_IOC_1_REPLY_COALESCING)) 1650 1.1 bouyer return (0); 1651 1.1 bouyer 1652 1.15 bouyer /* Disable coalescing */ 1653 1.15 bouyer CLR(ipg.flags, htole32(MPII_CFG_IOC_1_REPLY_COALESCING)); 1654 1.15 bouyer if (mpii_req_cfg_page(sc, 0, MPII_PG_POLL, &hdr, 0, &ipg, 1655 1.15 bouyer sizeof(ipg)) != 0) { 1656 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: unable to clear coalescing\n", 1657 1.1 bouyer DEVNAME(sc)); 1658 1.1 bouyer return (1); 1659 1.1 bouyer } 1660 1.1 bouyer 1661 1.1 bouyer return (0); 1662 1.1 bouyer } 1663 1.1 bouyer 1664 1.1 bouyer #define MPII_EVENT_MASKALL(enq) do { \ 1665 1.1 bouyer enq->event_masks[0] = 0xffffffff; \ 1666 1.1 bouyer enq->event_masks[1] = 0xffffffff; \ 1667 1.1 bouyer enq->event_masks[2] = 0xffffffff; \ 1668 1.1 bouyer enq->event_masks[3] = 0xffffffff; \ 1669 1.1 bouyer } while (0) 1670 1.1 bouyer 1671 1.1 bouyer #define MPII_EVENT_UNMASK(enq, evt) do { \ 1672 1.1 bouyer enq->event_masks[evt / 32] &= \ 1673 1.1 bouyer htole32(~(1 << (evt % 32))); \ 1674 1.1 bouyer } while (0) 1675 1.1 bouyer 1676 1.24 maxv static int 1677 1.1 bouyer mpii_eventnotify(struct mpii_softc *sc) 1678 1.1 bouyer { 1679 1.1 bouyer struct mpii_msg_event_request *enq; 1680 1.1 bouyer struct mpii_ccb *ccb; 1681 1.15 bouyer char wkname[15]; 1682 1.1 bouyer 1683 1.15 bouyer ccb = mpii_get_ccb(sc); 1684 1.1 bouyer if (ccb == NULL) { 1685 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_eventnotify ccb_get\n", 1686 1.1 bouyer DEVNAME(sc)); 1687 1.1 bouyer return (1); 1688 1.1 bouyer } 1689 1.1 bouyer 1690 1.15 bouyer SIMPLEQ_INIT(&sc->sc_evt_sas_queue); 1691 1.15 bouyer mutex_init(&sc->sc_evt_sas_mtx, MUTEX_DEFAULT, IPL_BIO); 1692 1.15 bouyer snprintf(wkname, sizeof(wkname), "%ssas", DEVNAME(sc)); 1693 1.15 bouyer if (workqueue_create(&sc->sc_evt_sas_wq, wkname, 1694 1.15 bouyer mpii_event_sas_work, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) { 1695 1.15 bouyer mpii_put_ccb(sc, ccb); 1696 1.15 bouyer aprint_error_dev(sc->sc_dev, 1697 1.15 bouyer "can't create %s workqueue\n", wkname); 1698 1.15 bouyer return 1; 1699 1.15 bouyer } 1700 1.15 bouyer 1701 1.15 bouyer SIMPLEQ_INIT(&sc->sc_evt_ack_queue); 1702 1.15 bouyer mutex_init(&sc->sc_evt_ack_mtx, MUTEX_DEFAULT, IPL_BIO); 1703 1.15 bouyer snprintf(wkname, sizeof(wkname), "%sevt", DEVNAME(sc)); 1704 1.15 bouyer if (workqueue_create(&sc->sc_evt_ack_wq, wkname, 1705 1.15 bouyer mpii_eventack, sc, PRI_NONE, IPL_BIO, WQ_MPSAFE) != 0) { 1706 1.15 bouyer mpii_put_ccb(sc, ccb); 1707 1.15 bouyer aprint_error_dev(sc->sc_dev, 1708 1.15 bouyer "can't create %s workqueue\n", wkname); 1709 1.15 bouyer return 1; 1710 1.15 bouyer } 1711 1.15 bouyer 1712 1.1 bouyer ccb->ccb_done = mpii_eventnotify_done; 1713 1.1 bouyer enq = ccb->ccb_cmd; 1714 1.1 bouyer 1715 1.1 bouyer enq->function = MPII_FUNCTION_EVENT_NOTIFICATION; 1716 1.1 bouyer 1717 1.1 bouyer /* 1718 1.1 bouyer * Enable reporting of the following events: 1719 1.1 bouyer * 1720 1.1 bouyer * MPII_EVENT_SAS_DISCOVERY 1721 1.1 bouyer * MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST 1722 1.1 bouyer * MPII_EVENT_SAS_DEVICE_STATUS_CHANGE 1723 1.1 bouyer * MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE 1724 1.1 bouyer * MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST 1725 1.1 bouyer * MPII_EVENT_IR_VOLUME 1726 1.1 bouyer * MPII_EVENT_IR_PHYSICAL_DISK 1727 1.1 bouyer * MPII_EVENT_IR_OPERATION_STATUS 1728 1.1 bouyer */ 1729 1.1 bouyer 1730 1.1 bouyer MPII_EVENT_MASKALL(enq); 1731 1.1 bouyer MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DISCOVERY); 1732 1.1 bouyer MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 1733 1.1 bouyer MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_DEVICE_STATUS_CHANGE); 1734 1.1 bouyer MPII_EVENT_UNMASK(enq, MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); 1735 1.1 bouyer MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST); 1736 1.1 bouyer MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_VOLUME); 1737 1.1 bouyer MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_PHYSICAL_DISK); 1738 1.1 bouyer MPII_EVENT_UNMASK(enq, MPII_EVENT_IR_OPERATION_STATUS); 1739 1.1 bouyer 1740 1.1 bouyer mpii_start(sc, ccb); 1741 1.1 bouyer 1742 1.1 bouyer return (0); 1743 1.1 bouyer } 1744 1.1 bouyer 1745 1.24 maxv static void 1746 1.1 bouyer mpii_eventnotify_done(struct mpii_ccb *ccb) 1747 1.1 bouyer { 1748 1.1 bouyer struct mpii_softc *sc = ccb->ccb_sc; 1749 1.1 bouyer struct mpii_rcb *rcb = ccb->ccb_rcb; 1750 1.1 bouyer 1751 1.1 bouyer DNPRINTF(MPII_D_EVT, "%s: mpii_eventnotify_done\n", DEVNAME(sc)); 1752 1.1 bouyer 1753 1.1 bouyer mpii_put_ccb(sc, ccb); 1754 1.1 bouyer mpii_event_process(sc, rcb); 1755 1.1 bouyer } 1756 1.1 bouyer 1757 1.24 maxv static void 1758 1.1 bouyer mpii_event_raid(struct mpii_softc *sc, struct mpii_msg_event_reply *enp) 1759 1.1 bouyer { 1760 1.1 bouyer struct mpii_evt_ir_cfg_change_list *ccl; 1761 1.1 bouyer struct mpii_evt_ir_cfg_element *ce; 1762 1.1 bouyer struct mpii_device *dev; 1763 1.1 bouyer u_int16_t type; 1764 1.1 bouyer int i; 1765 1.1 bouyer 1766 1.1 bouyer ccl = (struct mpii_evt_ir_cfg_change_list *)(enp + 1); 1767 1.1 bouyer if (ccl->num_elements == 0) 1768 1.1 bouyer return; 1769 1.15 bouyer 1770 1.15 bouyer if (ISSET(le32toh(ccl->flags), MPII_EVT_IR_CFG_CHANGE_LIST_FOREIGN)) { 1771 1.1 bouyer /* bail on foreign configurations */ 1772 1.1 bouyer return; 1773 1.15 bouyer } 1774 1.1 bouyer 1775 1.1 bouyer ce = (struct mpii_evt_ir_cfg_element *)(ccl + 1); 1776 1.1 bouyer 1777 1.1 bouyer for (i = 0; i < ccl->num_elements; i++, ce++) { 1778 1.1 bouyer type = (le16toh(ce->element_flags) & 1779 1.1 bouyer MPII_EVT_IR_CFG_ELEMENT_TYPE_MASK); 1780 1.1 bouyer 1781 1.1 bouyer switch (type) { 1782 1.1 bouyer case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME: 1783 1.1 bouyer switch (ce->reason_code) { 1784 1.1 bouyer case MPII_EVT_IR_CFG_ELEMENT_RC_ADDED: 1785 1.1 bouyer case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_CREATED: 1786 1.15 bouyer dev = malloc(sizeof(*dev), M_DEVBUF, 1787 1.23 chs M_WAITOK | M_ZERO); 1788 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 1789 1.1 bouyer if (mpii_find_dev(sc, 1790 1.1 bouyer le16toh(ce->vol_dev_handle))) { 1791 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1792 1.15 bouyer free(dev, M_DEVBUF); 1793 1.15 bouyer printf("%s: device %#x is already " 1794 1.15 bouyer "configured\n", DEVNAME(sc), 1795 1.1 bouyer le16toh(ce->vol_dev_handle)); 1796 1.1 bouyer break; 1797 1.1 bouyer } 1798 1.1 bouyer SET(dev->flags, MPII_DF_VOLUME); 1799 1.1 bouyer dev->slot = sc->sc_vd_id_low; 1800 1.1 bouyer dev->dev_handle = le16toh(ce->vol_dev_handle); 1801 1.1 bouyer if (mpii_insert_dev(sc, dev)) { 1802 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1803 1.1 bouyer free(dev, M_DEVBUF); 1804 1.1 bouyer break; 1805 1.1 bouyer } 1806 1.1 bouyer sc->sc_vd_count++; 1807 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1808 1.1 bouyer break; 1809 1.1 bouyer case MPII_EVT_IR_CFG_ELEMENT_RC_REMOVED: 1810 1.1 bouyer case MPII_EVT_IR_CFG_ELEMENT_RC_VOLUME_DELETED: 1811 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 1812 1.1 bouyer if (!(dev = mpii_find_dev(sc, 1813 1.15 bouyer le16toh(ce->vol_dev_handle)))) { 1814 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1815 1.1 bouyer break; 1816 1.15 bouyer } 1817 1.1 bouyer mpii_remove_dev(sc, dev); 1818 1.1 bouyer sc->sc_vd_count--; 1819 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1820 1.1 bouyer break; 1821 1.1 bouyer } 1822 1.1 bouyer break; 1823 1.1 bouyer case MPII_EVT_IR_CFG_ELEMENT_TYPE_VOLUME_DISK: 1824 1.1 bouyer if (ce->reason_code == 1825 1.1 bouyer MPII_EVT_IR_CFG_ELEMENT_RC_PD_CREATED || 1826 1.1 bouyer ce->reason_code == 1827 1.1 bouyer MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) { 1828 1.1 bouyer /* there should be an underlying sas drive */ 1829 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 1830 1.1 bouyer if (!(dev = mpii_find_dev(sc, 1831 1.15 bouyer le16toh(ce->phys_disk_dev_handle)))) { 1832 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1833 1.1 bouyer break; 1834 1.15 bouyer } 1835 1.1 bouyer /* promoted from a hot spare? */ 1836 1.1 bouyer CLR(dev->flags, MPII_DF_HOT_SPARE); 1837 1.1 bouyer SET(dev->flags, MPII_DF_VOLUME_DISK | 1838 1.1 bouyer MPII_DF_HIDDEN); 1839 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1840 1.1 bouyer } 1841 1.1 bouyer break; 1842 1.1 bouyer case MPII_EVT_IR_CFG_ELEMENT_TYPE_HOT_SPARE: 1843 1.1 bouyer if (ce->reason_code == 1844 1.1 bouyer MPII_EVT_IR_CFG_ELEMENT_RC_HIDE) { 1845 1.1 bouyer /* there should be an underlying sas drive */ 1846 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 1847 1.1 bouyer if (!(dev = mpii_find_dev(sc, 1848 1.15 bouyer le16toh(ce->phys_disk_dev_handle)))) { 1849 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1850 1.1 bouyer break; 1851 1.15 bouyer } 1852 1.1 bouyer SET(dev->flags, MPII_DF_HOT_SPARE | 1853 1.1 bouyer MPII_DF_HIDDEN); 1854 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1855 1.1 bouyer } 1856 1.1 bouyer break; 1857 1.1 bouyer } 1858 1.1 bouyer } 1859 1.1 bouyer } 1860 1.1 bouyer 1861 1.24 maxv static void 1862 1.15 bouyer mpii_event_sas(struct mpii_softc *sc, struct mpii_rcb *rcb) 1863 1.1 bouyer { 1864 1.15 bouyer struct mpii_msg_event_reply *enp; 1865 1.1 bouyer struct mpii_evt_sas_tcl *tcl; 1866 1.1 bouyer struct mpii_evt_phy_entry *pe; 1867 1.1 bouyer struct mpii_device *dev; 1868 1.1 bouyer int i; 1869 1.15 bouyer u_int16_t handle; 1870 1.15 bouyer int need_queue = 0; 1871 1.15 bouyer 1872 1.15 bouyer enp = (struct mpii_msg_event_reply *)rcb->rcb_reply; 1873 1.15 bouyer DNPRINTF(MPII_D_EVT, "%s: mpii_event_sas 0x%x\n", 1874 1.15 bouyer DEVNAME(sc), le16toh(enp->event)); 1875 1.15 bouyer KASSERT(le16toh(enp->event) == MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 1876 1.1 bouyer 1877 1.1 bouyer tcl = (struct mpii_evt_sas_tcl *)(enp + 1); 1878 1.1 bouyer pe = (struct mpii_evt_phy_entry *)(tcl + 1); 1879 1.1 bouyer 1880 1.1 bouyer for (i = 0; i < tcl->num_entries; i++, pe++) { 1881 1.15 bouyer DNPRINTF(MPII_D_EVT, "%s: sas change %d stat %d h %d slot %d phy %d enc %d expand %d\n", 1882 1.15 bouyer DEVNAME(sc), i, pe->phy_status, 1883 1.15 bouyer le16toh(pe->dev_handle), 1884 1.15 bouyer sc->sc_pd_id_start + tcl->start_phy_num + i, 1885 1.15 bouyer tcl->start_phy_num + i, le16toh(tcl->enclosure_handle), le16toh(tcl->expander_handle)); 1886 1.27 skrll 1887 1.1 bouyer switch (pe->phy_status & MPII_EVENT_SAS_TOPO_PS_RC_MASK) { 1888 1.1 bouyer case MPII_EVENT_SAS_TOPO_PS_RC_ADDED: 1889 1.15 bouyer handle = le16toh(pe->dev_handle); 1890 1.15 bouyer DNPRINTF(MPII_D_EVT, "%s: sas add handle %d\n", 1891 1.15 bouyer DEVNAME(sc), handle); 1892 1.15 bouyer dev = malloc(sizeof(*dev), M_DEVBUF, M_WAITOK | M_ZERO); 1893 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 1894 1.15 bouyer if (mpii_find_dev(sc, handle)) { 1895 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1896 1.15 bouyer free(dev, M_DEVBUF); 1897 1.15 bouyer printf("%s: device %#x is already " 1898 1.15 bouyer "configured\n", DEVNAME(sc), handle); 1899 1.1 bouyer break; 1900 1.1 bouyer } 1901 1.15 bouyer 1902 1.1 bouyer dev->slot = sc->sc_pd_id_start + tcl->start_phy_num + i; 1903 1.15 bouyer dev->dev_handle = handle; 1904 1.1 bouyer dev->phy_num = tcl->start_phy_num + i; 1905 1.1 bouyer if (tcl->enclosure_handle) 1906 1.1 bouyer dev->physical_port = tcl->physical_port; 1907 1.1 bouyer dev->enclosure = le16toh(tcl->enclosure_handle); 1908 1.1 bouyer dev->expander = le16toh(tcl->expander_handle); 1909 1.15 bouyer 1910 1.1 bouyer if (mpii_insert_dev(sc, dev)) { 1911 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1912 1.1 bouyer free(dev, M_DEVBUF); 1913 1.1 bouyer break; 1914 1.1 bouyer } 1915 1.22 kardel printf("%s: physical device inserted in slot %d\n", 1916 1.15 bouyer DEVNAME(sc), dev->slot); 1917 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1918 1.1 bouyer break; 1919 1.15 bouyer 1920 1.1 bouyer case MPII_EVENT_SAS_TOPO_PS_RC_MISSING: 1921 1.15 bouyer /* defer to workqueue thread */ 1922 1.15 bouyer need_queue++; 1923 1.15 bouyer break; 1924 1.15 bouyer } 1925 1.15 bouyer } 1926 1.15 bouyer 1927 1.15 bouyer if (need_queue) { 1928 1.15 bouyer bool start_wk; 1929 1.15 bouyer mutex_enter(&sc->sc_evt_sas_mtx); 1930 1.15 bouyer start_wk = (SIMPLEQ_FIRST(&sc->sc_evt_sas_queue) == 0); 1931 1.15 bouyer SIMPLEQ_INSERT_TAIL(&sc->sc_evt_sas_queue, rcb, rcb_link); 1932 1.15 bouyer if (start_wk) { 1933 1.15 bouyer workqueue_enqueue(sc->sc_evt_sas_wq, 1934 1.15 bouyer &sc->sc_evt_sas_work, NULL); 1935 1.15 bouyer } 1936 1.15 bouyer mutex_exit(&sc->sc_evt_sas_mtx); 1937 1.15 bouyer } else 1938 1.15 bouyer mpii_event_done(sc, rcb); 1939 1.15 bouyer } 1940 1.15 bouyer 1941 1.24 maxv static void 1942 1.15 bouyer mpii_event_sas_work(struct work *wq, void *xsc) 1943 1.15 bouyer { 1944 1.15 bouyer struct mpii_softc *sc = xsc; 1945 1.15 bouyer struct mpii_rcb *rcb, *next; 1946 1.15 bouyer struct mpii_msg_event_reply *enp; 1947 1.15 bouyer struct mpii_evt_sas_tcl *tcl; 1948 1.15 bouyer struct mpii_evt_phy_entry *pe; 1949 1.15 bouyer struct mpii_device *dev; 1950 1.15 bouyer int i; 1951 1.15 bouyer 1952 1.15 bouyer mutex_enter(&sc->sc_evt_sas_mtx); 1953 1.15 bouyer next = SIMPLEQ_FIRST(&sc->sc_evt_sas_queue); 1954 1.15 bouyer SIMPLEQ_INIT(&sc->sc_evt_sas_queue); 1955 1.15 bouyer mutex_exit(&sc->sc_evt_sas_mtx); 1956 1.15 bouyer 1957 1.15 bouyer while (next != NULL) { 1958 1.15 bouyer rcb = next; 1959 1.15 bouyer next = SIMPLEQ_NEXT(rcb, rcb_link); 1960 1.15 bouyer 1961 1.15 bouyer enp = (struct mpii_msg_event_reply *)rcb->rcb_reply; 1962 1.15 bouyer DNPRINTF(MPII_D_EVT, "%s: mpii_event_sas_work 0x%x\n", 1963 1.15 bouyer DEVNAME(sc), le16toh(enp->event)); 1964 1.15 bouyer KASSERT(le16toh(enp->event) == MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST); 1965 1.15 bouyer tcl = (struct mpii_evt_sas_tcl *)(enp + 1); 1966 1.15 bouyer pe = (struct mpii_evt_phy_entry *)(tcl + 1); 1967 1.15 bouyer 1968 1.15 bouyer for (i = 0; i < tcl->num_entries; i++, pe++) { 1969 1.15 bouyer DNPRINTF(MPII_D_EVT, "%s: sas change %d stat %d h %d slot %d phy %d enc %d expand %d\n", 1970 1.15 bouyer DEVNAME(sc), i, pe->phy_status, 1971 1.15 bouyer le16toh(pe->dev_handle), 1972 1.15 bouyer sc->sc_pd_id_start + tcl->start_phy_num + i, 1973 1.15 bouyer tcl->start_phy_num + i, le16toh(tcl->enclosure_handle), le16toh(tcl->expander_handle)); 1974 1.27 skrll 1975 1.15 bouyer switch (pe->phy_status & MPII_EVENT_SAS_TOPO_PS_RC_MASK) { 1976 1.15 bouyer case MPII_EVENT_SAS_TOPO_PS_RC_ADDED: 1977 1.15 bouyer /* already handled */ 1978 1.15 bouyer break; 1979 1.15 bouyer 1980 1.15 bouyer case MPII_EVENT_SAS_TOPO_PS_RC_MISSING: 1981 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 1982 1.15 bouyer dev = mpii_find_dev(sc, le16toh(pe->dev_handle)); 1983 1.15 bouyer if (dev == NULL) { 1984 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1985 1.15 bouyer break; 1986 1.15 bouyer } 1987 1.15 bouyer 1988 1.15 bouyer printf( 1989 1.22 kardel "%s: physical device removed from slot %d\n", 1990 1.15 bouyer DEVNAME(sc), dev->slot); 1991 1.15 bouyer mpii_remove_dev(sc, dev); 1992 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 1993 1.15 bouyer mpii_sas_remove_device(sc, dev->dev_handle); 1994 1.15 bouyer if (!ISSET(dev->flags, MPII_DF_HIDDEN)) { 1995 1.15 bouyer scsipi_target_detach(&sc->sc_chan, 1996 1.15 bouyer dev->slot, 0, DETACH_FORCE); 1997 1.15 bouyer } 1998 1.15 bouyer 1999 1.15 bouyer free(dev, M_DEVBUF); 2000 1.1 bouyer break; 2001 1.1 bouyer } 2002 1.1 bouyer } 2003 1.15 bouyer mpii_event_done(sc, rcb); 2004 1.15 bouyer } 2005 1.15 bouyer } 2006 1.15 bouyer 2007 1.24 maxv static void 2008 1.15 bouyer mpii_event_discovery(struct mpii_softc *sc, struct mpii_msg_event_reply *enp) 2009 1.15 bouyer { 2010 1.15 bouyer struct mpii_evt_sas_discovery *esd = 2011 1.15 bouyer (struct mpii_evt_sas_discovery *)(enp + 1); 2012 1.15 bouyer 2013 1.15 bouyer if (esd->reason_code == MPII_EVENT_SAS_DISC_REASON_CODE_COMPLETED) { 2014 1.15 bouyer if (esd->discovery_status != 0) { 2015 1.15 bouyer printf("%s: sas discovery completed with status %#x\n", 2016 1.15 bouyer DEVNAME(sc), esd->discovery_status); 2017 1.15 bouyer } 2018 1.15 bouyer 2019 1.1 bouyer } 2020 1.1 bouyer } 2021 1.1 bouyer 2022 1.24 maxv static void 2023 1.1 bouyer mpii_event_process(struct mpii_softc *sc, struct mpii_rcb *rcb) 2024 1.1 bouyer { 2025 1.1 bouyer struct mpii_msg_event_reply *enp; 2026 1.1 bouyer 2027 1.1 bouyer enp = (struct mpii_msg_event_reply *)rcb->rcb_reply; 2028 1.1 bouyer 2029 1.1 bouyer DNPRINTF(MPII_D_EVT, "%s: mpii_event_process: %#x\n", DEVNAME(sc), 2030 1.15 bouyer le16toh(enp->event)); 2031 1.1 bouyer 2032 1.15 bouyer switch (le16toh(enp->event)) { 2033 1.1 bouyer case MPII_EVENT_EVENT_CHANGE: 2034 1.1 bouyer /* should be properly ignored */ 2035 1.1 bouyer break; 2036 1.15 bouyer case MPII_EVENT_SAS_DISCOVERY: 2037 1.15 bouyer mpii_event_discovery(sc, enp); 2038 1.1 bouyer break; 2039 1.1 bouyer case MPII_EVENT_SAS_TOPOLOGY_CHANGE_LIST: 2040 1.15 bouyer mpii_event_sas(sc, rcb); 2041 1.15 bouyer return; 2042 1.1 bouyer case MPII_EVENT_SAS_DEVICE_STATUS_CHANGE: 2043 1.1 bouyer break; 2044 1.1 bouyer case MPII_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: 2045 1.1 bouyer break; 2046 1.1 bouyer case MPII_EVENT_IR_VOLUME: { 2047 1.1 bouyer struct mpii_evt_ir_volume *evd = 2048 1.1 bouyer (struct mpii_evt_ir_volume *)(enp + 1); 2049 1.1 bouyer struct mpii_device *dev; 2050 1.1 bouyer #if NBIO > 0 2051 1.1 bouyer const char *vol_states[] = { 2052 1.1 bouyer BIOC_SVINVALID_S, 2053 1.1 bouyer BIOC_SVOFFLINE_S, 2054 1.1 bouyer BIOC_SVBUILDING_S, 2055 1.1 bouyer BIOC_SVONLINE_S, 2056 1.1 bouyer BIOC_SVDEGRADED_S, 2057 1.1 bouyer BIOC_SVONLINE_S, 2058 1.1 bouyer }; 2059 1.1 bouyer #endif 2060 1.1 bouyer 2061 1.1 bouyer if (cold) 2062 1.1 bouyer break; 2063 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 2064 1.15 bouyer dev = mpii_find_dev(sc, le16toh(evd->vol_dev_handle)); 2065 1.15 bouyer if (dev == NULL) { 2066 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 2067 1.1 bouyer break; 2068 1.15 bouyer } 2069 1.1 bouyer #if NBIO > 0 2070 1.1 bouyer if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATE_CHANGED) 2071 1.1 bouyer printf("%s: volume %d state changed from %s to %s\n", 2072 1.1 bouyer DEVNAME(sc), dev->slot - sc->sc_vd_id_low, 2073 1.1 bouyer vol_states[evd->prev_value], 2074 1.1 bouyer vol_states[evd->new_value]); 2075 1.1 bouyer #endif 2076 1.1 bouyer if (evd->reason_code == MPII_EVENT_IR_VOL_RC_STATUS_CHANGED && 2077 1.1 bouyer ISSET(evd->new_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC) && 2078 1.1 bouyer !ISSET(evd->prev_value, MPII_CFG_RAID_VOL_0_STATUS_RESYNC)) 2079 1.1 bouyer printf("%s: started resync on a volume %d\n", 2080 1.1 bouyer DEVNAME(sc), dev->slot - sc->sc_vd_id_low); 2081 1.1 bouyer } 2082 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 2083 1.1 bouyer break; 2084 1.1 bouyer case MPII_EVENT_IR_PHYSICAL_DISK: 2085 1.1 bouyer break; 2086 1.1 bouyer case MPII_EVENT_IR_CONFIGURATION_CHANGE_LIST: 2087 1.1 bouyer mpii_event_raid(sc, enp); 2088 1.1 bouyer break; 2089 1.1 bouyer case MPII_EVENT_IR_OPERATION_STATUS: { 2090 1.1 bouyer struct mpii_evt_ir_status *evs = 2091 1.1 bouyer (struct mpii_evt_ir_status *)(enp + 1); 2092 1.1 bouyer struct mpii_device *dev; 2093 1.1 bouyer 2094 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 2095 1.15 bouyer dev = mpii_find_dev(sc, le16toh(evs->vol_dev_handle)); 2096 1.15 bouyer if (dev != NULL && 2097 1.15 bouyer evs->operation == MPII_EVENT_IR_RAIDOP_RESYNC) 2098 1.1 bouyer dev->percent = evs->percent; 2099 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 2100 1.1 bouyer break; 2101 1.1 bouyer } 2102 1.1 bouyer default: 2103 1.1 bouyer DNPRINTF(MPII_D_EVT, "%s: unhandled event 0x%02x\n", 2104 1.15 bouyer DEVNAME(sc), le16toh(enp->event)); 2105 1.1 bouyer } 2106 1.1 bouyer 2107 1.15 bouyer mpii_event_done(sc, rcb); 2108 1.1 bouyer } 2109 1.1 bouyer 2110 1.24 maxv static void 2111 1.15 bouyer mpii_event_done(struct mpii_softc *sc, struct mpii_rcb *rcb) 2112 1.1 bouyer { 2113 1.15 bouyer struct mpii_msg_event_reply *enp = rcb->rcb_reply; 2114 1.15 bouyer bool need_start; 2115 1.1 bouyer 2116 1.15 bouyer if (enp->ack_required) { 2117 1.15 bouyer mutex_enter(&sc->sc_evt_ack_mtx); 2118 1.15 bouyer need_start = (SIMPLEQ_FIRST(&sc->sc_evt_ack_queue) == 0); 2119 1.15 bouyer SIMPLEQ_INSERT_TAIL(&sc->sc_evt_ack_queue, rcb, rcb_link); 2120 1.15 bouyer if (need_start) 2121 1.15 bouyer workqueue_enqueue(sc->sc_evt_ack_wq, 2122 1.15 bouyer &sc->sc_evt_ack_work, NULL); 2123 1.15 bouyer mutex_exit(&sc->sc_evt_ack_mtx); 2124 1.15 bouyer } else 2125 1.15 bouyer mpii_push_reply(sc, rcb); 2126 1.1 bouyer } 2127 1.1 bouyer 2128 1.24 maxv static void 2129 1.1 bouyer mpii_sas_remove_device(struct mpii_softc *sc, u_int16_t handle) 2130 1.1 bouyer { 2131 1.15 bouyer struct mpii_msg_scsi_task_request *stq; 2132 1.1 bouyer struct mpii_msg_sas_oper_request *soq; 2133 1.1 bouyer struct mpii_ccb *ccb; 2134 1.1 bouyer 2135 1.15 bouyer ccb = mpii_get_ccb(sc); 2136 1.1 bouyer if (ccb == NULL) 2137 1.1 bouyer return; 2138 1.1 bouyer 2139 1.1 bouyer stq = ccb->ccb_cmd; 2140 1.1 bouyer stq->function = MPII_FUNCTION_SCSI_TASK_MGMT; 2141 1.1 bouyer stq->task_type = MPII_SCSI_TASK_TARGET_RESET; 2142 1.1 bouyer stq->dev_handle = htole16(handle); 2143 1.1 bouyer 2144 1.1 bouyer ccb->ccb_done = mpii_empty_done; 2145 1.1 bouyer mpii_wait(sc, ccb); 2146 1.1 bouyer 2147 1.1 bouyer if (ccb->ccb_rcb != NULL) 2148 1.1 bouyer mpii_push_reply(sc, ccb->ccb_rcb); 2149 1.1 bouyer 2150 1.1 bouyer /* reuse a ccb */ 2151 1.1 bouyer ccb->ccb_state = MPII_CCB_READY; 2152 1.1 bouyer ccb->ccb_rcb = NULL; 2153 1.1 bouyer 2154 1.1 bouyer soq = ccb->ccb_cmd; 2155 1.15 bouyer memset(soq, 0, sizeof(*soq)); 2156 1.1 bouyer soq->function = MPII_FUNCTION_SAS_IO_UNIT_CONTROL; 2157 1.1 bouyer soq->operation = MPII_SAS_OP_REMOVE_DEVICE; 2158 1.1 bouyer soq->dev_handle = htole16(handle); 2159 1.1 bouyer 2160 1.1 bouyer ccb->ccb_done = mpii_empty_done; 2161 1.1 bouyer mpii_wait(sc, ccb); 2162 1.1 bouyer if (ccb->ccb_rcb != NULL) 2163 1.1 bouyer mpii_push_reply(sc, ccb->ccb_rcb); 2164 1.15 bouyer 2165 1.15 bouyer mpii_put_ccb(sc, ccb); 2166 1.1 bouyer } 2167 1.1 bouyer 2168 1.24 maxv static int 2169 1.15 bouyer mpii_board_info(struct mpii_softc *sc) 2170 1.1 bouyer { 2171 1.15 bouyer struct mpii_msg_iocfacts_request ifq; 2172 1.15 bouyer struct mpii_msg_iocfacts_reply ifp; 2173 1.15 bouyer struct mpii_cfg_manufacturing_pg0 mpg; 2174 1.15 bouyer struct mpii_cfg_hdr hdr; 2175 1.15 bouyer 2176 1.15 bouyer memset(&ifq, 0, sizeof(ifq)); 2177 1.15 bouyer memset(&ifp, 0, sizeof(ifp)); 2178 1.1 bouyer 2179 1.15 bouyer ifq.function = MPII_FUNCTION_IOC_FACTS; 2180 1.1 bouyer 2181 1.15 bouyer if (mpii_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) { 2182 1.15 bouyer DNPRINTF(MPII_D_MISC, "%s: failed to request ioc facts\n", 2183 1.15 bouyer DEVNAME(sc)); 2184 1.1 bouyer return (1); 2185 1.1 bouyer } 2186 1.1 bouyer 2187 1.15 bouyer if (mpii_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) { 2188 1.15 bouyer DNPRINTF(MPII_D_MISC, "%s: failed to receive ioc facts\n", 2189 1.15 bouyer DEVNAME(sc)); 2190 1.1 bouyer return (1); 2191 1.1 bouyer } 2192 1.1 bouyer 2193 1.15 bouyer hdr.page_version = 0; 2194 1.15 bouyer hdr.page_length = sizeof(mpg) / 4; 2195 1.15 bouyer hdr.page_number = 0; 2196 1.15 bouyer hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_MANUFACTURING; 2197 1.15 bouyer memset(&mpg, 0, sizeof(mpg)); 2198 1.15 bouyer if (mpii_req_cfg_page(sc, 0, MPII_PG_POLL, &hdr, 1, &mpg, 2199 1.15 bouyer sizeof(mpg)) != 0) { 2200 1.15 bouyer printf("%s: unable to fetch manufacturing page 0\n", 2201 1.15 bouyer DEVNAME(sc)); 2202 1.15 bouyer return (EINVAL); 2203 1.1 bouyer } 2204 1.1 bouyer 2205 1.15 bouyer printf("%s: %s, firmware %u.%u.%u.%u%s, MPI %u.%u\n", DEVNAME(sc), 2206 1.15 bouyer mpg.board_name, ifp.fw_version_maj, ifp.fw_version_min, 2207 1.15 bouyer ifp.fw_version_unit, ifp.fw_version_dev, 2208 1.15 bouyer ISSET(sc->sc_flags, MPII_F_RAID) ? " IR" : "", 2209 1.15 bouyer ifp.msg_version_maj, ifp.msg_version_min); 2210 1.15 bouyer 2211 1.15 bouyer return (0); 2212 1.15 bouyer } 2213 1.15 bouyer 2214 1.24 maxv static int 2215 1.15 bouyer mpii_target_map(struct mpii_softc *sc) 2216 1.15 bouyer { 2217 1.15 bouyer struct mpii_cfg_hdr hdr; 2218 1.15 bouyer struct mpii_cfg_ioc_pg8 ipg; 2219 1.15 bouyer int flags, pad = 0; 2220 1.1 bouyer 2221 1.15 bouyer hdr.page_version = 0; 2222 1.15 bouyer hdr.page_length = sizeof(ipg) / 4; 2223 1.15 bouyer hdr.page_number = 8; 2224 1.15 bouyer hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_IOC; 2225 1.15 bouyer memset(&ipg, 0, sizeof(ipg)); 2226 1.15 bouyer if (mpii_req_cfg_page(sc, 0, MPII_PG_POLL, &hdr, 1, &ipg, 2227 1.15 bouyer sizeof(ipg)) != 0) { 2228 1.15 bouyer printf("%s: unable to fetch ioc page 8\n", 2229 1.15 bouyer DEVNAME(sc)); 2230 1.15 bouyer return (EINVAL); 2231 1.15 bouyer } 2232 1.15 bouyer 2233 1.15 bouyer if (le16toh(ipg.flags) & MPII_IOC_PG8_FLAGS_RESERVED_TARGETID_0) 2234 1.1 bouyer pad = 1; 2235 1.1 bouyer 2236 1.15 bouyer flags = le16toh(ipg.ir_volume_mapping_flags) & 2237 1.1 bouyer MPII_IOC_PG8_IRFLAGS_VOLUME_MAPPING_MODE_MASK; 2238 1.1 bouyer if (ISSET(sc->sc_flags, MPII_F_RAID)) { 2239 1.1 bouyer if (flags == MPII_IOC_PG8_IRFLAGS_LOW_VOLUME_MAPPING) { 2240 1.1 bouyer sc->sc_vd_id_low += pad; 2241 1.1 bouyer pad = sc->sc_max_volumes; /* for sc_pd_id_start */ 2242 1.1 bouyer } else 2243 1.1 bouyer sc->sc_vd_id_low = sc->sc_max_devices - 2244 1.1 bouyer sc->sc_max_volumes; 2245 1.1 bouyer } 2246 1.1 bouyer 2247 1.1 bouyer sc->sc_pd_id_start += pad; 2248 1.1 bouyer 2249 1.15 bouyer return (0); 2250 1.1 bouyer } 2251 1.1 bouyer 2252 1.24 maxv static int 2253 1.1 bouyer mpii_req_cfg_header(struct mpii_softc *sc, u_int8_t type, u_int8_t number, 2254 1.1 bouyer u_int32_t address, int flags, void *p) 2255 1.1 bouyer { 2256 1.1 bouyer struct mpii_msg_config_request *cq; 2257 1.1 bouyer struct mpii_msg_config_reply *cp; 2258 1.15 bouyer struct mpii_ccb *ccb; 2259 1.15 bouyer struct mpii_cfg_hdr *hdr = p; 2260 1.15 bouyer struct mpii_ecfg_hdr *ehdr = p; 2261 1.15 bouyer int etype = 0; 2262 1.15 bouyer int rv = 0; 2263 1.1 bouyer 2264 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_req_cfg_header type: %#x number: %x " 2265 1.1 bouyer "address: 0x%08x flags: 0x%x\n", DEVNAME(sc), type, number, 2266 1.1 bouyer address, flags); 2267 1.1 bouyer 2268 1.15 bouyer ccb = mpii_get_ccb(sc); 2269 1.1 bouyer if (ccb == NULL) { 2270 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header ccb_get\n", 2271 1.1 bouyer DEVNAME(sc)); 2272 1.1 bouyer return (1); 2273 1.1 bouyer } 2274 1.1 bouyer 2275 1.1 bouyer if (ISSET(flags, MPII_PG_EXTENDED)) { 2276 1.1 bouyer etype = type; 2277 1.1 bouyer type = MPII_CONFIG_REQ_PAGE_TYPE_EXTENDED; 2278 1.1 bouyer } 2279 1.1 bouyer 2280 1.1 bouyer cq = ccb->ccb_cmd; 2281 1.1 bouyer 2282 1.1 bouyer cq->function = MPII_FUNCTION_CONFIG; 2283 1.1 bouyer 2284 1.1 bouyer cq->action = MPII_CONFIG_REQ_ACTION_PAGE_HEADER; 2285 1.1 bouyer 2286 1.1 bouyer cq->config_header.page_number = number; 2287 1.1 bouyer cq->config_header.page_type = type; 2288 1.1 bouyer cq->ext_page_type = etype; 2289 1.1 bouyer cq->page_address = htole32(address); 2290 1.1 bouyer cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE | 2291 1.1 bouyer MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL); 2292 1.1 bouyer 2293 1.1 bouyer ccb->ccb_done = mpii_empty_done; 2294 1.1 bouyer if (ISSET(flags, MPII_PG_POLL)) { 2295 1.1 bouyer if (mpii_poll(sc, ccb) != 0) { 2296 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n", 2297 1.1 bouyer DEVNAME(sc)); 2298 1.1 bouyer return (1); 2299 1.1 bouyer } 2300 1.1 bouyer } else 2301 1.1 bouyer mpii_wait(sc, ccb); 2302 1.1 bouyer 2303 1.1 bouyer if (ccb->ccb_rcb == NULL) { 2304 1.1 bouyer mpii_put_ccb(sc, ccb); 2305 1.1 bouyer return (1); 2306 1.1 bouyer } 2307 1.1 bouyer cp = ccb->ccb_rcb->rcb_reply; 2308 1.1 bouyer 2309 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: action: 0x%02x sgl_flags: 0x%02x " 2310 1.1 bouyer "msg_length: %d function: 0x%02x\n", DEVNAME(sc), cp->action, 2311 1.1 bouyer cp->sgl_flags, cp->msg_length, cp->function); 2312 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: ext_page_length: %d ext_page_type: 0x%02x " 2313 1.1 bouyer "msg_flags: 0x%02x\n", DEVNAME(sc), 2314 1.1 bouyer le16toh(cp->ext_page_length), cp->ext_page_type, 2315 1.1 bouyer cp->msg_flags); 2316 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc), 2317 1.15 bouyer cp->vp_id, cp->vf_id); 2318 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), 2319 1.1 bouyer le16toh(cp->ioc_status)); 2320 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 2321 1.1 bouyer le32toh(cp->ioc_loginfo)); 2322 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: page_version: 0x%02x page_length: %d " 2323 1.1 bouyer "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc), 2324 1.1 bouyer cp->config_header.page_version, 2325 1.1 bouyer cp->config_header.page_length, 2326 1.1 bouyer cp->config_header.page_number, 2327 1.1 bouyer cp->config_header.page_type); 2328 1.1 bouyer 2329 1.1 bouyer if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS) 2330 1.1 bouyer rv = 1; 2331 1.1 bouyer else if (ISSET(flags, MPII_PG_EXTENDED)) { 2332 1.15 bouyer memset(ehdr, 0, sizeof(*ehdr)); 2333 1.1 bouyer ehdr->page_version = cp->config_header.page_version; 2334 1.1 bouyer ehdr->page_number = cp->config_header.page_number; 2335 1.1 bouyer ehdr->page_type = cp->config_header.page_type; 2336 1.1 bouyer ehdr->ext_page_length = cp->ext_page_length; 2337 1.1 bouyer ehdr->ext_page_type = cp->ext_page_type; 2338 1.1 bouyer } else 2339 1.1 bouyer *hdr = cp->config_header; 2340 1.1 bouyer 2341 1.1 bouyer mpii_push_reply(sc, ccb->ccb_rcb); 2342 1.1 bouyer mpii_put_ccb(sc, ccb); 2343 1.1 bouyer 2344 1.1 bouyer return (rv); 2345 1.1 bouyer } 2346 1.1 bouyer 2347 1.24 maxv static int 2348 1.1 bouyer mpii_req_cfg_page(struct mpii_softc *sc, u_int32_t address, int flags, 2349 1.1 bouyer void *p, int read, void *page, size_t len) 2350 1.1 bouyer { 2351 1.1 bouyer struct mpii_msg_config_request *cq; 2352 1.1 bouyer struct mpii_msg_config_reply *cp; 2353 1.15 bouyer struct mpii_ccb *ccb; 2354 1.15 bouyer struct mpii_cfg_hdr *hdr = p; 2355 1.15 bouyer struct mpii_ecfg_hdr *ehdr = p; 2356 1.15 bouyer uintptr_t kva; 2357 1.15 bouyer int page_length; 2358 1.15 bouyer int rv = 0; 2359 1.1 bouyer 2360 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page address: %d read: %d " 2361 1.1 bouyer "type: %x\n", DEVNAME(sc), address, read, hdr->page_type); 2362 1.1 bouyer 2363 1.1 bouyer page_length = ISSET(flags, MPII_PG_EXTENDED) ? 2364 1.1 bouyer le16toh(ehdr->ext_page_length) : hdr->page_length; 2365 1.1 bouyer 2366 1.15 bouyer if (len > sc->sc_request_size - sizeof(*cq) || len < page_length * 4) 2367 1.1 bouyer return (1); 2368 1.1 bouyer 2369 1.15 bouyer ccb = mpii_get_ccb(sc); 2370 1.1 bouyer if (ccb == NULL) { 2371 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_page ccb_get\n", 2372 1.1 bouyer DEVNAME(sc)); 2373 1.1 bouyer return (1); 2374 1.1 bouyer } 2375 1.1 bouyer 2376 1.1 bouyer cq = ccb->ccb_cmd; 2377 1.1 bouyer 2378 1.1 bouyer cq->function = MPII_FUNCTION_CONFIG; 2379 1.1 bouyer 2380 1.1 bouyer cq->action = (read ? MPII_CONFIG_REQ_ACTION_PAGE_READ_CURRENT : 2381 1.1 bouyer MPII_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT); 2382 1.1 bouyer 2383 1.1 bouyer if (ISSET(flags, MPII_PG_EXTENDED)) { 2384 1.1 bouyer cq->config_header.page_version = ehdr->page_version; 2385 1.1 bouyer cq->config_header.page_number = ehdr->page_number; 2386 1.1 bouyer cq->config_header.page_type = ehdr->page_type; 2387 1.1 bouyer cq->ext_page_len = ehdr->ext_page_length; 2388 1.1 bouyer cq->ext_page_type = ehdr->ext_page_type; 2389 1.1 bouyer } else 2390 1.1 bouyer cq->config_header = *hdr; 2391 1.1 bouyer cq->config_header.page_type &= MPII_CONFIG_REQ_PAGE_TYPE_MASK; 2392 1.1 bouyer cq->page_address = htole32(address); 2393 1.1 bouyer cq->page_buffer.sg_hdr = htole32(MPII_SGE_FL_TYPE_SIMPLE | 2394 1.1 bouyer MPII_SGE_FL_LAST | MPII_SGE_FL_EOB | MPII_SGE_FL_EOL | 2395 1.1 bouyer MPII_SGE_FL_SIZE_64 | (page_length * 4) | 2396 1.1 bouyer (read ? MPII_SGE_FL_DIR_IN : MPII_SGE_FL_DIR_OUT)); 2397 1.1 bouyer 2398 1.1 bouyer /* bounce the page via the request space to avoid more bus_dma games */ 2399 1.15 bouyer mpii_dvatosge(&cq->page_buffer, ccb->ccb_cmd_dva + 2400 1.15 bouyer sizeof(struct mpii_msg_config_request)); 2401 1.1 bouyer 2402 1.15 bouyer kva = (uintptr_t)ccb->ccb_cmd; 2403 1.1 bouyer kva += sizeof(struct mpii_msg_config_request); 2404 1.1 bouyer 2405 1.1 bouyer if (!read) 2406 1.15 bouyer memcpy((void *)kva, page, len); 2407 1.1 bouyer 2408 1.1 bouyer ccb->ccb_done = mpii_empty_done; 2409 1.1 bouyer if (ISSET(flags, MPII_PG_POLL)) { 2410 1.1 bouyer if (mpii_poll(sc, ccb) != 0) { 2411 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_cfg_header poll\n", 2412 1.1 bouyer DEVNAME(sc)); 2413 1.1 bouyer return (1); 2414 1.1 bouyer } 2415 1.1 bouyer } else 2416 1.1 bouyer mpii_wait(sc, ccb); 2417 1.1 bouyer 2418 1.1 bouyer if (ccb->ccb_rcb == NULL) { 2419 1.1 bouyer mpii_put_ccb(sc, ccb); 2420 1.1 bouyer return (1); 2421 1.1 bouyer } 2422 1.1 bouyer cp = ccb->ccb_rcb->rcb_reply; 2423 1.1 bouyer 2424 1.15 bouyer DNPRINTF(MPII_D_MISC, "%s: action: 0x%02x msg_length: %d " 2425 1.15 bouyer "function: 0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, 2426 1.15 bouyer cp->function); 2427 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: ext_page_length: %d ext_page_type: 0x%02x " 2428 1.1 bouyer "msg_flags: 0x%02x\n", DEVNAME(sc), 2429 1.1 bouyer le16toh(cp->ext_page_length), cp->ext_page_type, 2430 1.1 bouyer cp->msg_flags); 2431 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc), 2432 1.1 bouyer cp->vp_id, cp->vf_id); 2433 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), 2434 1.1 bouyer le16toh(cp->ioc_status)); 2435 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 2436 1.1 bouyer le32toh(cp->ioc_loginfo)); 2437 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: page_version: 0x%02x page_length: %d " 2438 1.1 bouyer "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc), 2439 1.1 bouyer cp->config_header.page_version, 2440 1.1 bouyer cp->config_header.page_length, 2441 1.1 bouyer cp->config_header.page_number, 2442 1.1 bouyer cp->config_header.page_type); 2443 1.15 bouyer 2444 1.1 bouyer if (le16toh(cp->ioc_status) != MPII_IOCSTATUS_SUCCESS) 2445 1.1 bouyer rv = 1; 2446 1.1 bouyer else if (read) 2447 1.15 bouyer memcpy(page, (void *)kva, len); 2448 1.1 bouyer 2449 1.1 bouyer mpii_push_reply(sc, ccb->ccb_rcb); 2450 1.1 bouyer mpii_put_ccb(sc, ccb); 2451 1.1 bouyer 2452 1.1 bouyer return (rv); 2453 1.1 bouyer } 2454 1.1 bouyer 2455 1.24 maxv static struct mpii_rcb * 2456 1.1 bouyer mpii_reply(struct mpii_softc *sc, struct mpii_reply_descr *rdp) 2457 1.1 bouyer { 2458 1.1 bouyer struct mpii_rcb *rcb = NULL; 2459 1.1 bouyer u_int32_t rfid; 2460 1.1 bouyer 2461 1.15 bouyer KASSERT(mutex_owned(&sc->sc_rep_mtx)); 2462 1.1 bouyer DNPRINTF(MPII_D_INTR, "%s: mpii_reply\n", DEVNAME(sc)); 2463 1.1 bouyer 2464 1.1 bouyer if ((rdp->reply_flags & MPII_REPLY_DESCR_TYPE_MASK) == 2465 1.1 bouyer MPII_REPLY_DESCR_ADDRESS_REPLY) { 2466 1.1 bouyer rfid = (le32toh(rdp->frame_addr) - 2467 1.15 bouyer (u_int32_t)MPII_DMA_DVA(sc->sc_replies)) / 2468 1.15 bouyer sc->sc_reply_size; 2469 1.1 bouyer 2470 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, 2471 1.15 bouyer MPII_DMA_MAP(sc->sc_replies), sc->sc_reply_size * rfid, 2472 1.15 bouyer sc->sc_reply_size, BUS_DMASYNC_POSTREAD); 2473 1.1 bouyer 2474 1.1 bouyer rcb = &sc->sc_rcbs[rfid]; 2475 1.1 bouyer } 2476 1.1 bouyer 2477 1.1 bouyer memset(rdp, 0xff, sizeof(*rdp)); 2478 1.1 bouyer 2479 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_reply_postq), 2480 1.1 bouyer 8 * sc->sc_reply_post_host_index, 8, 2481 1.1 bouyer BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 2482 1.1 bouyer 2483 1.1 bouyer return (rcb); 2484 1.1 bouyer } 2485 1.1 bouyer 2486 1.24 maxv static struct mpii_dmamem * 2487 1.1 bouyer mpii_dmamem_alloc(struct mpii_softc *sc, size_t size) 2488 1.1 bouyer { 2489 1.1 bouyer struct mpii_dmamem *mdm; 2490 1.1 bouyer int nsegs; 2491 1.1 bouyer 2492 1.23 chs mdm = malloc(sizeof(*mdm), M_DEVBUF, M_WAITOK | M_ZERO); 2493 1.1 bouyer mdm->mdm_size = size; 2494 1.1 bouyer 2495 1.1 bouyer if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 2496 1.1 bouyer BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0) 2497 1.1 bouyer goto mdmfree; 2498 1.1 bouyer 2499 1.1 bouyer if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg, 2500 1.15 bouyer 1, &nsegs, BUS_DMA_NOWAIT) != 0) 2501 1.15 bouyer goto destroy; 2502 1.1 bouyer 2503 1.1 bouyer if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size, 2504 1.1 bouyer &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0) 2505 1.1 bouyer goto free; 2506 1.1 bouyer 2507 1.1 bouyer if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size, 2508 1.1 bouyer NULL, BUS_DMA_NOWAIT) != 0) 2509 1.1 bouyer goto unmap; 2510 1.1 bouyer 2511 1.15 bouyer memset(mdm->mdm_kva, 0, size); 2512 1.1 bouyer 2513 1.1 bouyer return (mdm); 2514 1.1 bouyer 2515 1.1 bouyer unmap: 2516 1.1 bouyer bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size); 2517 1.1 bouyer free: 2518 1.1 bouyer bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1); 2519 1.1 bouyer destroy: 2520 1.1 bouyer bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map); 2521 1.1 bouyer mdmfree: 2522 1.1 bouyer free(mdm, M_DEVBUF); 2523 1.1 bouyer 2524 1.1 bouyer return (NULL); 2525 1.1 bouyer } 2526 1.1 bouyer 2527 1.24 maxv static void 2528 1.1 bouyer mpii_dmamem_free(struct mpii_softc *sc, struct mpii_dmamem *mdm) 2529 1.1 bouyer { 2530 1.1 bouyer DNPRINTF(MPII_D_MEM, "%s: mpii_dmamem_free %p\n", DEVNAME(sc), mdm); 2531 1.1 bouyer 2532 1.1 bouyer bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map); 2533 1.1 bouyer bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size); 2534 1.1 bouyer bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1); 2535 1.1 bouyer bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map); 2536 1.1 bouyer free(mdm, M_DEVBUF); 2537 1.1 bouyer } 2538 1.1 bouyer 2539 1.24 maxv static int 2540 1.1 bouyer mpii_insert_dev(struct mpii_softc *sc, struct mpii_device *dev) 2541 1.1 bouyer { 2542 1.15 bouyer int slot; /* initial hint */ 2543 1.10 maya 2544 1.15 bouyer KASSERT(mutex_owned(&sc->sc_devs_mtx)); 2545 1.15 bouyer DNPRINTF(MPII_D_EVT, "%s: mpii_insert_dev wants slot %d\n", 2546 1.15 bouyer DEVNAME(sc), dev->slot); 2547 1.15 bouyer if (dev == NULL || dev->slot < 0) 2548 1.10 maya return (1); 2549 1.15 bouyer slot = dev->slot; 2550 1.1 bouyer 2551 1.1 bouyer while (slot < sc->sc_max_devices && sc->sc_devs[slot] != NULL) 2552 1.1 bouyer slot++; 2553 1.15 bouyer 2554 1.1 bouyer if (slot >= sc->sc_max_devices) 2555 1.1 bouyer return (1); 2556 1.15 bouyer 2557 1.15 bouyer DNPRINTF(MPII_D_EVT, "%s: mpii_insert_dev alloc slot %d\n", 2558 1.15 bouyer DEVNAME(sc), slot); 2559 1.15 bouyer 2560 1.1 bouyer dev->slot = slot; 2561 1.1 bouyer sc->sc_devs[slot] = dev; 2562 1.15 bouyer 2563 1.1 bouyer return (0); 2564 1.1 bouyer } 2565 1.1 bouyer 2566 1.24 maxv static int 2567 1.1 bouyer mpii_remove_dev(struct mpii_softc *sc, struct mpii_device *dev) 2568 1.1 bouyer { 2569 1.1 bouyer int i; 2570 1.1 bouyer 2571 1.15 bouyer KASSERT(mutex_owned(&sc->sc_devs_mtx)); 2572 1.15 bouyer if (dev == NULL) 2573 1.1 bouyer return (1); 2574 1.15 bouyer 2575 1.15 bouyer for (i = 0; i < sc->sc_max_devices; i++) { 2576 1.15 bouyer if (sc->sc_devs[i] == NULL) 2577 1.15 bouyer continue; 2578 1.15 bouyer 2579 1.15 bouyer if (sc->sc_devs[i]->dev_handle == dev->dev_handle) { 2580 1.1 bouyer sc->sc_devs[i] = NULL; 2581 1.1 bouyer return (0); 2582 1.1 bouyer } 2583 1.15 bouyer } 2584 1.15 bouyer 2585 1.1 bouyer return (1); 2586 1.1 bouyer } 2587 1.1 bouyer 2588 1.24 maxv static struct mpii_device * 2589 1.1 bouyer mpii_find_dev(struct mpii_softc *sc, u_int16_t handle) 2590 1.1 bouyer { 2591 1.1 bouyer int i; 2592 1.15 bouyer KASSERT(mutex_owned(&sc->sc_devs_mtx)); 2593 1.1 bouyer 2594 1.15 bouyer for (i = 0; i < sc->sc_max_devices; i++) { 2595 1.15 bouyer if (sc->sc_devs[i] == NULL) 2596 1.15 bouyer continue; 2597 1.15 bouyer 2598 1.15 bouyer if (sc->sc_devs[i]->dev_handle == handle) 2599 1.1 bouyer return (sc->sc_devs[i]); 2600 1.15 bouyer } 2601 1.15 bouyer 2602 1.1 bouyer return (NULL); 2603 1.1 bouyer } 2604 1.1 bouyer 2605 1.24 maxv static int 2606 1.1 bouyer mpii_alloc_ccbs(struct mpii_softc *sc) 2607 1.1 bouyer { 2608 1.1 bouyer struct mpii_ccb *ccb; 2609 1.1 bouyer u_int8_t *cmd; 2610 1.1 bouyer int i; 2611 1.15 bouyer char wqname[16]; 2612 1.1 bouyer 2613 1.1 bouyer SIMPLEQ_INIT(&sc->sc_ccb_free); 2614 1.15 bouyer SIMPLEQ_INIT(&sc->sc_ccb_tmos); 2615 1.15 bouyer mutex_init(&sc->sc_ccb_free_mtx, MUTEX_DEFAULT, IPL_BIO); 2616 1.15 bouyer cv_init(&sc->sc_ccb_free_cv, "mpii_ccbs"); 2617 1.15 bouyer mutex_init(&sc->sc_ssb_tmomtx, MUTEX_DEFAULT, IPL_BIO); 2618 1.15 bouyer snprintf(wqname, sizeof(wqname) - 1, "%sabrt", DEVNAME(sc)); 2619 1.15 bouyer workqueue_create(&sc->sc_ssb_tmowk, wqname, mpii_scsi_cmd_tmo_handler, 2620 1.15 bouyer sc, PRI_BIO, IPL_BIO, WQ_MPSAFE); 2621 1.15 bouyer if (sc->sc_ssb_tmowk == NULL) 2622 1.15 bouyer return 1; 2623 1.1 bouyer 2624 1.15 bouyer sc->sc_ccbs = malloc((sc->sc_max_cmds-1) * sizeof(*ccb), 2625 1.23 chs M_DEVBUF, M_WAITOK | M_ZERO); 2626 1.1 bouyer sc->sc_requests = mpii_dmamem_alloc(sc, 2627 1.15 bouyer sc->sc_request_size * sc->sc_max_cmds); 2628 1.1 bouyer if (sc->sc_requests == NULL) { 2629 1.1 bouyer printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc)); 2630 1.1 bouyer goto free_ccbs; 2631 1.1 bouyer } 2632 1.1 bouyer cmd = MPII_DMA_KVA(sc->sc_requests); 2633 1.1 bouyer 2634 1.1 bouyer /* 2635 1.15 bouyer * we have sc->sc_max_cmds system request message 2636 1.1 bouyer * frames, but smid zero cannot be used. so we then 2637 1.15 bouyer * have (sc->sc_max_cmds - 1) number of ccbs 2638 1.1 bouyer */ 2639 1.15 bouyer for (i = 1; i < sc->sc_max_cmds; i++) { 2640 1.1 bouyer ccb = &sc->sc_ccbs[i - 1]; 2641 1.1 bouyer 2642 1.15 bouyer if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, sc->sc_max_sgl, 2643 1.15 bouyer MAXPHYS, 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, 2644 1.1 bouyer &ccb->ccb_dmamap) != 0) { 2645 1.1 bouyer printf("%s: unable to create dma map\n", DEVNAME(sc)); 2646 1.1 bouyer goto free_maps; 2647 1.1 bouyer } 2648 1.1 bouyer 2649 1.1 bouyer ccb->ccb_sc = sc; 2650 1.15 bouyer mutex_init(&ccb->ccb_mtx, MUTEX_DEFAULT, IPL_BIO); 2651 1.15 bouyer cv_init(&ccb->ccb_cv, "mpiiexec"); 2652 1.15 bouyer 2653 1.15 bouyer ccb->ccb_smid = htole16(i); 2654 1.15 bouyer ccb->ccb_offset = sc->sc_request_size * i; 2655 1.1 bouyer 2656 1.1 bouyer ccb->ccb_cmd = &cmd[ccb->ccb_offset]; 2657 1.1 bouyer ccb->ccb_cmd_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_requests) + 2658 1.1 bouyer ccb->ccb_offset; 2659 1.1 bouyer 2660 1.1 bouyer DNPRINTF(MPII_D_CCB, "%s: mpii_alloc_ccbs(%d) ccb: %p map: %p " 2661 1.15 bouyer "sc: %p smid: %#x offs: %#lx cmd: %p dva: %#lx\n", 2662 1.1 bouyer DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc, 2663 1.15 bouyer ccb->ccb_smid, ccb->ccb_offset, ccb->ccb_cmd, 2664 1.15 bouyer ccb->ccb_cmd_dva); 2665 1.1 bouyer 2666 1.1 bouyer mpii_put_ccb(sc, ccb); 2667 1.1 bouyer } 2668 1.1 bouyer 2669 1.1 bouyer return (0); 2670 1.1 bouyer 2671 1.1 bouyer free_maps: 2672 1.15 bouyer while ((ccb = mpii_get_ccb(sc)) != NULL) 2673 1.1 bouyer bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 2674 1.1 bouyer 2675 1.1 bouyer mpii_dmamem_free(sc, sc->sc_requests); 2676 1.1 bouyer free_ccbs: 2677 1.1 bouyer free(sc->sc_ccbs, M_DEVBUF); 2678 1.1 bouyer 2679 1.1 bouyer return (1); 2680 1.1 bouyer } 2681 1.1 bouyer 2682 1.24 maxv static void 2683 1.1 bouyer mpii_put_ccb(struct mpii_softc *sc, struct mpii_ccb *ccb) 2684 1.1 bouyer { 2685 1.1 bouyer DNPRINTF(MPII_D_CCB, "%s: mpii_put_ccb %p\n", DEVNAME(sc), ccb); 2686 1.1 bouyer 2687 1.1 bouyer ccb->ccb_state = MPII_CCB_FREE; 2688 1.1 bouyer ccb->ccb_cookie = NULL; 2689 1.1 bouyer ccb->ccb_done = NULL; 2690 1.1 bouyer ccb->ccb_rcb = NULL; 2691 1.15 bouyer memset(ccb->ccb_cmd, 0, sc->sc_request_size); 2692 1.1 bouyer 2693 1.1 bouyer mutex_enter(&sc->sc_ccb_free_mtx); 2694 1.15 bouyer SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ccb, ccb_link); 2695 1.1 bouyer mutex_exit(&sc->sc_ccb_free_mtx); 2696 1.1 bouyer } 2697 1.1 bouyer 2698 1.24 maxv static struct mpii_ccb * 2699 1.15 bouyer mpii_get_ccb(struct mpii_softc *sc) 2700 1.1 bouyer { 2701 1.1 bouyer struct mpii_ccb *ccb; 2702 1.1 bouyer 2703 1.1 bouyer mutex_enter(&sc->sc_ccb_free_mtx); 2704 1.15 bouyer ccb = SIMPLEQ_FIRST(&sc->sc_ccb_free); 2705 1.1 bouyer if (ccb != NULL) { 2706 1.15 bouyer SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ccb_link); 2707 1.1 bouyer ccb->ccb_state = MPII_CCB_READY; 2708 1.1 bouyer KASSERT(ccb->ccb_sc == sc); 2709 1.1 bouyer } 2710 1.1 bouyer mutex_exit(&sc->sc_ccb_free_mtx); 2711 1.1 bouyer 2712 1.1 bouyer DNPRINTF(MPII_D_CCB, "%s: mpii_get_ccb %p\n", DEVNAME(sc), ccb); 2713 1.1 bouyer 2714 1.1 bouyer return (ccb); 2715 1.1 bouyer } 2716 1.1 bouyer 2717 1.24 maxv static int 2718 1.1 bouyer mpii_alloc_replies(struct mpii_softc *sc) 2719 1.1 bouyer { 2720 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_replies\n", DEVNAME(sc)); 2721 1.1 bouyer 2722 1.1 bouyer sc->sc_rcbs = malloc(sc->sc_num_reply_frames * sizeof(struct mpii_rcb), 2723 1.23 chs M_DEVBUF, M_WAITOK); 2724 1.1 bouyer 2725 1.15 bouyer sc->sc_replies = mpii_dmamem_alloc(sc, sc->sc_reply_size * 2726 1.1 bouyer sc->sc_num_reply_frames); 2727 1.1 bouyer if (sc->sc_replies == NULL) { 2728 1.1 bouyer free(sc->sc_rcbs, M_DEVBUF); 2729 1.1 bouyer return (1); 2730 1.1 bouyer } 2731 1.1 bouyer 2732 1.1 bouyer return (0); 2733 1.1 bouyer } 2734 1.1 bouyer 2735 1.24 maxv static void 2736 1.1 bouyer mpii_push_replies(struct mpii_softc *sc) 2737 1.1 bouyer { 2738 1.1 bouyer struct mpii_rcb *rcb; 2739 1.15 bouyer uintptr_t kva = (uintptr_t)MPII_DMA_KVA(sc->sc_replies); 2740 1.1 bouyer int i; 2741 1.1 bouyer 2742 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_replies), 2743 1.15 bouyer 0, sc->sc_reply_size * sc->sc_num_reply_frames, 2744 1.15 bouyer BUS_DMASYNC_PREREAD); 2745 1.1 bouyer 2746 1.1 bouyer for (i = 0; i < sc->sc_num_reply_frames; i++) { 2747 1.1 bouyer rcb = &sc->sc_rcbs[i]; 2748 1.1 bouyer 2749 1.15 bouyer rcb->rcb_reply = (void *)(kva + sc->sc_reply_size * i); 2750 1.1 bouyer rcb->rcb_reply_dva = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) + 2751 1.15 bouyer sc->sc_reply_size * i; 2752 1.1 bouyer mpii_push_reply(sc, rcb); 2753 1.1 bouyer } 2754 1.1 bouyer } 2755 1.1 bouyer 2756 1.24 maxv static void 2757 1.1 bouyer mpii_start(struct mpii_softc *sc, struct mpii_ccb *ccb) 2758 1.1 bouyer { 2759 1.1 bouyer struct mpii_request_header *rhp; 2760 1.1 bouyer struct mpii_request_descr descr; 2761 1.15 bouyer #if defined(__LP64__) && 0 2762 1.15 bouyer u_long *rdp = (u_long *)&descr; 2763 1.15 bouyer #else 2764 1.15 bouyer u_int32_t *rdp = (u_int32_t *)&descr; 2765 1.15 bouyer #endif 2766 1.15 bouyer 2767 1.15 bouyer DNPRINTF(MPII_D_RW, "%s: mpii_start %#lx\n", DEVNAME(sc), 2768 1.15 bouyer ccb->ccb_cmd_dva); 2769 1.1 bouyer 2770 1.15 bouyer bus_dmamap_sync(sc->sc_dmat, MPII_DMA_MAP(sc->sc_requests), 2771 1.15 bouyer ccb->ccb_offset, sc->sc_request_size, 2772 1.15 bouyer BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2773 1.15 bouyer 2774 1.15 bouyer ccb->ccb_state = MPII_CCB_QUEUED; 2775 1.1 bouyer 2776 1.1 bouyer rhp = ccb->ccb_cmd; 2777 1.1 bouyer 2778 1.15 bouyer memset(&descr, 0, sizeof(descr)); 2779 1.1 bouyer 2780 1.1 bouyer switch (rhp->function) { 2781 1.1 bouyer case MPII_FUNCTION_SCSI_IO_REQUEST: 2782 1.1 bouyer descr.request_flags = MPII_REQ_DESCR_SCSI_IO; 2783 1.1 bouyer descr.dev_handle = htole16(ccb->ccb_dev_handle); 2784 1.1 bouyer break; 2785 1.1 bouyer case MPII_FUNCTION_SCSI_TASK_MGMT: 2786 1.1 bouyer descr.request_flags = MPII_REQ_DESCR_HIGH_PRIORITY; 2787 1.1 bouyer break; 2788 1.1 bouyer default: 2789 1.1 bouyer descr.request_flags = MPII_REQ_DESCR_DEFAULT; 2790 1.1 bouyer } 2791 1.1 bouyer 2792 1.1 bouyer descr.vf_id = sc->sc_vf_id; 2793 1.15 bouyer descr.smid = ccb->ccb_smid; 2794 1.1 bouyer 2795 1.15 bouyer #if defined(__LP64__) && 0 2796 1.15 bouyer DNPRINTF(MPII_D_RW, "%s: MPII_REQ_DESCR_POST_LOW (0x%08x) write " 2797 1.15 bouyer "0x%08lx\n", DEVNAME(sc), MPII_REQ_DESCR_POST_LOW, *rdp); 2798 1.15 bouyer bus_space_write_raw_8(sc->sc_iot, sc->sc_ioh, 2799 1.15 bouyer MPII_REQ_DESCR_POST_LOW, *rdp); 2800 1.15 bouyer #else 2801 1.1 bouyer DNPRINTF(MPII_D_RW, "%s: MPII_REQ_DESCR_POST_LOW (0x%08x) write " 2802 1.15 bouyer "0x%04x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_LOW, *rdp); 2803 1.1 bouyer 2804 1.1 bouyer DNPRINTF(MPII_D_RW, "%s: MPII_REQ_DESCR_POST_HIGH (0x%08x) write " 2805 1.15 bouyer "0x%04x\n", DEVNAME(sc), MPII_REQ_DESCR_POST_HIGH, *(rdp+1)); 2806 1.1 bouyer 2807 1.1 bouyer mutex_enter(&sc->sc_req_mtx); 2808 1.15 bouyer bus_space_write_4(sc->sc_iot, sc->sc_ioh, 2809 1.15 bouyer MPII_REQ_DESCR_POST_LOW, rdp[0]); 2810 1.15 bouyer bus_space_barrier(sc->sc_iot, sc->sc_ioh, 2811 1.15 bouyer MPII_REQ_DESCR_POST_LOW, 8, BUS_SPACE_BARRIER_WRITE); 2812 1.15 bouyer 2813 1.15 bouyer bus_space_write_4(sc->sc_iot, sc->sc_ioh, 2814 1.15 bouyer MPII_REQ_DESCR_POST_HIGH, rdp[1]); 2815 1.15 bouyer bus_space_barrier(sc->sc_iot, sc->sc_ioh, 2816 1.15 bouyer MPII_REQ_DESCR_POST_LOW, 8, BUS_SPACE_BARRIER_WRITE); 2817 1.1 bouyer mutex_exit(&sc->sc_req_mtx); 2818 1.15 bouyer #endif 2819 1.1 bouyer } 2820 1.1 bouyer 2821 1.24 maxv static int 2822 1.1 bouyer mpii_poll(struct mpii_softc *sc, struct mpii_ccb *ccb) 2823 1.1 bouyer { 2824 1.1 bouyer void (*done)(struct mpii_ccb *); 2825 1.1 bouyer void *cookie; 2826 1.1 bouyer int rv = 1; 2827 1.1 bouyer 2828 1.15 bouyer DNPRINTF(MPII_D_INTR, "%s: mpii_poll\n", DEVNAME(sc)); 2829 1.1 bouyer 2830 1.1 bouyer done = ccb->ccb_done; 2831 1.1 bouyer cookie = ccb->ccb_cookie; 2832 1.1 bouyer 2833 1.1 bouyer ccb->ccb_done = mpii_poll_done; 2834 1.1 bouyer ccb->ccb_cookie = &rv; 2835 1.1 bouyer 2836 1.1 bouyer mpii_start(sc, ccb); 2837 1.1 bouyer 2838 1.1 bouyer while (rv == 1) { 2839 1.1 bouyer /* avoid excessive polling */ 2840 1.1 bouyer if (mpii_reply_waiting(sc)) 2841 1.1 bouyer mpii_intr(sc); 2842 1.1 bouyer else 2843 1.1 bouyer delay(10); 2844 1.1 bouyer } 2845 1.1 bouyer 2846 1.1 bouyer ccb->ccb_cookie = cookie; 2847 1.1 bouyer done(ccb); 2848 1.1 bouyer 2849 1.1 bouyer return (0); 2850 1.1 bouyer } 2851 1.1 bouyer 2852 1.24 maxv static void 2853 1.1 bouyer mpii_poll_done(struct mpii_ccb *ccb) 2854 1.1 bouyer { 2855 1.1 bouyer int *rv = ccb->ccb_cookie; 2856 1.1 bouyer 2857 1.1 bouyer *rv = 0; 2858 1.1 bouyer } 2859 1.1 bouyer 2860 1.24 maxv static int 2861 1.1 bouyer mpii_alloc_queues(struct mpii_softc *sc) 2862 1.1 bouyer { 2863 1.15 bouyer u_int32_t *rfp; 2864 1.1 bouyer int i; 2865 1.15 bouyer 2866 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_alloc_queues\n", DEVNAME(sc)); 2867 1.1 bouyer 2868 1.15 bouyer mutex_init(&sc->sc_reply_free_mtx, MUTEX_DEFAULT, IPL_BIO); 2869 1.1 bouyer sc->sc_reply_freeq = mpii_dmamem_alloc(sc, 2870 1.15 bouyer sc->sc_reply_free_qdepth * sizeof(*rfp)); 2871 1.1 bouyer if (sc->sc_reply_freeq == NULL) 2872 1.1 bouyer return (1); 2873 1.15 bouyer rfp = MPII_DMA_KVA(sc->sc_reply_freeq); 2874 1.1 bouyer for (i = 0; i < sc->sc_num_reply_frames; i++) { 2875 1.15 bouyer rfp[i] = (u_int32_t)MPII_DMA_DVA(sc->sc_replies) + 2876 1.15 bouyer sc->sc_reply_size * i; 2877 1.1 bouyer } 2878 1.1 bouyer 2879 1.15 bouyer sc->sc_reply_postq = mpii_dmamem_alloc(sc, 2880 1.15 bouyer sc->sc_reply_post_qdepth * sizeof(struct mpii_reply_descr)); 2881 1.1 bouyer if (sc->sc_reply_postq == NULL) 2882 1.1 bouyer goto free_reply_freeq; 2883 1.1 bouyer sc->sc_reply_postq_kva = MPII_DMA_KVA(sc->sc_reply_postq); 2884 1.15 bouyer memset(sc->sc_reply_postq_kva, 0xff, sc->sc_reply_post_qdepth * 2885 1.15 bouyer sizeof(struct mpii_reply_descr)); 2886 1.1 bouyer 2887 1.1 bouyer return (0); 2888 1.1 bouyer 2889 1.1 bouyer free_reply_freeq: 2890 1.1 bouyer mpii_dmamem_free(sc, sc->sc_reply_freeq); 2891 1.1 bouyer return (1); 2892 1.1 bouyer } 2893 1.1 bouyer 2894 1.24 maxv static void 2895 1.1 bouyer mpii_init_queues(struct mpii_softc *sc) 2896 1.1 bouyer { 2897 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_init_queues\n", DEVNAME(sc)); 2898 1.1 bouyer 2899 1.1 bouyer sc->sc_reply_free_host_index = sc->sc_reply_free_qdepth - 1; 2900 1.1 bouyer sc->sc_reply_post_host_index = 0; 2901 1.1 bouyer mpii_write_reply_free(sc, sc->sc_reply_free_host_index); 2902 1.1 bouyer mpii_write_reply_post(sc, sc->sc_reply_post_host_index); 2903 1.1 bouyer } 2904 1.1 bouyer 2905 1.24 maxv static void 2906 1.1 bouyer mpii_wait(struct mpii_softc *sc, struct mpii_ccb *ccb) 2907 1.1 bouyer { 2908 1.1 bouyer void (*done)(struct mpii_ccb *); 2909 1.1 bouyer void *cookie; 2910 1.1 bouyer 2911 1.1 bouyer done = ccb->ccb_done; 2912 1.1 bouyer cookie = ccb->ccb_cookie; 2913 1.1 bouyer 2914 1.1 bouyer ccb->ccb_done = mpii_wait_done; 2915 1.15 bouyer ccb->ccb_cookie = ccb; 2916 1.1 bouyer 2917 1.1 bouyer /* XXX this will wait forever for the ccb to complete */ 2918 1.1 bouyer 2919 1.1 bouyer mpii_start(sc, ccb); 2920 1.1 bouyer 2921 1.15 bouyer mutex_enter(&ccb->ccb_mtx); 2922 1.15 bouyer while (ccb->ccb_cookie != NULL) 2923 1.15 bouyer cv_wait(&ccb->ccb_cv, &ccb->ccb_mtx); 2924 1.15 bouyer mutex_exit(&ccb->ccb_mtx); 2925 1.1 bouyer 2926 1.1 bouyer ccb->ccb_cookie = cookie; 2927 1.1 bouyer done(ccb); 2928 1.1 bouyer } 2929 1.1 bouyer 2930 1.24 maxv static void 2931 1.1 bouyer mpii_wait_done(struct mpii_ccb *ccb) 2932 1.1 bouyer { 2933 1.15 bouyer mutex_enter(&ccb->ccb_mtx); 2934 1.1 bouyer ccb->ccb_cookie = NULL; 2935 1.15 bouyer cv_signal(&ccb->ccb_cv); 2936 1.15 bouyer mutex_exit(&ccb->ccb_mtx); 2937 1.1 bouyer } 2938 1.1 bouyer 2939 1.24 maxv static void 2940 1.1 bouyer mpii_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 2941 1.1 bouyer void *arg) 2942 1.1 bouyer { 2943 1.1 bouyer struct scsipi_periph *periph; 2944 1.1 bouyer struct scsipi_xfer *xs; 2945 1.1 bouyer struct scsipi_adapter *adapt = chan->chan_adapter; 2946 1.1 bouyer struct mpii_softc *sc = device_private(adapt->adapt_dev); 2947 1.1 bouyer struct mpii_ccb *ccb; 2948 1.1 bouyer struct mpii_msg_scsi_io *io; 2949 1.1 bouyer struct mpii_device *dev; 2950 1.15 bouyer int target, timeout, ret; 2951 1.15 bouyer u_int16_t dev_handle; 2952 1.1 bouyer 2953 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: mpii_scsipi_request\n", DEVNAME(sc)); 2954 1.15 bouyer 2955 1.1 bouyer switch (req) { 2956 1.1 bouyer case ADAPTER_REQ_GROW_RESOURCES: 2957 1.27 skrll /* Not supported. */ 2958 1.1 bouyer return; 2959 1.1 bouyer case ADAPTER_REQ_SET_XFER_MODE: 2960 1.1 bouyer { 2961 1.1 bouyer struct scsipi_xfer_mode *xm = arg; 2962 1.1 bouyer xm->xm_mode = PERIPH_CAP_TQING; 2963 1.27 skrll xm->xm_period = 0; 2964 1.27 skrll xm->xm_offset = 0; 2965 1.1 bouyer scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm); 2966 1.1 bouyer return; 2967 1.1 bouyer } 2968 1.27 skrll case ADAPTER_REQ_RUN_XFER: 2969 1.1 bouyer break; 2970 1.1 bouyer } 2971 1.1 bouyer 2972 1.1 bouyer xs = arg; 2973 1.1 bouyer periph = xs->xs_periph; 2974 1.1 bouyer target = periph->periph_target; 2975 1.1 bouyer 2976 1.1 bouyer if (xs->cmdlen > MPII_CDB_LEN) { 2977 1.15 bouyer DNPRINTF(MPII_D_CMD, "%s: CDB too big %d\n", 2978 1.1 bouyer DEVNAME(sc), xs->cmdlen); 2979 1.15 bouyer memset(&xs->sense, 0, sizeof(xs->sense)); 2980 1.1 bouyer xs->sense.scsi_sense.response_code = 2981 1.1 bouyer SSD_RCODE_VALID | SSD_RCODE_CURRENT; 2982 1.1 bouyer xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST; 2983 1.1 bouyer xs->sense.scsi_sense.asc = 0x20; 2984 1.1 bouyer xs->error = XS_SENSE; 2985 1.1 bouyer scsipi_done(xs); 2986 1.1 bouyer return; 2987 1.1 bouyer } 2988 1.1 bouyer 2989 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 2990 1.1 bouyer if ((dev = sc->sc_devs[target]) == NULL) { 2991 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 2992 1.1 bouyer /* device no longer exists */ 2993 1.1 bouyer xs->error = XS_SELTIMEOUT; 2994 1.1 bouyer scsipi_done(xs); 2995 1.1 bouyer return; 2996 1.1 bouyer } 2997 1.15 bouyer dev_handle = dev->dev_handle; 2998 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 2999 1.1 bouyer 3000 1.15 bouyer ccb = mpii_get_ccb(sc); 3001 1.1 bouyer if (ccb == NULL) { 3002 1.1 bouyer xs->error = XS_RESOURCE_SHORTAGE; 3003 1.1 bouyer scsipi_done(xs); 3004 1.1 bouyer return; 3005 1.1 bouyer } 3006 1.22 kardel DNPRINTF(MPII_D_CMD, "%s: ccb_smid: %d xs->cmd->opcode: 0x%02x xs->xs_control: 0x%x\n", 3007 1.22 kardel DEVNAME(sc), ccb->ccb_smid, xs->cmd->opcode, xs->xs_control); 3008 1.1 bouyer 3009 1.1 bouyer ccb->ccb_cookie = xs; 3010 1.1 bouyer ccb->ccb_done = mpii_scsi_cmd_done; 3011 1.15 bouyer ccb->ccb_dev_handle = dev_handle; 3012 1.1 bouyer 3013 1.15 bouyer io = ccb->ccb_cmd; 3014 1.15 bouyer memset(io, 0, sizeof(*io)); 3015 1.1 bouyer io->function = MPII_FUNCTION_SCSI_IO_REQUEST; 3016 1.1 bouyer io->sense_buffer_length = sizeof(xs->sense); 3017 1.15 bouyer io->sgl_offset0 = sizeof(struct mpii_msg_scsi_io) / 4; 3018 1.1 bouyer io->io_flags = htole16(xs->cmdlen); 3019 1.1 bouyer io->dev_handle = htole16(ccb->ccb_dev_handle); 3020 1.19 kardel io->lun[0] = htobe16(periph->periph_lun); 3021 1.1 bouyer 3022 1.1 bouyer switch (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) { 3023 1.1 bouyer case XS_CTL_DATA_IN: 3024 1.1 bouyer io->direction = MPII_SCSIIO_DIR_READ; 3025 1.1 bouyer break; 3026 1.1 bouyer case XS_CTL_DATA_OUT: 3027 1.1 bouyer io->direction = MPII_SCSIIO_DIR_WRITE; 3028 1.1 bouyer break; 3029 1.1 bouyer default: 3030 1.1 bouyer io->direction = MPII_SCSIIO_DIR_NONE; 3031 1.15 bouyer break; 3032 1.1 bouyer } 3033 1.1 bouyer 3034 1.1 bouyer io->tagging = MPII_SCSIIO_ATTR_SIMPLE_Q; 3035 1.1 bouyer 3036 1.1 bouyer memcpy(io->cdb, xs->cmd, xs->cmdlen); 3037 1.1 bouyer 3038 1.1 bouyer io->data_length = htole32(xs->datalen); 3039 1.1 bouyer 3040 1.15 bouyer /* sense data is at the end of a request */ 3041 1.1 bouyer io->sense_buffer_low_address = htole32(ccb->ccb_cmd_dva + 3042 1.15 bouyer sc->sc_request_size - sizeof(struct scsi_sense_data)); 3043 1.15 bouyer 3044 1.15 bouyer if (ISSET(sc->sc_flags, MPII_F_SAS3)) 3045 1.15 bouyer ret = mpii_load_xs_sas3(ccb); 3046 1.15 bouyer else 3047 1.15 bouyer ret = mpii_load_xs(ccb); 3048 1.1 bouyer 3049 1.15 bouyer if (ret != 0) { 3050 1.1 bouyer xs->error = XS_DRIVER_STUFFUP; 3051 1.15 bouyer goto done; 3052 1.1 bouyer } 3053 1.1 bouyer 3054 1.1 bouyer if (xs->xs_control & XS_CTL_POLL) { 3055 1.1 bouyer if (mpii_poll(sc, ccb) != 0) { 3056 1.1 bouyer xs->error = XS_DRIVER_STUFFUP; 3057 1.15 bouyer goto done; 3058 1.1 bouyer } 3059 1.1 bouyer return; 3060 1.1 bouyer } 3061 1.15 bouyer timeout = mstohz(xs->timeout); 3062 1.1 bouyer if (timeout == 0) 3063 1.1 bouyer timeout = 1; 3064 1.1 bouyer callout_reset(&xs->xs_callout, timeout, mpii_scsi_cmd_tmo, ccb); 3065 1.1 bouyer mpii_start(sc, ccb); 3066 1.15 bouyer return; 3067 1.15 bouyer done: 3068 1.15 bouyer mpii_put_ccb(sc, ccb); 3069 1.15 bouyer scsipi_done(xs); 3070 1.1 bouyer } 3071 1.1 bouyer 3072 1.24 maxv static void 3073 1.1 bouyer mpii_scsi_cmd_tmo(void *xccb) 3074 1.1 bouyer { 3075 1.1 bouyer struct mpii_ccb *ccb = xccb; 3076 1.1 bouyer struct mpii_softc *sc = ccb->ccb_sc; 3077 1.15 bouyer bool start_work; 3078 1.1 bouyer 3079 1.1 bouyer printf("%s: mpii_scsi_cmd_tmo\n", DEVNAME(sc)); 3080 1.1 bouyer 3081 1.1 bouyer if (ccb->ccb_state == MPII_CCB_QUEUED) { 3082 1.15 bouyer mutex_enter(&sc->sc_ssb_tmomtx); 3083 1.15 bouyer start_work = (SIMPLEQ_FIRST(&sc->sc_ccb_tmos) == 0); 3084 1.1 bouyer ccb->ccb_state = MPII_CCB_TIMEOUT; 3085 1.15 bouyer SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_tmos, ccb, ccb_link); 3086 1.15 bouyer if (start_work) { 3087 1.15 bouyer workqueue_enqueue(sc->sc_ssb_tmowk, 3088 1.15 bouyer &sc->sc_ssb_tmowork, NULL); 3089 1.15 bouyer } 3090 1.15 bouyer mutex_exit(&sc->sc_ssb_tmomtx); 3091 1.1 bouyer } 3092 1.1 bouyer } 3093 1.1 bouyer 3094 1.24 maxv static void 3095 1.1 bouyer mpii_scsi_cmd_tmo_handler(struct work *wk, void *cookie) 3096 1.1 bouyer { 3097 1.1 bouyer struct mpii_softc *sc = cookie; 3098 1.15 bouyer struct mpii_ccb *next; 3099 1.15 bouyer struct mpii_ccb *ccb; 3100 1.1 bouyer struct mpii_ccb *tccb; 3101 1.1 bouyer struct mpii_msg_scsi_task_request *stq; 3102 1.1 bouyer 3103 1.15 bouyer mutex_enter(&sc->sc_ssb_tmomtx); 3104 1.15 bouyer next = SIMPLEQ_FIRST(&sc->sc_ccb_tmos); 3105 1.15 bouyer SIMPLEQ_INIT(&sc->sc_ccb_tmos); 3106 1.15 bouyer mutex_exit(&sc->sc_ssb_tmomtx); 3107 1.15 bouyer 3108 1.15 bouyer while (next != NULL) { 3109 1.15 bouyer ccb = next; 3110 1.15 bouyer next = SIMPLEQ_NEXT(ccb, ccb_link); 3111 1.15 bouyer if (ccb->ccb_state != MPII_CCB_TIMEOUT) 3112 1.15 bouyer continue; 3113 1.15 bouyer tccb = mpii_get_ccb(sc); 3114 1.15 bouyer stq = tccb->ccb_cmd; 3115 1.15 bouyer stq->function = MPII_FUNCTION_SCSI_TASK_MGMT; 3116 1.15 bouyer stq->task_type = MPII_SCSI_TASK_TARGET_RESET; 3117 1.15 bouyer stq->dev_handle = htole16(ccb->ccb_dev_handle); 3118 1.1 bouyer 3119 1.15 bouyer tccb->ccb_done = mpii_scsi_cmd_tmo_done; 3120 1.15 bouyer mpii_wait(sc, tccb); 3121 1.1 bouyer } 3122 1.1 bouyer } 3123 1.1 bouyer 3124 1.24 maxv static void 3125 1.1 bouyer mpii_scsi_cmd_tmo_done(struct mpii_ccb *tccb) 3126 1.1 bouyer { 3127 1.15 bouyer mpii_put_ccb(tccb->ccb_sc, tccb); 3128 1.1 bouyer } 3129 1.1 bouyer 3130 1.3 kardel static u_int8_t 3131 1.3 kardel map_scsi_status(u_int8_t mpii_scsi_status) 3132 1.3 kardel { 3133 1.3 kardel u_int8_t scsi_status; 3134 1.27 skrll 3135 1.27 skrll switch (mpii_scsi_status) 3136 1.3 kardel { 3137 1.15 bouyer case MPII_SCSIIO_STATUS_GOOD: 3138 1.3 kardel scsi_status = SCSI_OK; 3139 1.3 kardel break; 3140 1.27 skrll 3141 1.15 bouyer case MPII_SCSIIO_STATUS_CHECK_COND: 3142 1.3 kardel scsi_status = SCSI_CHECK; 3143 1.3 kardel break; 3144 1.27 skrll 3145 1.15 bouyer case MPII_SCSIIO_STATUS_BUSY: 3146 1.3 kardel scsi_status = SCSI_BUSY; 3147 1.3 kardel break; 3148 1.27 skrll 3149 1.15 bouyer case MPII_SCSIIO_STATUS_INTERMEDIATE: 3150 1.3 kardel scsi_status = SCSI_INTERM; 3151 1.3 kardel break; 3152 1.27 skrll 3153 1.15 bouyer case MPII_SCSIIO_STATUS_INTERMEDIATE_CONDMET: 3154 1.3 kardel scsi_status = SCSI_INTERM; 3155 1.3 kardel break; 3156 1.27 skrll 3157 1.15 bouyer case MPII_SCSIIO_STATUS_RESERVATION_CONFLICT: 3158 1.3 kardel scsi_status = SCSI_RESV_CONFLICT; 3159 1.3 kardel break; 3160 1.27 skrll 3161 1.15 bouyer case MPII_SCSIIO_STATUS_CMD_TERM: 3162 1.15 bouyer case MPII_SCSIIO_STATUS_TASK_ABORTED: 3163 1.3 kardel scsi_status = SCSI_TERMINATED; 3164 1.3 kardel break; 3165 1.3 kardel 3166 1.15 bouyer case MPII_SCSIIO_STATUS_TASK_SET_FULL: 3167 1.3 kardel scsi_status = SCSI_QUEUE_FULL; 3168 1.3 kardel break; 3169 1.3 kardel 3170 1.15 bouyer case MPII_SCSIIO_STATUS_ACA_ACTIVE: 3171 1.3 kardel scsi_status = SCSI_ACA_ACTIVE; 3172 1.3 kardel break; 3173 1.3 kardel 3174 1.3 kardel default: 3175 1.3 kardel /* XXX: for the lack of anything better and other than OK */ 3176 1.3 kardel scsi_status = 0xFF; 3177 1.3 kardel break; 3178 1.3 kardel } 3179 1.3 kardel 3180 1.3 kardel return scsi_status; 3181 1.3 kardel } 3182 1.1 bouyer 3183 1.24 maxv static void 3184 1.1 bouyer mpii_scsi_cmd_done(struct mpii_ccb *ccb) 3185 1.1 bouyer { 3186 1.1 bouyer struct mpii_msg_scsi_io_error *sie; 3187 1.1 bouyer struct mpii_softc *sc = ccb->ccb_sc; 3188 1.1 bouyer struct scsipi_xfer *xs = ccb->ccb_cookie; 3189 1.15 bouyer struct scsi_sense_data *sense; 3190 1.1 bouyer bus_dmamap_t dmap = ccb->ccb_dmamap; 3191 1.15 bouyer bool timeout = 1; 3192 1.1 bouyer 3193 1.1 bouyer callout_stop(&xs->xs_callout); 3194 1.1 bouyer if (ccb->ccb_state == MPII_CCB_TIMEOUT) 3195 1.1 bouyer timeout = 1; 3196 1.1 bouyer ccb->ccb_state = MPII_CCB_READY; 3197 1.1 bouyer 3198 1.1 bouyer if (xs->datalen != 0) { 3199 1.1 bouyer bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 3200 1.1 bouyer (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_POSTREAD : 3201 1.1 bouyer BUS_DMASYNC_POSTWRITE); 3202 1.1 bouyer 3203 1.1 bouyer bus_dmamap_unload(sc->sc_dmat, dmap); 3204 1.1 bouyer } 3205 1.27 skrll 3206 1.22 kardel KASSERT(xs->error == XS_NOERROR); 3207 1.22 kardel KASSERT(xs->status == SCSI_OK); 3208 1.27 skrll 3209 1.1 bouyer if (ccb->ccb_rcb == NULL) { 3210 1.1 bouyer /* no scsi error, we're ok so drop out early */ 3211 1.22 kardel xs->resid = 0; 3212 1.15 bouyer goto done; 3213 1.1 bouyer } 3214 1.1 bouyer 3215 1.1 bouyer sie = ccb->ccb_rcb->rcb_reply; 3216 1.1 bouyer 3217 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: mpii_scsi_cmd_done xs cmd: 0x%02x len: %d " 3218 1.15 bouyer "flags 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen, 3219 1.1 bouyer xs->xs_control); 3220 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: dev_handle: %d msg_length: %d " 3221 1.1 bouyer "function: 0x%02x\n", DEVNAME(sc), le16toh(sie->dev_handle), 3222 1.1 bouyer sie->msg_length, sie->function); 3223 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: vp_id: 0x%02x vf_id: 0x%02x\n", DEVNAME(sc), 3224 1.1 bouyer sie->vp_id, sie->vf_id); 3225 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: scsi_status: 0x%02x scsi_state: 0x%02x " 3226 1.1 bouyer "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status, 3227 1.1 bouyer sie->scsi_state, le16toh(sie->ioc_status)); 3228 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 3229 1.1 bouyer le32toh(sie->ioc_loginfo)); 3230 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: transfer_count: %d\n", DEVNAME(sc), 3231 1.1 bouyer le32toh(sie->transfer_count)); 3232 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: sense_count: %d\n", DEVNAME(sc), 3233 1.1 bouyer le32toh(sie->sense_count)); 3234 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: response_info: 0x%08x\n", DEVNAME(sc), 3235 1.1 bouyer le32toh(sie->response_info)); 3236 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: task_tag: 0x%04x\n", DEVNAME(sc), 3237 1.1 bouyer le16toh(sie->task_tag)); 3238 1.1 bouyer DNPRINTF(MPII_D_CMD, "%s: bidirectional_transfer_count: 0x%08x\n", 3239 1.1 bouyer DEVNAME(sc), le32toh(sie->bidirectional_transfer_count)); 3240 1.1 bouyer 3241 1.3 kardel xs->status = map_scsi_status(sie->scsi_status); 3242 1.3 kardel 3243 1.1 bouyer switch (le16toh(sie->ioc_status) & MPII_IOCSTATUS_MASK) { 3244 1.1 bouyer case MPII_IOCSTATUS_SCSI_DATA_UNDERRUN: 3245 1.15 bouyer switch(sie->scsi_status) { 3246 1.15 bouyer case MPII_SCSIIO_STATUS_CHECK_COND: 3247 1.3 kardel xs->error = XS_SENSE; 3248 1.21 mrg /* FALLTHROUGH */ 3249 1.15 bouyer case MPII_SCSIIO_STATUS_GOOD: 3250 1.1 bouyer xs->resid = xs->datalen - le32toh(sie->transfer_count); 3251 1.1 bouyer break; 3252 1.1 bouyer default: 3253 1.1 bouyer xs->error = XS_DRIVER_STUFFUP; 3254 1.1 bouyer break; 3255 1.1 bouyer } 3256 1.1 bouyer break; 3257 1.3 kardel 3258 1.1 bouyer case MPII_IOCSTATUS_SUCCESS: 3259 1.1 bouyer case MPII_IOCSTATUS_SCSI_RECOVERED_ERROR: 3260 1.3 kardel switch (sie->scsi_status) { 3261 1.15 bouyer case MPII_SCSIIO_STATUS_GOOD: 3262 1.22 kardel xs->resid = 0; 3263 1.1 bouyer break; 3264 1.1 bouyer 3265 1.15 bouyer case MPII_SCSIIO_STATUS_CHECK_COND: 3266 1.1 bouyer xs->error = XS_SENSE; 3267 1.1 bouyer break; 3268 1.15 bouyer 3269 1.15 bouyer case MPII_SCSIIO_STATUS_BUSY: 3270 1.15 bouyer case MPII_SCSIIO_STATUS_TASK_SET_FULL: 3271 1.1 bouyer xs->error = XS_BUSY; 3272 1.1 bouyer break; 3273 1.1 bouyer 3274 1.1 bouyer default: 3275 1.1 bouyer xs->error = XS_DRIVER_STUFFUP; 3276 1.1 bouyer } 3277 1.1 bouyer break; 3278 1.1 bouyer 3279 1.1 bouyer case MPII_IOCSTATUS_BUSY: 3280 1.1 bouyer case MPII_IOCSTATUS_INSUFFICIENT_RESOURCES: 3281 1.1 bouyer xs->error = XS_BUSY; 3282 1.1 bouyer break; 3283 1.1 bouyer 3284 1.1 bouyer case MPII_IOCSTATUS_SCSI_IOC_TERMINATED: 3285 1.1 bouyer case MPII_IOCSTATUS_SCSI_TASK_TERMINATED: 3286 1.1 bouyer xs->error = timeout ? XS_TIMEOUT : XS_RESET; 3287 1.1 bouyer break; 3288 1.1 bouyer 3289 1.1 bouyer case MPII_IOCSTATUS_SCSI_INVALID_DEVHANDLE: 3290 1.1 bouyer case MPII_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 3291 1.1 bouyer xs->error = XS_SELTIMEOUT; 3292 1.1 bouyer break; 3293 1.1 bouyer 3294 1.1 bouyer default: 3295 1.1 bouyer xs->error = XS_DRIVER_STUFFUP; 3296 1.1 bouyer break; 3297 1.1 bouyer } 3298 1.1 bouyer 3299 1.15 bouyer sense = (struct scsi_sense_data *)((uintptr_t)ccb->ccb_cmd + 3300 1.15 bouyer sc->sc_request_size - sizeof(*sense)); 3301 1.15 bouyer if (sie->scsi_state & MPII_SCSIIO_STATE_AUTOSENSE_VALID) 3302 1.15 bouyer memcpy(&xs->sense, sense, sizeof(xs->sense)); 3303 1.1 bouyer 3304 1.22 kardel mpii_push_reply(sc, ccb->ccb_rcb); 3305 1.1 bouyer 3306 1.22 kardel done: 3307 1.1 bouyer mpii_put_ccb(sc, ccb); 3308 1.22 kardel 3309 1.22 kardel DNPRINTF(MPII_D_CMD, "%s: xs err: %d status: %#x len: %d resid: %d\n", 3310 1.22 kardel DEVNAME(sc), xs->error, xs->status, xs->datalen, xs->resid); 3311 1.22 kardel 3312 1.1 bouyer scsipi_done(xs); 3313 1.1 bouyer } 3314 1.1 bouyer 3315 1.1 bouyer #if 0 3316 1.15 bouyer int 3317 1.15 bouyer mpii_scsi_ioctl(struct scsi_link *link, u_long cmd, void *addr, int flag) 3318 1.15 bouyer { 3319 1.15 bouyer struct mpii_softc *sc = (struct mpii_softc *)link->adapter_softc; 3320 1.15 bouyer struct mpii_device *dev = sc->sc_devs[link->target]; 3321 1.15 bouyer 3322 1.15 bouyer DNPRINTF(MPII_D_IOCTL, "%s: mpii_scsi_ioctl\n", DEVNAME(sc)); 3323 1.15 bouyer 3324 1.15 bouyer switch (cmd) { 3325 1.15 bouyer case DIOCGCACHE: 3326 1.15 bouyer case DIOCSCACHE: 3327 1.15 bouyer if (dev != NULL && ISSET(dev->flags, MPII_DF_VOLUME)) { 3328 1.15 bouyer return (mpii_ioctl_cache(link, cmd, 3329 1.15 bouyer (struct dk_cache *)addr)); 3330 1.15 bouyer } 3331 1.15 bouyer break; 3332 1.15 bouyer 3333 1.15 bouyer default: 3334 1.15 bouyer if (sc->sc_ioctl) 3335 1.15 bouyer return (sc->sc_ioctl(link->adapter_softc, cmd, addr)); 3336 1.15 bouyer 3337 1.15 bouyer break; 3338 1.15 bouyer } 3339 1.15 bouyer 3340 1.15 bouyer return (ENOTTY); 3341 1.15 bouyer } 3342 1.15 bouyer 3343 1.15 bouyer int 3344 1.1 bouyer mpii_ioctl_cache(struct scsi_link *link, u_long cmd, struct dk_cache *dc) 3345 1.1 bouyer { 3346 1.1 bouyer struct mpii_softc *sc = (struct mpii_softc *)link->adapter_softc; 3347 1.1 bouyer struct mpii_device *dev = sc->sc_devs[link->target]; 3348 1.1 bouyer struct mpii_cfg_raid_vol_pg0 *vpg; 3349 1.1 bouyer struct mpii_msg_raid_action_request *req; 3350 1.15 bouyer struct mpii_msg_raid_action_reply *rep; 3351 1.1 bouyer struct mpii_cfg_hdr hdr; 3352 1.1 bouyer struct mpii_ccb *ccb; 3353 1.1 bouyer u_int32_t addr = MPII_CFG_RAID_VOL_ADDR_HANDLE | dev->dev_handle; 3354 1.1 bouyer size_t pagelen; 3355 1.1 bouyer int rv = 0; 3356 1.1 bouyer int enabled; 3357 1.1 bouyer 3358 1.1 bouyer if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0, 3359 1.1 bouyer addr, MPII_PG_POLL, &hdr) != 0) 3360 1.1 bouyer return (EINVAL); 3361 1.1 bouyer 3362 1.1 bouyer pagelen = hdr.page_length * 4; 3363 1.12 jdolecek vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO); 3364 1.1 bouyer if (vpg == NULL) 3365 1.1 bouyer return (ENOMEM); 3366 1.1 bouyer 3367 1.1 bouyer if (mpii_req_cfg_page(sc, addr, MPII_PG_POLL, &hdr, 1, 3368 1.1 bouyer vpg, pagelen) != 0) { 3369 1.1 bouyer rv = EINVAL; 3370 1.1 bouyer goto done; 3371 1.1 bouyer } 3372 1.1 bouyer 3373 1.1 bouyer enabled = ((le16toh(vpg->volume_settings) & 3374 1.1 bouyer MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_MASK) == 3375 1.1 bouyer MPII_CFG_RAID_VOL_0_SETTINGS_CACHE_ENABLED) ? 1 : 0; 3376 1.1 bouyer 3377 1.1 bouyer if (cmd == DIOCGCACHE) { 3378 1.1 bouyer dc->wrcache = enabled; 3379 1.1 bouyer dc->rdcache = 0; 3380 1.1 bouyer goto done; 3381 1.1 bouyer } /* else DIOCSCACHE */ 3382 1.1 bouyer 3383 1.1 bouyer if (dc->rdcache) { 3384 1.1 bouyer rv = EOPNOTSUPP; 3385 1.1 bouyer goto done; 3386 1.1 bouyer } 3387 1.1 bouyer 3388 1.1 bouyer if (((dc->wrcache) ? 1 : 0) == enabled) 3389 1.1 bouyer goto done; 3390 1.1 bouyer 3391 1.15 bouyer ccb = scsi_io_get(&sc->sc_iopool, SCSI_POLL); 3392 1.1 bouyer if (ccb == NULL) { 3393 1.1 bouyer rv = ENOMEM; 3394 1.1 bouyer goto done; 3395 1.1 bouyer } 3396 1.1 bouyer 3397 1.1 bouyer ccb->ccb_done = mpii_empty_done; 3398 1.1 bouyer 3399 1.1 bouyer req = ccb->ccb_cmd; 3400 1.15 bouyer memset(req, 0, sizeof(*req)); 3401 1.1 bouyer req->function = MPII_FUNCTION_RAID_ACTION; 3402 1.1 bouyer req->action = MPII_RAID_ACTION_CHANGE_VOL_WRITE_CACHE; 3403 1.1 bouyer req->vol_dev_handle = htole16(dev->dev_handle); 3404 1.1 bouyer req->action_data = htole32(dc->wrcache ? 3405 1.1 bouyer MPII_RAID_VOL_WRITE_CACHE_ENABLE : 3406 1.1 bouyer MPII_RAID_VOL_WRITE_CACHE_DISABLE); 3407 1.1 bouyer 3408 1.1 bouyer if (mpii_poll(sc, ccb) != 0) { 3409 1.1 bouyer rv = EIO; 3410 1.1 bouyer goto done; 3411 1.1 bouyer } 3412 1.1 bouyer 3413 1.1 bouyer if (ccb->ccb_rcb != NULL) { 3414 1.1 bouyer rep = ccb->ccb_rcb->rcb_reply; 3415 1.1 bouyer if ((rep->ioc_status != MPII_IOCSTATUS_SUCCESS) || 3416 1.1 bouyer ((rep->action_data[0] & 3417 1.1 bouyer MPII_RAID_VOL_WRITE_CACHE_MASK) != 3418 1.1 bouyer (dc->wrcache ? MPII_RAID_VOL_WRITE_CACHE_ENABLE : 3419 1.1 bouyer MPII_RAID_VOL_WRITE_CACHE_DISABLE))) 3420 1.1 bouyer rv = EINVAL; 3421 1.1 bouyer mpii_push_reply(sc, ccb->ccb_rcb); 3422 1.1 bouyer } 3423 1.1 bouyer 3424 1.15 bouyer scsi_io_put(&sc->sc_iopool, ccb); 3425 1.1 bouyer 3426 1.1 bouyer done: 3427 1.1 bouyer free(vpg, M_TEMP); 3428 1.1 bouyer return (rv); 3429 1.1 bouyer } 3430 1.15 bouyer #endif /* 0 */ 3431 1.1 bouyer 3432 1.1 bouyer #if NBIO > 0 3433 1.24 maxv static int 3434 1.1 bouyer mpii_ioctl(device_t dev, u_long cmd, void *addr) 3435 1.1 bouyer { 3436 1.1 bouyer struct mpii_softc *sc = device_private(dev); 3437 1.15 bouyer int error = 0; 3438 1.1 bouyer 3439 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl ", DEVNAME(sc)); 3440 1.1 bouyer 3441 1.1 bouyer switch (cmd) { 3442 1.1 bouyer case BIOCINQ: 3443 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "inq\n"); 3444 1.1 bouyer error = mpii_ioctl_inq(sc, (struct bioc_inq *)addr); 3445 1.1 bouyer break; 3446 1.1 bouyer case BIOCVOL: 3447 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "vol\n"); 3448 1.1 bouyer error = mpii_ioctl_vol(sc, (struct bioc_vol *)addr); 3449 1.1 bouyer break; 3450 1.1 bouyer case BIOCDISK: 3451 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "disk\n"); 3452 1.1 bouyer error = mpii_ioctl_disk(sc, (struct bioc_disk *)addr); 3453 1.1 bouyer break; 3454 1.1 bouyer default: 3455 1.1 bouyer DNPRINTF(MPII_D_IOCTL, " invalid ioctl\n"); 3456 1.15 bouyer error = ENOTTY; 3457 1.1 bouyer } 3458 1.1 bouyer 3459 1.1 bouyer return (error); 3460 1.1 bouyer } 3461 1.1 bouyer 3462 1.24 maxv static int 3463 1.1 bouyer mpii_ioctl_inq(struct mpii_softc *sc, struct bioc_inq *bi) 3464 1.1 bouyer { 3465 1.1 bouyer int i; 3466 1.1 bouyer 3467 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_inq\n", DEVNAME(sc)); 3468 1.1 bouyer 3469 1.1 bouyer strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev)); 3470 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 3471 1.1 bouyer for (i = 0; i < sc->sc_max_devices; i++) 3472 1.1 bouyer if (sc->sc_devs[i] && 3473 1.1 bouyer ISSET(sc->sc_devs[i]->flags, MPII_DF_VOLUME)) 3474 1.1 bouyer bi->bi_novol++; 3475 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3476 1.1 bouyer return (0); 3477 1.1 bouyer } 3478 1.1 bouyer 3479 1.24 maxv static int 3480 1.1 bouyer mpii_ioctl_vol(struct mpii_softc *sc, struct bioc_vol *bv) 3481 1.1 bouyer { 3482 1.1 bouyer struct mpii_cfg_raid_vol_pg0 *vpg; 3483 1.1 bouyer struct mpii_cfg_hdr hdr; 3484 1.1 bouyer struct mpii_device *dev; 3485 1.1 bouyer size_t pagelen; 3486 1.1 bouyer u_int16_t volh; 3487 1.1 bouyer int rv, hcnt = 0; 3488 1.15 bouyer int percent; 3489 1.1 bouyer 3490 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_vol %d\n", 3491 1.1 bouyer DEVNAME(sc), bv->bv_volid); 3492 1.1 bouyer 3493 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 3494 1.15 bouyer if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL) { 3495 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3496 1.1 bouyer return (ENODEV); 3497 1.15 bouyer } 3498 1.1 bouyer volh = dev->dev_handle; 3499 1.15 bouyer percent = dev->percent; 3500 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3501 1.1 bouyer 3502 1.1 bouyer if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0, 3503 1.1 bouyer MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) { 3504 1.1 bouyer printf("%s: unable to fetch header for raid volume page 0\n", 3505 1.1 bouyer DEVNAME(sc)); 3506 1.1 bouyer return (EINVAL); 3507 1.1 bouyer } 3508 1.1 bouyer 3509 1.1 bouyer pagelen = hdr.page_length * 4; 3510 1.12 jdolecek vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO); 3511 1.1 bouyer if (vpg == NULL) { 3512 1.1 bouyer printf("%s: unable to allocate space for raid " 3513 1.1 bouyer "volume page 0\n", DEVNAME(sc)); 3514 1.1 bouyer return (ENOMEM); 3515 1.1 bouyer } 3516 1.1 bouyer 3517 1.1 bouyer if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, 3518 1.1 bouyer &hdr, 1, vpg, pagelen) != 0) { 3519 1.1 bouyer printf("%s: unable to fetch raid volume page 0\n", 3520 1.1 bouyer DEVNAME(sc)); 3521 1.1 bouyer free(vpg, M_TEMP); 3522 1.1 bouyer return (EINVAL); 3523 1.1 bouyer } 3524 1.1 bouyer 3525 1.1 bouyer switch (vpg->volume_state) { 3526 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_ONLINE: 3527 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL: 3528 1.1 bouyer bv->bv_status = BIOC_SVONLINE; 3529 1.1 bouyer break; 3530 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_DEGRADED: 3531 1.1 bouyer if (ISSET(le32toh(vpg->volume_status), 3532 1.1 bouyer MPII_CFG_RAID_VOL_0_STATUS_RESYNC)) { 3533 1.1 bouyer bv->bv_status = BIOC_SVREBUILD; 3534 1.15 bouyer bv->bv_percent = percent; 3535 1.1 bouyer } else 3536 1.1 bouyer bv->bv_status = BIOC_SVDEGRADED; 3537 1.1 bouyer break; 3538 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_FAILED: 3539 1.1 bouyer bv->bv_status = BIOC_SVOFFLINE; 3540 1.1 bouyer break; 3541 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING: 3542 1.1 bouyer bv->bv_status = BIOC_SVBUILDING; 3543 1.1 bouyer break; 3544 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_MISSING: 3545 1.1 bouyer default: 3546 1.1 bouyer bv->bv_status = BIOC_SVINVALID; 3547 1.1 bouyer break; 3548 1.1 bouyer } 3549 1.1 bouyer 3550 1.1 bouyer switch (vpg->volume_type) { 3551 1.1 bouyer case MPII_CFG_RAID_VOL_0_TYPE_RAID0: 3552 1.1 bouyer bv->bv_level = 0; 3553 1.1 bouyer break; 3554 1.1 bouyer case MPII_CFG_RAID_VOL_0_TYPE_RAID1: 3555 1.1 bouyer bv->bv_level = 1; 3556 1.1 bouyer break; 3557 1.1 bouyer case MPII_CFG_RAID_VOL_0_TYPE_RAID1E: 3558 1.1 bouyer case MPII_CFG_RAID_VOL_0_TYPE_RAID10: 3559 1.1 bouyer bv->bv_level = 10; 3560 1.1 bouyer break; 3561 1.1 bouyer default: 3562 1.1 bouyer bv->bv_level = -1; 3563 1.1 bouyer } 3564 1.1 bouyer 3565 1.1 bouyer if ((rv = mpii_bio_hs(sc, NULL, 0, vpg->hot_spare_pool, &hcnt)) != 0) { 3566 1.1 bouyer free(vpg, M_TEMP); 3567 1.1 bouyer return (rv); 3568 1.1 bouyer } 3569 1.1 bouyer 3570 1.1 bouyer bv->bv_nodisk = vpg->num_phys_disks + hcnt; 3571 1.1 bouyer 3572 1.1 bouyer bv->bv_size = le64toh(vpg->max_lba) * le16toh(vpg->block_size); 3573 1.1 bouyer 3574 1.1 bouyer free(vpg, M_TEMP); 3575 1.1 bouyer return (0); 3576 1.1 bouyer } 3577 1.1 bouyer 3578 1.24 maxv static int 3579 1.1 bouyer mpii_ioctl_disk(struct mpii_softc *sc, struct bioc_disk *bd) 3580 1.1 bouyer { 3581 1.1 bouyer struct mpii_cfg_raid_vol_pg0 *vpg; 3582 1.1 bouyer struct mpii_cfg_raid_vol_pg0_physdisk *pd; 3583 1.1 bouyer struct mpii_cfg_hdr hdr; 3584 1.1 bouyer struct mpii_device *dev; 3585 1.1 bouyer size_t pagelen; 3586 1.1 bouyer u_int16_t volh; 3587 1.1 bouyer u_int8_t dn; 3588 1.1 bouyer 3589 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "%s: mpii_ioctl_disk %d/%d\n", 3590 1.1 bouyer DEVNAME(sc), bd->bd_volid, bd->bd_diskid); 3591 1.1 bouyer 3592 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 3593 1.15 bouyer if ((dev = mpii_find_vol(sc, bd->bd_volid)) == NULL) { 3594 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3595 1.1 bouyer return (ENODEV); 3596 1.15 bouyer } 3597 1.1 bouyer volh = dev->dev_handle; 3598 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3599 1.1 bouyer 3600 1.1 bouyer if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0, 3601 1.1 bouyer MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, &hdr) != 0) { 3602 1.1 bouyer printf("%s: unable to fetch header for raid volume page 0\n", 3603 1.1 bouyer DEVNAME(sc)); 3604 1.1 bouyer return (EINVAL); 3605 1.1 bouyer } 3606 1.1 bouyer 3607 1.1 bouyer pagelen = hdr.page_length * 4; 3608 1.12 jdolecek vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO); 3609 1.1 bouyer if (vpg == NULL) { 3610 1.1 bouyer printf("%s: unable to allocate space for raid " 3611 1.1 bouyer "volume page 0\n", DEVNAME(sc)); 3612 1.1 bouyer return (ENOMEM); 3613 1.1 bouyer } 3614 1.1 bouyer 3615 1.1 bouyer if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 0, 3616 1.1 bouyer &hdr, 1, vpg, pagelen) != 0) { 3617 1.1 bouyer printf("%s: unable to fetch raid volume page 0\n", 3618 1.1 bouyer DEVNAME(sc)); 3619 1.1 bouyer free(vpg, M_TEMP); 3620 1.1 bouyer return (EINVAL); 3621 1.1 bouyer } 3622 1.1 bouyer 3623 1.1 bouyer if (bd->bd_diskid >= vpg->num_phys_disks) { 3624 1.1 bouyer int nvdsk = vpg->num_phys_disks; 3625 1.1 bouyer int hsmap = vpg->hot_spare_pool; 3626 1.1 bouyer 3627 1.1 bouyer free(vpg, M_TEMP); 3628 1.1 bouyer return (mpii_bio_hs(sc, bd, nvdsk, hsmap, NULL)); 3629 1.1 bouyer } 3630 1.1 bouyer 3631 1.1 bouyer pd = (struct mpii_cfg_raid_vol_pg0_physdisk *)(vpg + 1) + 3632 1.1 bouyer bd->bd_diskid; 3633 1.1 bouyer dn = pd->phys_disk_num; 3634 1.1 bouyer 3635 1.1 bouyer free(vpg, M_TEMP); 3636 1.1 bouyer return (mpii_bio_disk(sc, bd, dn)); 3637 1.1 bouyer } 3638 1.1 bouyer 3639 1.24 maxv static int 3640 1.1 bouyer mpii_bio_hs(struct mpii_softc *sc, struct bioc_disk *bd, int nvdsk, 3641 1.1 bouyer int hsmap, int *hscnt) 3642 1.1 bouyer { 3643 1.1 bouyer struct mpii_cfg_raid_config_pg0 *cpg; 3644 1.1 bouyer struct mpii_raid_config_element *el; 3645 1.1 bouyer struct mpii_ecfg_hdr ehdr; 3646 1.1 bouyer size_t pagelen; 3647 1.1 bouyer int i, nhs = 0; 3648 1.1 bouyer 3649 1.1 bouyer if (bd) { 3650 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs %d\n", DEVNAME(sc), 3651 1.1 bouyer bd->bd_diskid - nvdsk); 3652 1.1 bouyer } else { 3653 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_hs\n", DEVNAME(sc)); 3654 1.1 bouyer } 3655 1.1 bouyer 3656 1.1 bouyer if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_CONFIG, 3657 1.1 bouyer 0, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG, MPII_PG_EXTENDED, 3658 1.1 bouyer &ehdr) != 0) { 3659 1.1 bouyer printf("%s: unable to fetch header for raid config page 0\n", 3660 1.1 bouyer DEVNAME(sc)); 3661 1.1 bouyer return (EINVAL); 3662 1.1 bouyer } 3663 1.1 bouyer 3664 1.1 bouyer pagelen = le16toh(ehdr.ext_page_length) * 4; 3665 1.12 jdolecek cpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO); 3666 1.1 bouyer if (cpg == NULL) { 3667 1.1 bouyer printf("%s: unable to allocate space for raid config page 0\n", 3668 1.1 bouyer DEVNAME(sc)); 3669 1.1 bouyer return (ENOMEM); 3670 1.1 bouyer } 3671 1.1 bouyer 3672 1.1 bouyer if (mpii_req_cfg_page(sc, MPII_CFG_RAID_CONFIG_ACTIVE_CONFIG, 3673 1.1 bouyer MPII_PG_EXTENDED, &ehdr, 1, cpg, pagelen) != 0) { 3674 1.1 bouyer printf("%s: unable to fetch raid config page 0\n", 3675 1.1 bouyer DEVNAME(sc)); 3676 1.1 bouyer free(cpg, M_TEMP); 3677 1.1 bouyer return (EINVAL); 3678 1.1 bouyer } 3679 1.1 bouyer 3680 1.1 bouyer el = (struct mpii_raid_config_element *)(cpg + 1); 3681 1.1 bouyer for (i = 0; i < cpg->num_elements; i++, el++) { 3682 1.1 bouyer if (ISSET(le16toh(el->element_flags), 3683 1.1 bouyer MPII_RAID_CONFIG_ELEMENT_FLAG_HSP_PHYS_DISK) && 3684 1.1 bouyer el->hot_spare_pool == hsmap) { 3685 1.1 bouyer /* 3686 1.1 bouyer * diskid comparison is based on the idea that all 3687 1.1 bouyer * disks are counted by the bio(4) in sequence, thus 3688 1.31 andvar * subtracting the number of disks in the volume 3689 1.1 bouyer * from the diskid yields us a "relative" hotspare 3690 1.1 bouyer * number, which is good enough for us. 3691 1.1 bouyer */ 3692 1.1 bouyer if (bd != NULL && bd->bd_diskid == nhs + nvdsk) { 3693 1.1 bouyer u_int8_t dn = el->phys_disk_num; 3694 1.1 bouyer 3695 1.1 bouyer free(cpg, M_TEMP); 3696 1.1 bouyer return (mpii_bio_disk(sc, bd, dn)); 3697 1.1 bouyer } 3698 1.1 bouyer nhs++; 3699 1.1 bouyer } 3700 1.1 bouyer } 3701 1.1 bouyer 3702 1.1 bouyer if (hscnt) 3703 1.1 bouyer *hscnt = nhs; 3704 1.1 bouyer 3705 1.1 bouyer free(cpg, M_TEMP); 3706 1.1 bouyer return (0); 3707 1.1 bouyer } 3708 1.1 bouyer 3709 1.24 maxv static int 3710 1.1 bouyer mpii_bio_disk(struct mpii_softc *sc, struct bioc_disk *bd, u_int8_t dn) 3711 1.1 bouyer { 3712 1.1 bouyer struct mpii_cfg_raid_physdisk_pg0 *ppg; 3713 1.1 bouyer struct mpii_cfg_hdr hdr; 3714 1.1 bouyer struct mpii_device *dev; 3715 1.1 bouyer int len; 3716 1.1 bouyer 3717 1.1 bouyer DNPRINTF(MPII_D_IOCTL, "%s: mpii_bio_disk %d\n", DEVNAME(sc), 3718 1.1 bouyer bd->bd_diskid); 3719 1.1 bouyer 3720 1.12 jdolecek ppg = malloc(sizeof(*ppg), M_TEMP, M_WAITOK | M_ZERO); 3721 1.1 bouyer if (ppg == NULL) { 3722 1.1 bouyer printf("%s: unable to allocate space for raid physical disk " 3723 1.1 bouyer "page 0\n", DEVNAME(sc)); 3724 1.1 bouyer return (ENOMEM); 3725 1.1 bouyer } 3726 1.1 bouyer 3727 1.1 bouyer hdr.page_version = 0; 3728 1.1 bouyer hdr.page_length = sizeof(*ppg) / 4; 3729 1.1 bouyer hdr.page_number = 0; 3730 1.1 bouyer hdr.page_type = MPII_CONFIG_REQ_PAGE_TYPE_RAID_PD; 3731 1.1 bouyer 3732 1.1 bouyer if (mpii_req_cfg_page(sc, MPII_CFG_RAID_PHYS_DISK_ADDR_NUMBER | dn, 0, 3733 1.1 bouyer &hdr, 1, ppg, sizeof(*ppg)) != 0) { 3734 1.1 bouyer printf("%s: unable to fetch raid drive page 0\n", 3735 1.1 bouyer DEVNAME(sc)); 3736 1.1 bouyer free(ppg, M_TEMP); 3737 1.1 bouyer return (EINVAL); 3738 1.1 bouyer } 3739 1.1 bouyer 3740 1.1 bouyer bd->bd_target = ppg->phys_disk_num; 3741 1.1 bouyer 3742 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 3743 1.1 bouyer if ((dev = mpii_find_dev(sc, le16toh(ppg->dev_handle))) == NULL) { 3744 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3745 1.1 bouyer bd->bd_status = BIOC_SDINVALID; 3746 1.1 bouyer free(ppg, M_TEMP); 3747 1.1 bouyer return (0); 3748 1.1 bouyer } 3749 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3750 1.1 bouyer 3751 1.1 bouyer switch (ppg->phys_disk_state) { 3752 1.1 bouyer case MPII_CFG_RAID_PHYDISK_0_STATE_ONLINE: 3753 1.1 bouyer case MPII_CFG_RAID_PHYDISK_0_STATE_OPTIMAL: 3754 1.1 bouyer bd->bd_status = BIOC_SDONLINE; 3755 1.1 bouyer break; 3756 1.1 bouyer case MPII_CFG_RAID_PHYDISK_0_STATE_OFFLINE: 3757 1.1 bouyer if (ppg->offline_reason == 3758 1.1 bouyer MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILED || 3759 1.1 bouyer ppg->offline_reason == 3760 1.1 bouyer MPII_CFG_RAID_PHYDISK_0_OFFLINE_FAILEDREQ) 3761 1.1 bouyer bd->bd_status = BIOC_SDFAILED; 3762 1.1 bouyer else 3763 1.1 bouyer bd->bd_status = BIOC_SDOFFLINE; 3764 1.1 bouyer break; 3765 1.1 bouyer case MPII_CFG_RAID_PHYDISK_0_STATE_DEGRADED: 3766 1.1 bouyer bd->bd_status = BIOC_SDFAILED; 3767 1.1 bouyer break; 3768 1.1 bouyer case MPII_CFG_RAID_PHYDISK_0_STATE_REBUILDING: 3769 1.1 bouyer bd->bd_status = BIOC_SDREBUILD; 3770 1.1 bouyer break; 3771 1.1 bouyer case MPII_CFG_RAID_PHYDISK_0_STATE_HOTSPARE: 3772 1.1 bouyer bd->bd_status = BIOC_SDHOTSPARE; 3773 1.1 bouyer break; 3774 1.1 bouyer case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCONFIGURED: 3775 1.1 bouyer bd->bd_status = BIOC_SDUNUSED; 3776 1.1 bouyer break; 3777 1.1 bouyer case MPII_CFG_RAID_PHYDISK_0_STATE_NOTCOMPATIBLE: 3778 1.1 bouyer default: 3779 1.1 bouyer bd->bd_status = BIOC_SDINVALID; 3780 1.1 bouyer break; 3781 1.1 bouyer } 3782 1.1 bouyer 3783 1.1 bouyer bd->bd_size = le64toh(ppg->dev_max_lba) * le16toh(ppg->block_size); 3784 1.1 bouyer 3785 1.8 christos strnvisx(bd->bd_vendor, sizeof(bd->bd_vendor), 3786 1.8 christos ppg->vendor_id, sizeof(ppg->vendor_id), 3787 1.8 christos VIS_TRIM|VIS_SAFE|VIS_OCTAL); 3788 1.1 bouyer len = strlen(bd->bd_vendor); 3789 1.1 bouyer bd->bd_vendor[len] = ' '; 3790 1.8 christos strnvisx(&bd->bd_vendor[len + 1], sizeof(ppg->vendor_id) - len - 1, 3791 1.8 christos ppg->product_id, sizeof(ppg->product_id), 3792 1.8 christos VIS_TRIM|VIS_SAFE|VIS_OCTAL); 3793 1.8 christos strnvisx(bd->bd_serial, sizeof(bd->bd_serial), 3794 1.8 christos ppg->serial, sizeof(ppg->serial), VIS_TRIM|VIS_SAFE|VIS_OCTAL); 3795 1.1 bouyer 3796 1.1 bouyer free(ppg, M_TEMP); 3797 1.1 bouyer return (0); 3798 1.1 bouyer } 3799 1.1 bouyer 3800 1.24 maxv static struct mpii_device * 3801 1.1 bouyer mpii_find_vol(struct mpii_softc *sc, int volid) 3802 1.1 bouyer { 3803 1.1 bouyer struct mpii_device *dev = NULL; 3804 1.1 bouyer 3805 1.15 bouyer KASSERT(mutex_owned(&sc->sc_devs_mtx)); 3806 1.1 bouyer if (sc->sc_vd_id_low + volid >= sc->sc_max_devices) 3807 1.1 bouyer return (NULL); 3808 1.1 bouyer dev = sc->sc_devs[sc->sc_vd_id_low + volid]; 3809 1.1 bouyer if (dev && ISSET(dev->flags, MPII_DF_VOLUME)) 3810 1.1 bouyer return (dev); 3811 1.1 bouyer return (NULL); 3812 1.1 bouyer } 3813 1.1 bouyer 3814 1.1 bouyer /* 3815 1.1 bouyer * Non-sleeping lightweight version of the mpii_ioctl_vol 3816 1.1 bouyer */ 3817 1.24 maxv static int 3818 1.1 bouyer mpii_bio_volstate(struct mpii_softc *sc, struct bioc_vol *bv) 3819 1.1 bouyer { 3820 1.1 bouyer struct mpii_cfg_raid_vol_pg0 *vpg; 3821 1.1 bouyer struct mpii_cfg_hdr hdr; 3822 1.1 bouyer struct mpii_device *dev = NULL; 3823 1.1 bouyer size_t pagelen; 3824 1.1 bouyer u_int16_t volh; 3825 1.1 bouyer 3826 1.15 bouyer mutex_enter(&sc->sc_devs_mtx); 3827 1.15 bouyer if ((dev = mpii_find_vol(sc, bv->bv_volid)) == NULL) { 3828 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3829 1.1 bouyer return (ENODEV); 3830 1.15 bouyer } 3831 1.1 bouyer volh = dev->dev_handle; 3832 1.15 bouyer mutex_exit(&sc->sc_devs_mtx); 3833 1.1 bouyer 3834 1.15 bouyer if (mpii_req_cfg_header(sc, MPII_CONFIG_REQ_PAGE_TYPE_RAID_VOL, 0, 3835 1.15 bouyer MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, MPII_PG_POLL, &hdr) != 0) { 3836 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: unable to fetch header for raid " 3837 1.1 bouyer "volume page 0\n", DEVNAME(sc)); 3838 1.1 bouyer return (EINVAL); 3839 1.1 bouyer } 3840 1.1 bouyer 3841 1.1 bouyer pagelen = hdr.page_length * 4; 3842 1.23 chs vpg = malloc(pagelen, M_TEMP, M_WAITOK | M_ZERO); 3843 1.15 bouyer if (mpii_req_cfg_page(sc, MPII_CFG_RAID_VOL_ADDR_HANDLE | volh, 3844 1.15 bouyer MPII_PG_POLL, &hdr, 1, vpg, pagelen) != 0) { 3845 1.1 bouyer DNPRINTF(MPII_D_MISC, "%s: unable to fetch raid volume " 3846 1.1 bouyer "page 0\n", DEVNAME(sc)); 3847 1.1 bouyer free(vpg, M_TEMP); 3848 1.1 bouyer return (EINVAL); 3849 1.1 bouyer } 3850 1.1 bouyer 3851 1.1 bouyer switch (vpg->volume_state) { 3852 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_ONLINE: 3853 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_OPTIMAL: 3854 1.1 bouyer bv->bv_status = BIOC_SVONLINE; 3855 1.1 bouyer break; 3856 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_DEGRADED: 3857 1.1 bouyer if (ISSET(le32toh(vpg->volume_status), 3858 1.1 bouyer MPII_CFG_RAID_VOL_0_STATUS_RESYNC)) 3859 1.1 bouyer bv->bv_status = BIOC_SVREBUILD; 3860 1.1 bouyer else 3861 1.1 bouyer bv->bv_status = BIOC_SVDEGRADED; 3862 1.1 bouyer break; 3863 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_FAILED: 3864 1.1 bouyer bv->bv_status = BIOC_SVOFFLINE; 3865 1.1 bouyer break; 3866 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_INITIALIZING: 3867 1.1 bouyer bv->bv_status = BIOC_SVBUILDING; 3868 1.1 bouyer break; 3869 1.1 bouyer case MPII_CFG_RAID_VOL_0_STATE_MISSING: 3870 1.1 bouyer default: 3871 1.1 bouyer bv->bv_status = BIOC_SVINVALID; 3872 1.1 bouyer break; 3873 1.1 bouyer } 3874 1.1 bouyer 3875 1.1 bouyer free(vpg, M_TEMP); 3876 1.1 bouyer return (0); 3877 1.1 bouyer } 3878 1.1 bouyer 3879 1.24 maxv static int 3880 1.1 bouyer mpii_create_sensors(struct mpii_softc *sc) 3881 1.1 bouyer { 3882 1.1 bouyer int i, rv; 3883 1.1 bouyer 3884 1.15 bouyer DNPRINTF(MPII_D_MISC, "%s: mpii_create_sensors(%d)\n", 3885 1.15 bouyer DEVNAME(sc), sc->sc_max_volumes); 3886 1.1 bouyer sc->sc_sme = sysmon_envsys_create(); 3887 1.15 bouyer sc->sc_sensors = malloc(sizeof(envsys_data_t) * sc->sc_max_volumes, 3888 1.23 chs M_DEVBUF, M_WAITOK | M_ZERO); 3889 1.1 bouyer 3890 1.15 bouyer for (i = 0; i < sc->sc_max_volumes; i++) { 3891 1.1 bouyer sc->sc_sensors[i].units = ENVSYS_DRIVE; 3892 1.1 bouyer sc->sc_sensors[i].state = ENVSYS_SINVALID; 3893 1.1 bouyer sc->sc_sensors[i].value_cur = ENVSYS_DRIVE_EMPTY; 3894 1.1 bouyer sc->sc_sensors[i].flags |= ENVSYS_FMONSTCHANGED; 3895 1.1 bouyer 3896 1.27 skrll /* logical drives */ 3897 1.1 bouyer snprintf(sc->sc_sensors[i].desc, 3898 1.1 bouyer sizeof(sc->sc_sensors[i].desc), "%s:%d", 3899 1.27 skrll DEVNAME(sc), i); 3900 1.27 skrll if ((rv = sysmon_envsys_sensor_attach(sc->sc_sme, 3901 1.1 bouyer &sc->sc_sensors[i])) != 0) { 3902 1.1 bouyer aprint_error_dev(sc->sc_dev, 3903 1.1 bouyer "unable to attach sensor (rv = %d)\n", rv); 3904 1.27 skrll goto out; 3905 1.27 skrll } 3906 1.1 bouyer } 3907 1.1 bouyer sc->sc_sme->sme_name = DEVNAME(sc); 3908 1.27 skrll sc->sc_sme->sme_cookie = sc; 3909 1.1 bouyer sc->sc_sme->sme_refresh = mpii_refresh_sensors; 3910 1.1 bouyer 3911 1.1 bouyer rv = sysmon_envsys_register(sc->sc_sme); 3912 1.1 bouyer if (rv != 0) { 3913 1.1 bouyer aprint_error_dev(sc->sc_dev, 3914 1.27 skrll "unable to register with sysmon (rv = %d)\n", rv); 3915 1.1 bouyer goto out; 3916 1.1 bouyer } 3917 1.1 bouyer return 0; 3918 1.1 bouyer 3919 1.1 bouyer out: 3920 1.1 bouyer free(sc->sc_sensors, M_DEVBUF); 3921 1.1 bouyer sysmon_envsys_destroy(sc->sc_sme); 3922 1.1 bouyer sc->sc_sme = NULL; 3923 1.15 bouyer return 1; 3924 1.1 bouyer } 3925 1.1 bouyer 3926 1.24 maxv static int 3927 1.1 bouyer mpii_destroy_sensors(struct mpii_softc *sc) 3928 1.1 bouyer { 3929 1.27 skrll if (sc->sc_sme == NULL) 3930 1.1 bouyer return 0; 3931 1.1 bouyer sysmon_envsys_unregister(sc->sc_sme); 3932 1.1 bouyer sc->sc_sme = NULL; 3933 1.1 bouyer free(sc->sc_sensors, M_DEVBUF); 3934 1.1 bouyer return 0; 3935 1.15 bouyer 3936 1.1 bouyer } 3937 1.1 bouyer 3938 1.24 maxv static void 3939 1.1 bouyer mpii_refresh_sensors(struct sysmon_envsys *sme, envsys_data_t *edata) 3940 1.1 bouyer { 3941 1.15 bouyer struct mpii_softc *sc = sme->sme_cookie; 3942 1.1 bouyer struct bioc_vol bv; 3943 1.1 bouyer 3944 1.15 bouyer memset(&bv, 0, sizeof(bv)); 3945 1.1 bouyer bv.bv_volid = edata->sensor; 3946 1.15 bouyer if (mpii_bio_volstate(sc, &bv)) 3947 1.6 christos bv.bv_status = BIOC_SVINVALID; 3948 1.6 christos bio_vol_to_envsys(edata, &bv); 3949 1.1 bouyer } 3950 1.1 bouyer #endif /* NBIO > 0 */ 3951