1/* $NetBSD$ */ 2/* $OpenBSD: mfi.c,v 1.66 2006/11/28 23:59:45 dlg Exp $ */ 3 4/* 5 * Copyright (c) 2012 Manuel Bouyer. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28/* 29 * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> 30 * 31 * Permission to use, copy, modify, and distribute this software for any 32 * purpose with or without fee is hereby granted, provided that the above 33 * copyright notice and this permission notice appear in all copies. 34 * 35 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 36 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 37 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 38 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 39 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 40 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 41 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 42 */ 43 44 /*- 45 * Redistribution and use in source and binary forms, with or without 46 * modification, are permitted provided that the following conditions 47 * are met: 48 * 49 * Copyright 1994-2009 The FreeBSD Project. 50 * All rights reserved. 51 * 52 * 1. Redistributions of source code must retain the above copyright 53 * notice, this list of conditions and the following disclaimer. 54 * 2. Redistributions in binary form must reproduce the above copyright 55 * notice, this list of conditions and the following disclaimer in the 56 * documentation and/or other materials provided with the distribution. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 60 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 61 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR 62 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 63 * EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 64 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 65 * PROFITS; OR BUSINESS INTERRUPTION)HOWEVER CAUSED AND ON ANY THEORY 66 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 67 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 68 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 69 * 70 * The views and conclusions contained in the software and documentation 71 * are those of the authors and should not be interpreted as representing 72 * official policies,either expressed or implied, of the FreeBSD Project. 73 */ 74 75#include <sys/cdefs.h> 76__KERNEL_RCSID(0, "$NetBSD$"); 77 78#include "bio.h" 79 80#include <sys/param.h> 81#include <sys/systm.h> 82#include <sys/buf.h> 83#include <sys/ioctl.h> 84#include <sys/device.h> 85#include <sys/kernel.h> 86#include <sys/malloc.h> 87#include <sys/proc.h> 88#include <sys/cpu.h> 89#include <sys/conf.h> 90#include <sys/kauth.h> 91 92#include <uvm/uvm_param.h> 93 94#include <sys/bus.h> 95 96#include <dev/scsipi/scsipi_all.h> 97#include <dev/scsipi/scsi_all.h> 98#include <dev/scsipi/scsi_spc.h> 99#include <dev/scsipi/scsipi_disk.h> 100#include <dev/scsipi/scsi_disk.h> 101#include <dev/scsipi/scsiconf.h> 102 103#include <dev/ic/mfireg.h> 104#include <dev/ic/mfivar.h> 105#include <dev/ic/mfiio.h> 106 107#if NBIO > 0 108#include <dev/biovar.h> 109#endif /* NBIO > 0 */ 110 111#ifdef MFI_DEBUG 112uint32_t mfi_debug = 0 113/* | MFI_D_CMD */ 114/* | MFI_D_INTR */ 115/* | MFI_D_MISC */ 116/* | MFI_D_DMA */ 117/* | MFI_D_IOCTL */ 118/* | MFI_D_RW */ 119/* | MFI_D_MEM */ 120/* | MFI_D_CCB */ 121/* | MFI_D_SYNC */ 122 ; 123#endif 124 125static void mfi_scsipi_request(struct scsipi_channel *, 126 scsipi_adapter_req_t, void *); 127static void mfiminphys(struct buf *bp); 128 129static struct mfi_ccb *mfi_get_ccb(struct mfi_softc *); 130static void mfi_put_ccb(struct mfi_ccb *); 131static int mfi_init_ccb(struct mfi_softc *); 132 133static struct mfi_mem *mfi_allocmem(struct mfi_softc *, size_t); 134static void mfi_freemem(struct mfi_softc *, struct mfi_mem **); 135 136static int mfi_transition_firmware(struct mfi_softc *); 137static int mfi_initialize_firmware(struct mfi_softc *); 138static int mfi_get_info(struct mfi_softc *); 139static int mfi_get_bbu(struct mfi_softc *, 140 struct mfi_bbu_status *); 141/* return codes for mfi_get_bbu */ 142#define MFI_BBU_GOOD 0 143#define MFI_BBU_BAD 1 144#define MFI_BBU_UNKNOWN 2 145static uint32_t mfi_read(struct mfi_softc *, bus_size_t); 146static void mfi_write(struct mfi_softc *, bus_size_t, uint32_t); 147static int mfi_poll(struct mfi_ccb *); 148static int mfi_create_sgl(struct mfi_ccb *, int); 149 150/* commands */ 151static int mfi_scsi_ld(struct mfi_ccb *, struct scsipi_xfer *); 152static int mfi_scsi_ld_io(struct mfi_ccb *, struct scsipi_xfer *, 153 uint64_t, uint32_t); 154static void mfi_scsi_ld_done(struct mfi_ccb *); 155static void mfi_scsi_xs_done(struct mfi_ccb *, int, int); 156static int mfi_mgmt_internal(struct mfi_softc *, uint32_t, 157 uint32_t, uint32_t, void *, uint8_t *, bool); 158static int mfi_mgmt(struct mfi_ccb *,struct scsipi_xfer *, 159 uint32_t, uint32_t, uint32_t, void *, uint8_t *); 160static void mfi_mgmt_done(struct mfi_ccb *); 161 162#if NBIO > 0 163static int mfi_ioctl(device_t, u_long, void *); 164static int mfi_ioctl_inq(struct mfi_softc *, struct bioc_inq *); 165static int mfi_ioctl_vol(struct mfi_softc *, struct bioc_vol *); 166static int mfi_ioctl_disk(struct mfi_softc *, struct bioc_disk *); 167static int mfi_ioctl_alarm(struct mfi_softc *, 168 struct bioc_alarm *); 169static int mfi_ioctl_blink(struct mfi_softc *sc, 170 struct bioc_blink *); 171static int mfi_ioctl_setstate(struct mfi_softc *, 172 struct bioc_setstate *); 173static int mfi_bio_hs(struct mfi_softc *, int, int, void *); 174static int mfi_create_sensors(struct mfi_softc *); 175static int mfi_destroy_sensors(struct mfi_softc *); 176static void mfi_sensor_refresh(struct sysmon_envsys *, 177 envsys_data_t *); 178#endif /* NBIO > 0 */ 179static bool mfi_shutdown(device_t, int); 180static bool mfi_suspend(device_t, const pmf_qual_t *); 181static bool mfi_resume(device_t, const pmf_qual_t *); 182 183static dev_type_open(mfifopen); 184static dev_type_close(mfifclose); 185static dev_type_ioctl(mfifioctl); 186const struct cdevsw mfi_cdevsw = { 187 mfifopen, mfifclose, noread, nowrite, mfifioctl, 188 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER 189}; 190 191extern struct cfdriver mfi_cd; 192 193static uint32_t mfi_xscale_fw_state(struct mfi_softc *sc); 194static void mfi_xscale_intr_ena(struct mfi_softc *sc); 195static void mfi_xscale_intr_dis(struct mfi_softc *sc); 196static int mfi_xscale_intr(struct mfi_softc *sc); 197static void mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb); 198 199static const struct mfi_iop_ops mfi_iop_xscale = { 200 mfi_xscale_fw_state, 201 mfi_xscale_intr_dis, 202 mfi_xscale_intr_ena, 203 mfi_xscale_intr, 204 mfi_xscale_post, 205 mfi_scsi_ld_io, 206}; 207 208static uint32_t mfi_ppc_fw_state(struct mfi_softc *sc); 209static void mfi_ppc_intr_ena(struct mfi_softc *sc); 210static void mfi_ppc_intr_dis(struct mfi_softc *sc); 211static int mfi_ppc_intr(struct mfi_softc *sc); 212static void mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb); 213 214static const struct mfi_iop_ops mfi_iop_ppc = { 215 mfi_ppc_fw_state, 216 mfi_ppc_intr_dis, 217 mfi_ppc_intr_ena, 218 mfi_ppc_intr, 219 mfi_ppc_post, 220 mfi_scsi_ld_io, 221}; 222 223uint32_t mfi_gen2_fw_state(struct mfi_softc *sc); 224void mfi_gen2_intr_ena(struct mfi_softc *sc); 225void mfi_gen2_intr_dis(struct mfi_softc *sc); 226int mfi_gen2_intr(struct mfi_softc *sc); 227void mfi_gen2_post(struct mfi_softc *sc, struct mfi_ccb *ccb); 228 229static const struct mfi_iop_ops mfi_iop_gen2 = { 230 mfi_gen2_fw_state, 231 mfi_gen2_intr_dis, 232 mfi_gen2_intr_ena, 233 mfi_gen2_intr, 234 mfi_gen2_post, 235 mfi_scsi_ld_io, 236}; 237 238u_int32_t mfi_skinny_fw_state(struct mfi_softc *); 239void mfi_skinny_intr_dis(struct mfi_softc *); 240void mfi_skinny_intr_ena(struct mfi_softc *); 241int mfi_skinny_intr(struct mfi_softc *); 242void mfi_skinny_post(struct mfi_softc *, struct mfi_ccb *); 243 244static const struct mfi_iop_ops mfi_iop_skinny = { 245 mfi_skinny_fw_state, 246 mfi_skinny_intr_dis, 247 mfi_skinny_intr_ena, 248 mfi_skinny_intr, 249 mfi_skinny_post, 250 mfi_scsi_ld_io, 251}; 252 253static int mfi_tbolt_init_desc_pool(struct mfi_softc *); 254static int mfi_tbolt_init_MFI_queue(struct mfi_softc *); 255static void mfi_tbolt_build_mpt_ccb(struct mfi_ccb *); 256int mfi_tbolt_scsi_ld_io(struct mfi_ccb *, struct scsipi_xfer *, 257 uint64_t, uint32_t); 258static void mfi_tbolt_scsi_ld_done(struct mfi_ccb *); 259static int mfi_tbolt_create_sgl(struct mfi_ccb *, int); 260void mfi_tbolt_sync_map_info(struct work *, void *); 261static void mfi_sync_map_complete(struct mfi_ccb *); 262 263u_int32_t mfi_tbolt_fw_state(struct mfi_softc *); 264void mfi_tbolt_intr_dis(struct mfi_softc *); 265void mfi_tbolt_intr_ena(struct mfi_softc *); 266int mfi_tbolt_intr(struct mfi_softc *sc); 267void mfi_tbolt_post(struct mfi_softc *, struct mfi_ccb *); 268 269static const struct mfi_iop_ops mfi_iop_tbolt = { 270 mfi_tbolt_fw_state, 271 mfi_tbolt_intr_dis, 272 mfi_tbolt_intr_ena, 273 mfi_tbolt_intr, 274 mfi_tbolt_post, 275 mfi_tbolt_scsi_ld_io, 276}; 277 278#define mfi_fw_state(_s) ((_s)->sc_iop->mio_fw_state(_s)) 279#define mfi_intr_enable(_s) ((_s)->sc_iop->mio_intr_ena(_s)) 280#define mfi_intr_disable(_s) ((_s)->sc_iop->mio_intr_dis(_s)) 281#define mfi_my_intr(_s) ((_s)->sc_iop->mio_intr(_s)) 282#define mfi_post(_s, _c) ((_s)->sc_iop->mio_post((_s), (_c))) 283 284static struct mfi_ccb * 285mfi_get_ccb(struct mfi_softc *sc) 286{ 287 struct mfi_ccb *ccb; 288 int s; 289 290 s = splbio(); 291 ccb = TAILQ_FIRST(&sc->sc_ccb_freeq); 292 if (ccb) { 293 TAILQ_REMOVE(&sc->sc_ccb_freeq, ccb, ccb_link); 294 ccb->ccb_state = MFI_CCB_READY; 295 } 296 splx(s); 297 298 DNPRINTF(MFI_D_CCB, "%s: mfi_get_ccb: %p\n", DEVNAME(sc), ccb); 299 if (__predict_false(ccb == NULL && sc->sc_running)) 300 aprint_error_dev(sc->sc_dev, "out of ccb\n"); 301 302 return ccb; 303} 304 305static void 306mfi_put_ccb(struct mfi_ccb *ccb) 307{ 308 struct mfi_softc *sc = ccb->ccb_sc; 309 struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header; 310 int s; 311 312 DNPRINTF(MFI_D_CCB, "%s: mfi_put_ccb: %p\n", DEVNAME(sc), ccb); 313 314 hdr->mfh_cmd_status = 0x0; 315 hdr->mfh_flags = 0x0; 316 ccb->ccb_state = MFI_CCB_FREE; 317 ccb->ccb_xs = NULL; 318 ccb->ccb_flags = 0; 319 ccb->ccb_done = NULL; 320 ccb->ccb_direction = 0; 321 ccb->ccb_frame_size = 0; 322 ccb->ccb_extra_frames = 0; 323 ccb->ccb_sgl = NULL; 324 ccb->ccb_data = NULL; 325 ccb->ccb_len = 0; 326 if (sc->sc_ioptype == MFI_IOP_TBOLT) { 327 /* erase tb_request_desc but preserve SMID */ 328 int index = ccb->ccb_tb_request_desc.header.SMID; 329 ccb->ccb_tb_request_desc.words = 0; 330 ccb->ccb_tb_request_desc.header.SMID = index; 331 } 332 s = splbio(); 333 TAILQ_INSERT_TAIL(&sc->sc_ccb_freeq, ccb, ccb_link); 334 splx(s); 335} 336 337static int 338mfi_destroy_ccb(struct mfi_softc *sc) 339{ 340 struct mfi_ccb *ccb; 341 uint32_t i; 342 343 DNPRINTF(MFI_D_CCB, "%s: mfi_destroy_ccb\n", DEVNAME(sc)); 344 345 346 for (i = 0; (ccb = mfi_get_ccb(sc)) != NULL; i++) { 347 /* create a dma map for transfer */ 348 bus_dmamap_destroy(sc->sc_datadmat, ccb->ccb_dmamap); 349 } 350 351 if (i < sc->sc_max_cmds) 352 return EBUSY; 353 354 free(sc->sc_ccb, M_DEVBUF); 355 356 return 0; 357} 358 359static int 360mfi_init_ccb(struct mfi_softc *sc) 361{ 362 struct mfi_ccb *ccb; 363 uint32_t i; 364 int error; 365 bus_addr_t io_req_base_phys; 366 uint8_t *io_req_base; 367 int offset; 368 369 DNPRINTF(MFI_D_CCB, "%s: mfi_init_ccb\n", DEVNAME(sc)); 370 371 sc->sc_ccb = malloc(sizeof(struct mfi_ccb) * sc->sc_max_cmds, 372 M_DEVBUF, M_WAITOK|M_ZERO); 373 if (sc->sc_ioptype == MFI_IOP_TBOLT) { 374 /* 375 * The first 256 bytes (SMID 0) is not used. 376 * Don't add to the cmd list. 377 */ 378 io_req_base = (uint8_t *)MFIMEM_KVA(sc->sc_tbolt_reqmsgpool) + 379 MEGASAS_THUNDERBOLT_NEW_MSG_SIZE; 380 io_req_base_phys = MFIMEM_DVA(sc->sc_tbolt_reqmsgpool) + 381 MEGASAS_THUNDERBOLT_NEW_MSG_SIZE; 382 } 383 384 for (i = 0; i < sc->sc_max_cmds; i++) { 385 ccb = &sc->sc_ccb[i]; 386 387 ccb->ccb_sc = sc; 388 389 /* select i'th frame */ 390 ccb->ccb_frame = (union mfi_frame *) 391 ((char*)MFIMEM_KVA(sc->sc_frames) + sc->sc_frames_size * i); 392 ccb->ccb_pframe = 393 MFIMEM_DVA(sc->sc_frames) + sc->sc_frames_size * i; 394 ccb->ccb_frame->mfr_header.mfh_context = i; 395 396 /* select i'th sense */ 397 ccb->ccb_sense = (struct mfi_sense *) 398 ((char*)MFIMEM_KVA(sc->sc_sense) + MFI_SENSE_SIZE * i); 399 ccb->ccb_psense = 400 (MFIMEM_DVA(sc->sc_sense) + MFI_SENSE_SIZE * i); 401 402 /* create a dma map for transfer */ 403 error = bus_dmamap_create(sc->sc_datadmat, 404 MAXPHYS, sc->sc_max_sgl, MAXPHYS, 0, 405 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ccb->ccb_dmamap); 406 if (error) { 407 aprint_error_dev(sc->sc_dev, 408 "cannot create ccb dmamap (%d)\n", error); 409 goto destroy; 410 } 411 if (sc->sc_ioptype == MFI_IOP_TBOLT) { 412 offset = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * i; 413 ccb->ccb_tb_io_request = 414 (struct mfi_mpi2_request_raid_scsi_io *) 415 (io_req_base + offset); 416 ccb->ccb_tb_pio_request = 417 io_req_base_phys + offset; 418 offset = MEGASAS_MAX_SZ_CHAIN_FRAME * i; 419 ccb->ccb_tb_sg_frame = 420 (mpi2_sge_io_union *)(sc->sc_reply_pool_limit + 421 offset); 422 ccb->ccb_tb_psg_frame = sc->sc_sg_frame_busaddr + 423 offset; 424 /* SMID 0 is reserved. Set SMID/index from 1 */ 425 ccb->ccb_tb_request_desc.header.SMID = i + 1; 426 } 427 428 DNPRINTF(MFI_D_CCB, 429 "ccb(%d): %p frame: %#lx (%#lx) sense: %#lx (%#lx) map: %#lx\n", 430 ccb->ccb_frame->mfr_header.mfh_context, ccb, 431 (u_long)ccb->ccb_frame, (u_long)ccb->ccb_pframe, 432 (u_long)ccb->ccb_sense, (u_long)ccb->ccb_psense, 433 (u_long)ccb->ccb_dmamap); 434 435 /* add ccb to queue */ 436 mfi_put_ccb(ccb); 437 } 438 439 return 0; 440destroy: 441 /* free dma maps and ccb memory */ 442 while (i) { 443 i--; 444 ccb = &sc->sc_ccb[i]; 445 bus_dmamap_destroy(sc->sc_datadmat, ccb->ccb_dmamap); 446 } 447 448 free(sc->sc_ccb, M_DEVBUF); 449 450 return 1; 451} 452 453static uint32_t 454mfi_read(struct mfi_softc *sc, bus_size_t r) 455{ 456 uint32_t rv; 457 458 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 459 BUS_SPACE_BARRIER_READ); 460 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r); 461 462 DNPRINTF(MFI_D_RW, "%s: mr 0x%lx 0x08%x ", DEVNAME(sc), (u_long)r, rv); 463 return rv; 464} 465 466static void 467mfi_write(struct mfi_softc *sc, bus_size_t r, uint32_t v) 468{ 469 DNPRINTF(MFI_D_RW, "%s: mw 0x%lx 0x%08x", DEVNAME(sc), (u_long)r, v); 470 471 bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v); 472 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 473 BUS_SPACE_BARRIER_WRITE); 474} 475 476static struct mfi_mem * 477mfi_allocmem(struct mfi_softc *sc, size_t size) 478{ 479 struct mfi_mem *mm; 480 int nsegs; 481 482 DNPRINTF(MFI_D_MEM, "%s: mfi_allocmem: %ld\n", DEVNAME(sc), 483 (long)size); 484 485 mm = malloc(sizeof(struct mfi_mem), M_DEVBUF, M_NOWAIT|M_ZERO); 486 if (mm == NULL) 487 return NULL; 488 489 mm->am_size = size; 490 491 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 492 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mm->am_map) != 0) 493 goto amfree; 494 495 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mm->am_seg, 1, 496 &nsegs, BUS_DMA_NOWAIT) != 0) 497 goto destroy; 498 499 if (bus_dmamem_map(sc->sc_dmat, &mm->am_seg, nsegs, size, &mm->am_kva, 500 BUS_DMA_NOWAIT) != 0) 501 goto free; 502 503 if (bus_dmamap_load(sc->sc_dmat, mm->am_map, mm->am_kva, size, NULL, 504 BUS_DMA_NOWAIT) != 0) 505 goto unmap; 506 507 DNPRINTF(MFI_D_MEM, " kva: %p dva: %p map: %p\n", 508 mm->am_kva, (void *)mm->am_map->dm_segs[0].ds_addr, mm->am_map); 509 510 memset(mm->am_kva, 0, size); 511 return mm; 512 513unmap: 514 bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, size); 515free: 516 bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1); 517destroy: 518 bus_dmamap_destroy(sc->sc_dmat, mm->am_map); 519amfree: 520 free(mm, M_DEVBUF); 521 522 return NULL; 523} 524 525static void 526mfi_freemem(struct mfi_softc *sc, struct mfi_mem **mmp) 527{ 528 struct mfi_mem *mm = *mmp; 529 530 if (mm == NULL) 531 return; 532 533 *mmp = NULL; 534 535 DNPRINTF(MFI_D_MEM, "%s: mfi_freemem: %p\n", DEVNAME(sc), mm); 536 537 bus_dmamap_unload(sc->sc_dmat, mm->am_map); 538 bus_dmamem_unmap(sc->sc_dmat, mm->am_kva, mm->am_size); 539 bus_dmamem_free(sc->sc_dmat, &mm->am_seg, 1); 540 bus_dmamap_destroy(sc->sc_dmat, mm->am_map); 541 free(mm, M_DEVBUF); 542} 543 544static int 545mfi_transition_firmware(struct mfi_softc *sc) 546{ 547 uint32_t fw_state, cur_state; 548 int max_wait, i; 549 550 fw_state = mfi_fw_state(sc) & MFI_STATE_MASK; 551 552 DNPRINTF(MFI_D_CMD, "%s: mfi_transition_firmware: %#x\n", DEVNAME(sc), 553 fw_state); 554 555 while (fw_state != MFI_STATE_READY) { 556 DNPRINTF(MFI_D_MISC, 557 "%s: waiting for firmware to become ready\n", 558 DEVNAME(sc)); 559 cur_state = fw_state; 560 switch (fw_state) { 561 case MFI_STATE_FAULT: 562 aprint_error_dev(sc->sc_dev, "firmware fault\n"); 563 return 1; 564 case MFI_STATE_WAIT_HANDSHAKE: 565 if (sc->sc_ioptype == MFI_IOP_SKINNY || 566 sc->sc_ioptype == MFI_IOP_TBOLT) 567 mfi_write(sc, MFI_SKINNY_IDB, MFI_INIT_CLEAR_HANDSHAKE); 568 else 569 mfi_write(sc, MFI_IDB, MFI_INIT_CLEAR_HANDSHAKE); 570 max_wait = 2; 571 break; 572 case MFI_STATE_OPERATIONAL: 573 if (sc->sc_ioptype == MFI_IOP_SKINNY || 574 sc->sc_ioptype == MFI_IOP_TBOLT) 575 mfi_write(sc, MFI_SKINNY_IDB, MFI_INIT_READY); 576 else 577 mfi_write(sc, MFI_IDB, MFI_INIT_READY); 578 max_wait = 10; 579 break; 580 case MFI_STATE_UNDEFINED: 581 case MFI_STATE_BB_INIT: 582 max_wait = 2; 583 break; 584 case MFI_STATE_FW_INIT: 585 case MFI_STATE_DEVICE_SCAN: 586 case MFI_STATE_FLUSH_CACHE: 587 max_wait = 20; 588 break; 589 case MFI_STATE_BOOT_MESSAGE_PENDING: 590 if (sc->sc_ioptype == MFI_IOP_SKINNY || 591 sc->sc_ioptype == MFI_IOP_TBOLT) { 592 mfi_write(sc, MFI_SKINNY_IDB, MFI_INIT_HOTPLUG); 593 } else { 594 mfi_write(sc, MFI_IDB, MFI_INIT_HOTPLUG); 595 } 596 max_wait = 180; 597 break; 598 default: 599 aprint_error_dev(sc->sc_dev, 600 "unknown firmware state %d\n", fw_state); 601 return 1; 602 } 603 for (i = 0; i < (max_wait * 10); i++) { 604 fw_state = mfi_fw_state(sc) & MFI_STATE_MASK; 605 if (fw_state == cur_state) 606 DELAY(100000); 607 else 608 break; 609 } 610 if (fw_state == cur_state) { 611 aprint_error_dev(sc->sc_dev, 612 "firmware stuck in state %#x\n", fw_state); 613 return 1; 614 } 615 } 616 617 return 0; 618} 619 620static int 621mfi_initialize_firmware(struct mfi_softc *sc) 622{ 623 struct mfi_ccb *ccb; 624 struct mfi_init_frame *init; 625 struct mfi_init_qinfo *qinfo; 626 627 DNPRINTF(MFI_D_MISC, "%s: mfi_initialize_firmware\n", DEVNAME(sc)); 628 629 if ((ccb = mfi_get_ccb(sc)) == NULL) 630 return 1; 631 632 init = &ccb->ccb_frame->mfr_init; 633 qinfo = (struct mfi_init_qinfo *)((uint8_t *)init + MFI_FRAME_SIZE); 634 635 memset(qinfo, 0, sizeof *qinfo); 636 qinfo->miq_rq_entries = sc->sc_max_cmds + 1; 637 qinfo->miq_rq_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) + 638 offsetof(struct mfi_prod_cons, mpc_reply_q)); 639 qinfo->miq_pi_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) + 640 offsetof(struct mfi_prod_cons, mpc_producer)); 641 qinfo->miq_ci_addr_lo = htole32(MFIMEM_DVA(sc->sc_pcq) + 642 offsetof(struct mfi_prod_cons, mpc_consumer)); 643 644 init->mif_header.mfh_cmd = MFI_CMD_INIT; 645 init->mif_header.mfh_data_len = sizeof *qinfo; 646 init->mif_qinfo_new_addr_lo = htole32(ccb->ccb_pframe + MFI_FRAME_SIZE); 647 648 DNPRINTF(MFI_D_MISC, "%s: entries: %#x rq: %#x pi: %#x ci: %#x\n", 649 DEVNAME(sc), 650 qinfo->miq_rq_entries, qinfo->miq_rq_addr_lo, 651 qinfo->miq_pi_addr_lo, qinfo->miq_ci_addr_lo); 652 653 if (mfi_poll(ccb)) { 654 aprint_error_dev(sc->sc_dev, 655 "mfi_initialize_firmware failed\n"); 656 return 1; 657 } 658 659 mfi_put_ccb(ccb); 660 661 return 0; 662} 663 664static int 665mfi_get_info(struct mfi_softc *sc) 666{ 667#ifdef MFI_DEBUG 668 int i; 669#endif 670 DNPRINTF(MFI_D_MISC, "%s: mfi_get_info\n", DEVNAME(sc)); 671 672 if (mfi_mgmt_internal(sc, MR_DCMD_CTRL_GET_INFO, MFI_DATA_IN, 673 sizeof(sc->sc_info), &sc->sc_info, NULL, cold ? true : false)) 674 return 1; 675 676#ifdef MFI_DEBUG 677 678 for (i = 0; i < sc->sc_info.mci_image_component_count; i++) { 679 printf("%s: active FW %s Version %s date %s time %s\n", 680 DEVNAME(sc), 681 sc->sc_info.mci_image_component[i].mic_name, 682 sc->sc_info.mci_image_component[i].mic_version, 683 sc->sc_info.mci_image_component[i].mic_build_date, 684 sc->sc_info.mci_image_component[i].mic_build_time); 685 } 686 687 for (i = 0; i < sc->sc_info.mci_pending_image_component_count; i++) { 688 printf("%s: pending FW %s Version %s date %s time %s\n", 689 DEVNAME(sc), 690 sc->sc_info.mci_pending_image_component[i].mic_name, 691 sc->sc_info.mci_pending_image_component[i].mic_version, 692 sc->sc_info.mci_pending_image_component[i].mic_build_date, 693 sc->sc_info.mci_pending_image_component[i].mic_build_time); 694 } 695 696 printf("%s: max_arms %d max_spans %d max_arrs %d max_lds %d name %s\n", 697 DEVNAME(sc), 698 sc->sc_info.mci_max_arms, 699 sc->sc_info.mci_max_spans, 700 sc->sc_info.mci_max_arrays, 701 sc->sc_info.mci_max_lds, 702 sc->sc_info.mci_product_name); 703 704 printf("%s: serial %s present %#x fw time %d max_cmds %d max_sg %d\n", 705 DEVNAME(sc), 706 sc->sc_info.mci_serial_number, 707 sc->sc_info.mci_hw_present, 708 sc->sc_info.mci_current_fw_time, 709 sc->sc_info.mci_max_cmds, 710 sc->sc_info.mci_max_sg_elements); 711 712 printf("%s: max_rq %d lds_pres %d lds_deg %d lds_off %d pd_pres %d\n", 713 DEVNAME(sc), 714 sc->sc_info.mci_max_request_size, 715 sc->sc_info.mci_lds_present, 716 sc->sc_info.mci_lds_degraded, 717 sc->sc_info.mci_lds_offline, 718 sc->sc_info.mci_pd_present); 719 720 printf("%s: pd_dsk_prs %d pd_dsk_pred_fail %d pd_dsk_fail %d\n", 721 DEVNAME(sc), 722 sc->sc_info.mci_pd_disks_present, 723 sc->sc_info.mci_pd_disks_pred_failure, 724 sc->sc_info.mci_pd_disks_failed); 725 726 printf("%s: nvram %d mem %d flash %d\n", 727 DEVNAME(sc), 728 sc->sc_info.mci_nvram_size, 729 sc->sc_info.mci_memory_size, 730 sc->sc_info.mci_flash_size); 731 732 printf("%s: ram_cor %d ram_uncor %d clus_all %d clus_act %d\n", 733 DEVNAME(sc), 734 sc->sc_info.mci_ram_correctable_errors, 735 sc->sc_info.mci_ram_uncorrectable_errors, 736 sc->sc_info.mci_cluster_allowed, 737 sc->sc_info.mci_cluster_active); 738 739 printf("%s: max_strps_io %d raid_lvl %#x adapt_ops %#x ld_ops %#x\n", 740 DEVNAME(sc), 741 sc->sc_info.mci_max_strips_per_io, 742 sc->sc_info.mci_raid_levels, 743 sc->sc_info.mci_adapter_ops, 744 sc->sc_info.mci_ld_ops); 745 746 printf("%s: strp_sz_min %d strp_sz_max %d pd_ops %#x pd_mix %#x\n", 747 DEVNAME(sc), 748 sc->sc_info.mci_stripe_sz_ops.min, 749 sc->sc_info.mci_stripe_sz_ops.max, 750 sc->sc_info.mci_pd_ops, 751 sc->sc_info.mci_pd_mix_support); 752 753 printf("%s: ecc_bucket %d pckg_prop %s\n", 754 DEVNAME(sc), 755 sc->sc_info.mci_ecc_bucket_count, 756 sc->sc_info.mci_package_version); 757 758 printf("%s: sq_nm %d prd_fail_poll %d intr_thrtl %d intr_thrtl_to %d\n", 759 DEVNAME(sc), 760 sc->sc_info.mci_properties.mcp_seq_num, 761 sc->sc_info.mci_properties.mcp_pred_fail_poll_interval, 762 sc->sc_info.mci_properties.mcp_intr_throttle_cnt, 763 sc->sc_info.mci_properties.mcp_intr_throttle_timeout); 764 765 printf("%s: rbld_rate %d patr_rd_rate %d bgi_rate %d cc_rate %d\n", 766 DEVNAME(sc), 767 sc->sc_info.mci_properties.mcp_rebuild_rate, 768 sc->sc_info.mci_properties.mcp_patrol_read_rate, 769 sc->sc_info.mci_properties.mcp_bgi_rate, 770 sc->sc_info.mci_properties.mcp_cc_rate); 771 772 printf("%s: rc_rate %d ch_flsh %d spin_cnt %d spin_dly %d clus_en %d\n", 773 DEVNAME(sc), 774 sc->sc_info.mci_properties.mcp_recon_rate, 775 sc->sc_info.mci_properties.mcp_cache_flush_interval, 776 sc->sc_info.mci_properties.mcp_spinup_drv_cnt, 777 sc->sc_info.mci_properties.mcp_spinup_delay, 778 sc->sc_info.mci_properties.mcp_cluster_enable); 779 780 printf("%s: coerc %d alarm %d dis_auto_rbld %d dis_bat_wrn %d ecc %d\n", 781 DEVNAME(sc), 782 sc->sc_info.mci_properties.mcp_coercion_mode, 783 sc->sc_info.mci_properties.mcp_alarm_enable, 784 sc->sc_info.mci_properties.mcp_disable_auto_rebuild, 785 sc->sc_info.mci_properties.mcp_disable_battery_warn, 786 sc->sc_info.mci_properties.mcp_ecc_bucket_size); 787 788 printf("%s: ecc_leak %d rest_hs %d exp_encl_dev %d\n", 789 DEVNAME(sc), 790 sc->sc_info.mci_properties.mcp_ecc_bucket_leak_rate, 791 sc->sc_info.mci_properties.mcp_restore_hotspare_on_insertion, 792 sc->sc_info.mci_properties.mcp_expose_encl_devices); 793 794 printf("%s: vendor %#x device %#x subvendor %#x subdevice %#x\n", 795 DEVNAME(sc), 796 sc->sc_info.mci_pci.mip_vendor, 797 sc->sc_info.mci_pci.mip_device, 798 sc->sc_info.mci_pci.mip_subvendor, 799 sc->sc_info.mci_pci.mip_subdevice); 800 801 printf("%s: type %#x port_count %d port_addr ", 802 DEVNAME(sc), 803 sc->sc_info.mci_host.mih_type, 804 sc->sc_info.mci_host.mih_port_count); 805 806 for (i = 0; i < 8; i++) 807 printf("%.0" PRIx64 " ", sc->sc_info.mci_host.mih_port_addr[i]); 808 printf("\n"); 809 810 printf("%s: type %.x port_count %d port_addr ", 811 DEVNAME(sc), 812 sc->sc_info.mci_device.mid_type, 813 sc->sc_info.mci_device.mid_port_count); 814 815 for (i = 0; i < 8; i++) { 816 printf("%.0" PRIx64 " ", 817 sc->sc_info.mci_device.mid_port_addr[i]); 818 } 819 printf("\n"); 820#endif /* MFI_DEBUG */ 821 822 return 0; 823} 824 825static int 826mfi_get_bbu(struct mfi_softc *sc, struct mfi_bbu_status *stat) 827{ 828 DNPRINTF(MFI_D_MISC, "%s: mfi_get_bbu\n", DEVNAME(sc)); 829 830 if (mfi_mgmt_internal(sc, MR_DCMD_BBU_GET_STATUS, MFI_DATA_IN, 831 sizeof(*stat), stat, NULL, cold ? true : false)) 832 return MFI_BBU_UNKNOWN; 833#ifdef MFI_DEBUG 834 printf("bbu type %d, voltage %d, current %d, temperature %d, " 835 "status 0x%x\n", stat->battery_type, stat->voltage, stat->current, 836 stat->temperature, stat->fw_status); 837 printf("details: "); 838 switch(stat->battery_type) { 839 case MFI_BBU_TYPE_IBBU: 840 printf("guage %d relative charge %d charger state %d " 841 "charger ctrl %d\n", stat->detail.ibbu.gas_guage_status, 842 stat->detail.ibbu.relative_charge , 843 stat->detail.ibbu.charger_system_state , 844 stat->detail.ibbu.charger_system_ctrl); 845 printf("\tcurrent %d abs charge %d max error %d\n", 846 stat->detail.ibbu.charging_current , 847 stat->detail.ibbu.absolute_charge , 848 stat->detail.ibbu.max_error); 849 break; 850 case MFI_BBU_TYPE_BBU: 851 printf("guage %d relative charge %d charger state %d\n", 852 stat->detail.ibbu.gas_guage_status, 853 stat->detail.bbu.relative_charge , 854 stat->detail.bbu.charger_status ); 855 printf("\trem capacity %d fyll capacity %d SOH %d\n", 856 stat->detail.bbu.remaining_capacity , 857 stat->detail.bbu.full_charge_capacity , 858 stat->detail.bbu.is_SOH_good); 859 default: 860 printf("\n"); 861 } 862#endif 863 switch(stat->battery_type) { 864 case MFI_BBU_TYPE_BBU: 865 return (stat->detail.bbu.is_SOH_good ? 866 MFI_BBU_GOOD : MFI_BBU_BAD); 867 case MFI_BBU_TYPE_NONE: 868 return MFI_BBU_UNKNOWN; 869 default: 870 if (stat->fw_status & 871 (MFI_BBU_STATE_PACK_MISSING | 872 MFI_BBU_STATE_VOLTAGE_LOW | 873 MFI_BBU_STATE_TEMPERATURE_HIGH | 874 MFI_BBU_STATE_LEARN_CYC_FAIL | 875 MFI_BBU_STATE_LEARN_CYC_TIMEOUT | 876 MFI_BBU_STATE_I2C_ERR_DETECT)) 877 return MFI_BBU_BAD; 878 return MFI_BBU_GOOD; 879 } 880} 881 882static void 883mfiminphys(struct buf *bp) 884{ 885 DNPRINTF(MFI_D_MISC, "mfiminphys: %d\n", bp->b_bcount); 886 887 /* XXX currently using MFI_MAXFER = MAXPHYS */ 888 if (bp->b_bcount > MFI_MAXFER) 889 bp->b_bcount = MFI_MAXFER; 890 minphys(bp); 891} 892 893int 894mfi_rescan(device_t self, const char *ifattr, const int *locators) 895{ 896 struct mfi_softc *sc = device_private(self); 897 898 if (sc->sc_child != NULL) 899 return 0; 900 901 sc->sc_child = config_found_sm_loc(self, ifattr, locators, &sc->sc_chan, 902 scsiprint, NULL); 903 904 return 0; 905} 906 907void 908mfi_childdetached(device_t self, device_t child) 909{ 910 struct mfi_softc *sc = device_private(self); 911 912 KASSERT(self == sc->sc_dev); 913 KASSERT(child == sc->sc_child); 914 915 if (child == sc->sc_child) 916 sc->sc_child = NULL; 917} 918 919int 920mfi_detach(struct mfi_softc *sc, int flags) 921{ 922 int error; 923 924 DNPRINTF(MFI_D_MISC, "%s: mfi_detach\n", DEVNAME(sc)); 925 926 if ((error = config_detach_children(sc->sc_dev, flags)) != 0) 927 return error; 928 929#if NBIO > 0 930 mfi_destroy_sensors(sc); 931 bio_unregister(sc->sc_dev); 932#endif /* NBIO > 0 */ 933 934 mfi_intr_disable(sc); 935 mfi_shutdown(sc->sc_dev, 0); 936 937 if (sc->sc_ioptype == MFI_IOP_TBOLT) { 938 workqueue_destroy(sc->sc_ldsync_wq); 939 mfi_put_ccb(sc->sc_ldsync_ccb); 940 mfi_freemem(sc, &sc->sc_tbolt_reqmsgpool); 941 mfi_freemem(sc, &sc->sc_tbolt_ioc_init); 942 mfi_freemem(sc, &sc->sc_tbolt_verbuf); 943 } 944 945 if ((error = mfi_destroy_ccb(sc)) != 0) 946 return error; 947 948 mfi_freemem(sc, &sc->sc_sense); 949 950 mfi_freemem(sc, &sc->sc_frames); 951 952 mfi_freemem(sc, &sc->sc_pcq); 953 954 return 0; 955} 956 957static bool 958mfi_shutdown(device_t dev, int how) 959{ 960 struct mfi_softc *sc = device_private(dev); 961 uint8_t mbox[MFI_MBOX_SIZE]; 962 int s = splbio(); 963 DNPRINTF(MFI_D_MISC, "%s: mfi_shutdown\n", DEVNAME(sc)); 964 if (sc->sc_running) { 965 mbox[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; 966 if (mfi_mgmt_internal(sc, MR_DCMD_CTRL_CACHE_FLUSH, 967 MFI_DATA_NONE, 0, NULL, mbox, true)) { 968 aprint_error_dev(dev, "shutdown: cache flush failed\n"); 969 goto fail; 970 } 971 972 mbox[0] = 0; 973 if (mfi_mgmt_internal(sc, MR_DCMD_CTRL_SHUTDOWN, 974 MFI_DATA_NONE, 0, NULL, mbox, true)) { 975 aprint_error_dev(dev, "shutdown: " 976 "firmware shutdown failed\n"); 977 goto fail; 978 } 979 sc->sc_running = false; 980 } 981 splx(s); 982 return true; 983fail: 984 splx(s); 985 return false; 986} 987 988static bool 989mfi_suspend(device_t dev, const pmf_qual_t *q) 990{ 991 /* XXX to be implemented */ 992 return false; 993} 994 995static bool 996mfi_resume(device_t dev, const pmf_qual_t *q) 997{ 998 /* XXX to be implemented */ 999 return false; 1000} 1001 1002int 1003mfi_attach(struct mfi_softc *sc, enum mfi_iop iop) 1004{ 1005 struct scsipi_adapter *adapt = &sc->sc_adapt; 1006 struct scsipi_channel *chan = &sc->sc_chan; 1007 uint32_t status, frames, max_sgl; 1008 int i; 1009 1010 DNPRINTF(MFI_D_MISC, "%s: mfi_attach\n", DEVNAME(sc)); 1011 1012 sc->sc_ioptype = iop; 1013 1014 switch (iop) { 1015 case MFI_IOP_XSCALE: 1016 sc->sc_iop = &mfi_iop_xscale; 1017 break; 1018 case MFI_IOP_PPC: 1019 sc->sc_iop = &mfi_iop_ppc; 1020 break; 1021 case MFI_IOP_GEN2: 1022 sc->sc_iop = &mfi_iop_gen2; 1023 break; 1024 case MFI_IOP_SKINNY: 1025 sc->sc_iop = &mfi_iop_skinny; 1026 break; 1027 case MFI_IOP_TBOLT: 1028 sc->sc_iop = &mfi_iop_tbolt; 1029 break; 1030 default: 1031 panic("%s: unknown iop %d", DEVNAME(sc), iop); 1032 } 1033 1034 if (mfi_transition_firmware(sc)) 1035 return 1; 1036 1037 TAILQ_INIT(&sc->sc_ccb_freeq); 1038 1039 status = mfi_fw_state(sc); 1040 sc->sc_max_cmds = status & MFI_STATE_MAXCMD_MASK; 1041 max_sgl = (status & MFI_STATE_MAXSGL_MASK) >> 16; 1042 if (sc->sc_ioptype == MFI_IOP_TBOLT) { 1043 sc->sc_max_sgl = min(max_sgl, (128 * 1024) / PAGE_SIZE + 1); 1044 sc->sc_sgl_size = sizeof(struct mfi_sg_ieee); 1045 } else if (sc->sc_64bit_dma) { 1046 sc->sc_max_sgl = min(max_sgl, (128 * 1024) / PAGE_SIZE + 1); 1047 sc->sc_sgl_size = sizeof(struct mfi_sg64); 1048 } else { 1049 sc->sc_max_sgl = max_sgl; 1050 sc->sc_sgl_size = sizeof(struct mfi_sg32); 1051 } 1052 DNPRINTF(MFI_D_MISC, "%s: max commands: %u, max sgl: %u\n", 1053 DEVNAME(sc), sc->sc_max_cmds, sc->sc_max_sgl); 1054 1055 if (sc->sc_ioptype == MFI_IOP_TBOLT) { 1056 uint32_t tb_mem_size; 1057 /* for Alignment */ 1058 tb_mem_size = MEGASAS_THUNDERBOLT_MSG_ALLIGNMENT; 1059 1060 tb_mem_size += 1061 MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * (sc->sc_max_cmds + 1); 1062 sc->sc_reply_pool_size = 1063 ((sc->sc_max_cmds + 1 + 15) / 16) * 16; 1064 tb_mem_size += 1065 MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size; 1066 1067 /* this is for SGL's */ 1068 tb_mem_size += MEGASAS_MAX_SZ_CHAIN_FRAME * sc->sc_max_cmds; 1069 sc->sc_tbolt_reqmsgpool = mfi_allocmem(sc, tb_mem_size); 1070 if (sc->sc_tbolt_reqmsgpool == NULL) { 1071 aprint_error_dev(sc->sc_dev, 1072 "unable to allocate thunderbolt " 1073 "request message pool\n"); 1074 goto nopcq; 1075 } 1076 if (mfi_tbolt_init_desc_pool(sc)) { 1077 aprint_error_dev(sc->sc_dev, 1078 "Thunderbolt pool preparation error\n"); 1079 goto nopcq; 1080 } 1081 1082 /* 1083 * Allocate DMA memory mapping for MPI2 IOC Init descriptor, 1084 * we are taking it diffrent from what we have allocated for 1085 * Request and reply descriptors to avoid confusion later 1086 */ 1087 sc->sc_tbolt_ioc_init = mfi_allocmem(sc, 1088 sizeof(struct mpi2_ioc_init_request)); 1089 if (sc->sc_tbolt_ioc_init == NULL) { 1090 aprint_error_dev(sc->sc_dev, 1091 "unable to allocate thunderbolt IOC init memory"); 1092 goto nopcq; 1093 } 1094 1095 sc->sc_tbolt_verbuf = mfi_allocmem(sc, 1096 MEGASAS_MAX_NAME*sizeof(bus_addr_t)); 1097 if (sc->sc_tbolt_verbuf == NULL) { 1098 aprint_error_dev(sc->sc_dev, 1099 "unable to allocate thunderbolt version buffer\n"); 1100 goto nopcq; 1101 } 1102 1103 } 1104 /* consumer/producer and reply queue memory */ 1105 sc->sc_pcq = mfi_allocmem(sc, (sizeof(uint32_t) * sc->sc_max_cmds) + 1106 sizeof(struct mfi_prod_cons)); 1107 if (sc->sc_pcq == NULL) { 1108 aprint_error_dev(sc->sc_dev, 1109 "unable to allocate reply queue memory\n"); 1110 goto nopcq; 1111 } 1112 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq), 0, 1113 sizeof(uint32_t) * sc->sc_max_cmds + sizeof(struct mfi_prod_cons), 1114 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1115 1116 /* frame memory */ 1117 frames = (sc->sc_sgl_size * sc->sc_max_sgl + MFI_FRAME_SIZE - 1) / 1118 MFI_FRAME_SIZE + 1; 1119 sc->sc_frames_size = frames * MFI_FRAME_SIZE; 1120 sc->sc_frames = mfi_allocmem(sc, sc->sc_frames_size * sc->sc_max_cmds); 1121 if (sc->sc_frames == NULL) { 1122 aprint_error_dev(sc->sc_dev, 1123 "unable to allocate frame memory\n"); 1124 goto noframe; 1125 } 1126 /* XXX hack, fix this */ 1127 if (MFIMEM_DVA(sc->sc_frames) & 0x3f) { 1128 aprint_error_dev(sc->sc_dev, 1129 "improper frame alignment (%#llx) FIXME\n", 1130 (long long int)MFIMEM_DVA(sc->sc_frames)); 1131 goto noframe; 1132 } 1133 1134 /* sense memory */ 1135 sc->sc_sense = mfi_allocmem(sc, sc->sc_max_cmds * MFI_SENSE_SIZE); 1136 if (sc->sc_sense == NULL) { 1137 aprint_error_dev(sc->sc_dev, 1138 "unable to allocate sense memory\n"); 1139 goto nosense; 1140 } 1141 1142 /* now that we have all memory bits go initialize ccbs */ 1143 if (mfi_init_ccb(sc)) { 1144 aprint_error_dev(sc->sc_dev, "could not init ccb list\n"); 1145 goto noinit; 1146 } 1147 1148 /* kickstart firmware with all addresses and pointers */ 1149 if (sc->sc_ioptype == MFI_IOP_TBOLT) { 1150 if (mfi_tbolt_init_MFI_queue(sc)) { 1151 aprint_error_dev(sc->sc_dev, 1152 "could not initialize firmware\n"); 1153 goto noinit; 1154 } 1155 } else { 1156 if (mfi_initialize_firmware(sc)) { 1157 aprint_error_dev(sc->sc_dev, 1158 "could not initialize firmware\n"); 1159 goto noinit; 1160 } 1161 } 1162 sc->sc_running = true; 1163 1164 if (mfi_get_info(sc)) { 1165 aprint_error_dev(sc->sc_dev, 1166 "could not retrieve controller information\n"); 1167 goto noinit; 1168 } 1169 aprint_normal_dev(sc->sc_dev, 1170 "%s version %s\n", 1171 sc->sc_info.mci_product_name, 1172 sc->sc_info.mci_package_version); 1173 1174 1175 aprint_normal_dev(sc->sc_dev, "logical drives %d, %dMB RAM, ", 1176 sc->sc_info.mci_lds_present, 1177 sc->sc_info.mci_memory_size); 1178 sc->sc_bbuok = false; 1179 if (sc->sc_info.mci_hw_present & MFI_INFO_HW_BBU) { 1180 struct mfi_bbu_status bbu_stat; 1181 int mfi_bbu_status = mfi_get_bbu(sc, &bbu_stat); 1182 aprint_normal("BBU type "); 1183 switch (bbu_stat.battery_type) { 1184 case MFI_BBU_TYPE_BBU: 1185 aprint_normal("BBU"); 1186 break; 1187 case MFI_BBU_TYPE_IBBU: 1188 aprint_normal("IBBU"); 1189 break; 1190 default: 1191 aprint_normal("unknown type %d", bbu_stat.battery_type); 1192 } 1193 aprint_normal(", status "); 1194 switch(mfi_bbu_status) { 1195 case MFI_BBU_GOOD: 1196 aprint_normal("good\n"); 1197 sc->sc_bbuok = true; 1198 break; 1199 case MFI_BBU_BAD: 1200 aprint_normal("bad\n"); 1201 break; 1202 case MFI_BBU_UNKNOWN: 1203 aprint_normal("unknown\n"); 1204 break; 1205 default: 1206 panic("mfi_bbu_status"); 1207 } 1208 } else { 1209 aprint_normal("BBU not present\n"); 1210 } 1211 1212 sc->sc_ld_cnt = sc->sc_info.mci_lds_present; 1213 sc->sc_max_ld = sc->sc_ld_cnt; 1214 for (i = 0; i < sc->sc_ld_cnt; i++) 1215 sc->sc_ld[i].ld_present = 1; 1216 1217 memset(adapt, 0, sizeof(*adapt)); 1218 adapt->adapt_dev = sc->sc_dev; 1219 adapt->adapt_nchannels = 1; 1220 /* keep a few commands for management */ 1221 if (sc->sc_max_cmds > 4) 1222 adapt->adapt_openings = sc->sc_max_cmds - 4; 1223 else 1224 adapt->adapt_openings = sc->sc_max_cmds; 1225 adapt->adapt_max_periph = adapt->adapt_openings; 1226 adapt->adapt_request = mfi_scsipi_request; 1227 adapt->adapt_minphys = mfiminphys; 1228 1229 memset(chan, 0, sizeof(*chan)); 1230 chan->chan_adapter = adapt; 1231 chan->chan_bustype = &scsi_sas_bustype; 1232 chan->chan_channel = 0; 1233 chan->chan_flags = 0; 1234 chan->chan_nluns = 8; 1235 chan->chan_ntargets = MFI_MAX_LD; 1236 chan->chan_id = MFI_MAX_LD; 1237 1238 mfi_rescan(sc->sc_dev, "scsi", NULL); 1239 1240 /* enable interrupts */ 1241 mfi_intr_enable(sc); 1242 1243#if NBIO > 0 1244 if (bio_register(sc->sc_dev, mfi_ioctl) != 0) 1245 panic("%s: controller registration failed", DEVNAME(sc)); 1246 if (mfi_create_sensors(sc) != 0) 1247 aprint_error_dev(sc->sc_dev, "unable to create sensors\n"); 1248#endif /* NBIO > 0 */ 1249 if (!pmf_device_register1(sc->sc_dev, mfi_suspend, mfi_resume, 1250 mfi_shutdown)) { 1251 aprint_error_dev(sc->sc_dev, 1252 "couldn't establish power handler\n"); 1253 } 1254 1255 return 0; 1256noinit: 1257 mfi_freemem(sc, &sc->sc_sense); 1258nosense: 1259 mfi_freemem(sc, &sc->sc_frames); 1260noframe: 1261 mfi_freemem(sc, &sc->sc_pcq); 1262nopcq: 1263 if (sc->sc_ioptype == MFI_IOP_TBOLT) { 1264 if (sc->sc_tbolt_reqmsgpool) 1265 mfi_freemem(sc, &sc->sc_tbolt_reqmsgpool); 1266 if (sc->sc_tbolt_verbuf) 1267 mfi_freemem(sc, &sc->sc_tbolt_verbuf); 1268 } 1269 return 1; 1270} 1271 1272static int 1273mfi_poll(struct mfi_ccb *ccb) 1274{ 1275 struct mfi_softc *sc = ccb->ccb_sc; 1276 struct mfi_frame_header *hdr; 1277 int to = 0; 1278 int rv = 0; 1279 1280 DNPRINTF(MFI_D_CMD, "%s: mfi_poll\n", DEVNAME(sc)); 1281 1282 hdr = &ccb->ccb_frame->mfr_header; 1283 hdr->mfh_cmd_status = 0xff; 1284 if (!sc->sc_MFA_enabled) 1285 hdr->mfh_flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; 1286 1287 /* no callback, caller is supposed to do the cleanup */ 1288 ccb->ccb_done = NULL; 1289 1290 mfi_post(sc, ccb); 1291 if (sc->sc_MFA_enabled) { 1292 /* 1293 * depending on the command type, result may be posted 1294 * to *hdr, or not. In addition it seems there's 1295 * no way to avoid posting the SMID to the reply queue. 1296 * So pool using the interrupt routine. 1297 */ 1298 while (ccb->ccb_state != MFI_CCB_DONE) { 1299 delay(1000); 1300 if (to++ > 5000) { /* XXX 5 seconds busywait sucks */ 1301 rv = 1; 1302 break; 1303 } 1304 mfi_tbolt_intrh(sc); 1305 } 1306 } else { 1307 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames), 1308 ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames), 1309 sc->sc_frames_size, BUS_DMASYNC_POSTREAD); 1310 1311 while (hdr->mfh_cmd_status == 0xff) { 1312 delay(1000); 1313 if (to++ > 5000) { /* XXX 5 seconds busywait sucks */ 1314 rv = 1; 1315 break; 1316 } 1317 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames), 1318 ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames), 1319 sc->sc_frames_size, BUS_DMASYNC_POSTREAD); 1320 } 1321 } 1322 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames), 1323 ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames), 1324 sc->sc_frames_size, BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1325 1326 if (ccb->ccb_data != NULL) { 1327 DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done sync\n", 1328 DEVNAME(sc)); 1329 bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0, 1330 ccb->ccb_dmamap->dm_mapsize, 1331 (ccb->ccb_direction & MFI_DATA_IN) ? 1332 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1333 1334 bus_dmamap_unload(sc->sc_datadmat, ccb->ccb_dmamap); 1335 } 1336 1337 if (rv != 0) { 1338 aprint_error_dev(sc->sc_dev, "timeout on ccb %d\n", 1339 hdr->mfh_context); 1340 ccb->ccb_flags |= MFI_CCB_F_ERR; 1341 return 1; 1342 } 1343 1344 return 0; 1345} 1346 1347int 1348mfi_intr(void *arg) 1349{ 1350 struct mfi_softc *sc = arg; 1351 struct mfi_prod_cons *pcq; 1352 struct mfi_ccb *ccb; 1353 uint32_t producer, consumer, ctx; 1354 int claimed = 0; 1355 1356 if (!mfi_my_intr(sc)) 1357 return 0; 1358 1359 pcq = MFIMEM_KVA(sc->sc_pcq); 1360 1361 DNPRINTF(MFI_D_INTR, "%s: mfi_intr %#lx %#lx\n", DEVNAME(sc), 1362 (u_long)sc, (u_long)pcq); 1363 1364 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq), 0, 1365 sizeof(uint32_t) * sc->sc_max_cmds + sizeof(struct mfi_prod_cons), 1366 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1367 1368 producer = pcq->mpc_producer; 1369 consumer = pcq->mpc_consumer; 1370 1371 while (consumer != producer) { 1372 DNPRINTF(MFI_D_INTR, "%s: mfi_intr pi %#x ci %#x\n", 1373 DEVNAME(sc), producer, consumer); 1374 1375 ctx = pcq->mpc_reply_q[consumer]; 1376 pcq->mpc_reply_q[consumer] = MFI_INVALID_CTX; 1377 if (ctx == MFI_INVALID_CTX) 1378 aprint_error_dev(sc->sc_dev, 1379 "invalid context, p: %d c: %d\n", 1380 producer, consumer); 1381 else { 1382 /* XXX remove from queue and call scsi_done */ 1383 ccb = &sc->sc_ccb[ctx]; 1384 DNPRINTF(MFI_D_INTR, "%s: mfi_intr context %#x\n", 1385 DEVNAME(sc), ctx); 1386 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames), 1387 ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames), 1388 sc->sc_frames_size, 1389 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 1390 ccb->ccb_done(ccb); 1391 1392 claimed = 1; 1393 } 1394 consumer++; 1395 if (consumer == (sc->sc_max_cmds + 1)) 1396 consumer = 0; 1397 } 1398 1399 pcq->mpc_consumer = consumer; 1400 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_pcq), 0, 1401 sizeof(uint32_t) * sc->sc_max_cmds + sizeof(struct mfi_prod_cons), 1402 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 1403 1404 return claimed; 1405} 1406 1407static int 1408mfi_scsi_ld_io(struct mfi_ccb *ccb, struct scsipi_xfer *xs, uint64_t blockno, 1409 uint32_t blockcnt) 1410{ 1411 struct scsipi_periph *periph = xs->xs_periph; 1412 struct mfi_io_frame *io; 1413 1414 DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_ld_io: %d\n", 1415 device_xname(periph->periph_channel->chan_adapter->adapt_dev), 1416 periph->periph_target); 1417 1418 if (!xs->data) 1419 return 1; 1420 1421 io = &ccb->ccb_frame->mfr_io; 1422 if (xs->xs_control & XS_CTL_DATA_IN) { 1423 io->mif_header.mfh_cmd = MFI_CMD_LD_READ; 1424 ccb->ccb_direction = MFI_DATA_IN; 1425 } else { 1426 io->mif_header.mfh_cmd = MFI_CMD_LD_WRITE; 1427 ccb->ccb_direction = MFI_DATA_OUT; 1428 } 1429 io->mif_header.mfh_target_id = periph->periph_target; 1430 io->mif_header.mfh_timeout = 0; 1431 io->mif_header.mfh_flags = 0; 1432 io->mif_header.mfh_sense_len = MFI_SENSE_SIZE; 1433 io->mif_header.mfh_data_len= blockcnt; 1434 io->mif_lba_hi = (blockno >> 32); 1435 io->mif_lba_lo = (blockno & 0xffffffff); 1436 io->mif_sense_addr_lo = htole32(ccb->ccb_psense); 1437 io->mif_sense_addr_hi = 0; 1438 1439 ccb->ccb_done = mfi_scsi_ld_done; 1440 ccb->ccb_xs = xs; 1441 ccb->ccb_frame_size = MFI_IO_FRAME_SIZE; 1442 ccb->ccb_sgl = &io->mif_sgl; 1443 ccb->ccb_data = xs->data; 1444 ccb->ccb_len = xs->datalen; 1445 1446 if (mfi_create_sgl(ccb, (xs->xs_control & XS_CTL_NOSLEEP) ? 1447 BUS_DMA_NOWAIT : BUS_DMA_WAITOK)) 1448 return 1; 1449 1450 return 0; 1451} 1452 1453static void 1454mfi_scsi_ld_done(struct mfi_ccb *ccb) 1455{ 1456 struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header; 1457 mfi_scsi_xs_done(ccb, hdr->mfh_cmd_status, hdr->mfh_scsi_status); 1458} 1459 1460static void 1461mfi_scsi_xs_done(struct mfi_ccb *ccb, int status, int scsi_status) 1462{ 1463 struct scsipi_xfer *xs = ccb->ccb_xs; 1464 struct mfi_softc *sc = ccb->ccb_sc; 1465 1466 DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done %#lx %#lx\n", 1467 DEVNAME(sc), (u_long)ccb, (u_long)ccb->ccb_frame); 1468 1469 if (xs->data != NULL) { 1470 DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done sync\n", 1471 DEVNAME(sc)); 1472 bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0, 1473 ccb->ccb_dmamap->dm_mapsize, 1474 (xs->xs_control & XS_CTL_DATA_IN) ? 1475 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1476 1477 bus_dmamap_unload(sc->sc_datadmat, ccb->ccb_dmamap); 1478 } 1479 1480 if (status != MFI_STAT_OK) { 1481 xs->error = XS_DRIVER_STUFFUP; 1482 DNPRINTF(MFI_D_INTR, "%s: mfi_scsi_xs_done stuffup %#x\n", 1483 DEVNAME(sc), status); 1484 1485 if (scsi_status != 0) { 1486 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_sense), 1487 ccb->ccb_psense - MFIMEM_DVA(sc->sc_sense), 1488 MFI_SENSE_SIZE, BUS_DMASYNC_POSTREAD); 1489 DNPRINTF(MFI_D_INTR, 1490 "%s: mfi_scsi_xs_done sense %#x %lx %lx\n", 1491 DEVNAME(sc), scsi_status, 1492 (u_long)&xs->sense, (u_long)ccb->ccb_sense); 1493 memset(&xs->sense, 0, sizeof(xs->sense)); 1494 memcpy(&xs->sense, ccb->ccb_sense, 1495 sizeof(struct scsi_sense_data)); 1496 xs->error = XS_SENSE; 1497 } 1498 } else { 1499 xs->error = XS_NOERROR; 1500 xs->status = SCSI_OK; 1501 xs->resid = 0; 1502 } 1503 1504 mfi_put_ccb(ccb); 1505 scsipi_done(xs); 1506} 1507 1508static int 1509mfi_scsi_ld(struct mfi_ccb *ccb, struct scsipi_xfer *xs) 1510{ 1511 struct mfi_pass_frame *pf; 1512 struct scsipi_periph *periph = xs->xs_periph; 1513 1514 DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_ld: %d\n", 1515 device_xname(periph->periph_channel->chan_adapter->adapt_dev), 1516 periph->periph_target); 1517 1518 pf = &ccb->ccb_frame->mfr_pass; 1519 pf->mpf_header.mfh_cmd = MFI_CMD_LD_SCSI_IO; 1520 pf->mpf_header.mfh_target_id = periph->periph_target; 1521 pf->mpf_header.mfh_lun_id = 0; 1522 pf->mpf_header.mfh_cdb_len = xs->cmdlen; 1523 pf->mpf_header.mfh_timeout = 0; 1524 pf->mpf_header.mfh_data_len= xs->datalen; /* XXX */ 1525 pf->mpf_header.mfh_sense_len = MFI_SENSE_SIZE; 1526 1527 pf->mpf_sense_addr_hi = 0; 1528 pf->mpf_sense_addr_lo = htole32(ccb->ccb_psense); 1529 1530 memset(pf->mpf_cdb, 0, 16); 1531 memcpy(pf->mpf_cdb, &xs->cmdstore, xs->cmdlen); 1532 1533 ccb->ccb_done = mfi_scsi_ld_done; 1534 ccb->ccb_xs = xs; 1535 ccb->ccb_frame_size = MFI_PASS_FRAME_SIZE; 1536 ccb->ccb_sgl = &pf->mpf_sgl; 1537 1538 if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) 1539 ccb->ccb_direction = (xs->xs_control & XS_CTL_DATA_IN) ? 1540 MFI_DATA_IN : MFI_DATA_OUT; 1541 else 1542 ccb->ccb_direction = MFI_DATA_NONE; 1543 1544 if (xs->data) { 1545 ccb->ccb_data = xs->data; 1546 ccb->ccb_len = xs->datalen; 1547 1548 if (mfi_create_sgl(ccb, (xs->xs_control & XS_CTL_NOSLEEP) ? 1549 BUS_DMA_NOWAIT : BUS_DMA_WAITOK)) 1550 return 1; 1551 } 1552 1553 return 0; 1554} 1555 1556static void 1557mfi_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 1558 void *arg) 1559{ 1560 struct scsipi_periph *periph; 1561 struct scsipi_xfer *xs; 1562 struct scsipi_adapter *adapt = chan->chan_adapter; 1563 struct mfi_softc *sc = device_private(adapt->adapt_dev); 1564 struct mfi_ccb *ccb; 1565 struct scsi_rw_6 *rw; 1566 struct scsipi_rw_10 *rwb; 1567 struct scsipi_rw_12 *rw12; 1568 struct scsipi_rw_16 *rw16; 1569 uint64_t blockno; 1570 uint32_t blockcnt; 1571 uint8_t target; 1572 uint8_t mbox[MFI_MBOX_SIZE]; 1573 int s; 1574 1575 switch (req) { 1576 case ADAPTER_REQ_GROW_RESOURCES: 1577 /* Not supported. */ 1578 return; 1579 case ADAPTER_REQ_SET_XFER_MODE: 1580 { 1581 struct scsipi_xfer_mode *xm = arg; 1582 xm->xm_mode = PERIPH_CAP_TQING; 1583 xm->xm_period = 0; 1584 xm->xm_offset = 0; 1585 scsipi_async_event(&sc->sc_chan, ASYNC_EVENT_XFER_MODE, xm); 1586 return; 1587 } 1588 case ADAPTER_REQ_RUN_XFER: 1589 break; 1590 } 1591 1592 xs = arg; 1593 1594 periph = xs->xs_periph; 1595 target = periph->periph_target; 1596 1597 DNPRINTF(MFI_D_CMD, "%s: mfi_scsipi_request req %d opcode: %#x " 1598 "target %d lun %d\n", DEVNAME(sc), req, xs->cmd->opcode, 1599 periph->periph_target, periph->periph_lun); 1600 1601 s = splbio(); 1602 if (target >= MFI_MAX_LD || !sc->sc_ld[target].ld_present || 1603 periph->periph_lun != 0) { 1604 DNPRINTF(MFI_D_CMD, "%s: invalid target %d\n", 1605 DEVNAME(sc), target); 1606 xs->error = XS_SELTIMEOUT; 1607 scsipi_done(xs); 1608 splx(s); 1609 return; 1610 } 1611 if ((xs->cmd->opcode == SCSI_SYNCHRONIZE_CACHE_10 || 1612 xs->cmd->opcode == SCSI_SYNCHRONIZE_CACHE_16) && sc->sc_bbuok) { 1613 /* the cache is stable storage, don't flush */ 1614 xs->error = XS_NOERROR; 1615 xs->status = SCSI_OK; 1616 xs->resid = 0; 1617 scsipi_done(xs); 1618 splx(s); 1619 return; 1620 } 1621 1622 if ((ccb = mfi_get_ccb(sc)) == NULL) { 1623 DNPRINTF(MFI_D_CMD, "%s: mfi_scsipi_request no ccb\n", DEVNAME(sc)); 1624 xs->error = XS_RESOURCE_SHORTAGE; 1625 scsipi_done(xs); 1626 splx(s); 1627 return; 1628 } 1629 1630 switch (xs->cmd->opcode) { 1631 /* IO path */ 1632 case READ_16: 1633 case WRITE_16: 1634 rw16 = (struct scsipi_rw_16 *)xs->cmd; 1635 blockno = _8btol(rw16->addr); 1636 blockcnt = _4btol(rw16->length); 1637 if (sc->sc_iop->mio_ld_io(ccb, xs, blockno, blockcnt)) { 1638 goto stuffup; 1639 } 1640 break; 1641 1642 case READ_12: 1643 case WRITE_12: 1644 rw12 = (struct scsipi_rw_12 *)xs->cmd; 1645 blockno = _4btol(rw12->addr); 1646 blockcnt = _4btol(rw12->length); 1647 if (sc->sc_iop->mio_ld_io(ccb, xs, blockno, blockcnt)) { 1648 goto stuffup; 1649 } 1650 break; 1651 1652 case READ_10: 1653 case WRITE_10: 1654 rwb = (struct scsipi_rw_10 *)xs->cmd; 1655 blockno = _4btol(rwb->addr); 1656 blockcnt = _2btol(rwb->length); 1657 if (sc->sc_iop->mio_ld_io(ccb, xs, blockno, blockcnt)) { 1658 goto stuffup; 1659 } 1660 break; 1661 1662 case SCSI_READ_6_COMMAND: 1663 case SCSI_WRITE_6_COMMAND: 1664 rw = (struct scsi_rw_6 *)xs->cmd; 1665 blockno = _3btol(rw->addr) & (SRW_TOPADDR << 16 | 0xffff); 1666 blockcnt = rw->length ? rw->length : 0x100; 1667 if (sc->sc_iop->mio_ld_io(ccb, xs, blockno, blockcnt)) { 1668 goto stuffup; 1669 } 1670 break; 1671 1672 case SCSI_SYNCHRONIZE_CACHE_10: 1673 case SCSI_SYNCHRONIZE_CACHE_16: 1674 mbox[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; 1675 if (mfi_mgmt(ccb, xs, 1676 MR_DCMD_CTRL_CACHE_FLUSH, MFI_DATA_NONE, 0, NULL, mbox)) { 1677 goto stuffup; 1678 } 1679 break; 1680 1681 /* hand it of to the firmware and let it deal with it */ 1682 case SCSI_TEST_UNIT_READY: 1683 /* save off sd? after autoconf */ 1684 if (!cold) /* XXX bogus */ 1685 strlcpy(sc->sc_ld[target].ld_dev, device_xname(sc->sc_dev), 1686 sizeof(sc->sc_ld[target].ld_dev)); 1687 /* FALLTHROUGH */ 1688 1689 default: 1690 if (mfi_scsi_ld(ccb, xs)) { 1691 goto stuffup; 1692 } 1693 break; 1694 } 1695 1696 DNPRINTF(MFI_D_CMD, "%s: start io %d\n", DEVNAME(sc), target); 1697 1698 if (xs->xs_control & XS_CTL_POLL) { 1699 if (mfi_poll(ccb)) { 1700 /* XXX check for sense in ccb->ccb_sense? */ 1701 aprint_error_dev(sc->sc_dev, 1702 "mfi_scsipi_request poll failed\n"); 1703 memset(&xs->sense, 0, sizeof(xs->sense)); 1704 xs->sense.scsi_sense.response_code = 1705 SSD_RCODE_VALID | SSD_RCODE_CURRENT; 1706 xs->sense.scsi_sense.flags = SKEY_ILLEGAL_REQUEST; 1707 xs->sense.scsi_sense.asc = 0x20; /* invalid opcode */ 1708 xs->error = XS_SENSE; 1709 xs->status = SCSI_CHECK; 1710 } else { 1711 DNPRINTF(MFI_D_DMA, 1712 "%s: mfi_scsipi_request poll complete %d\n", 1713 DEVNAME(sc), ccb->ccb_dmamap->dm_nsegs); 1714 xs->error = XS_NOERROR; 1715 xs->status = SCSI_OK; 1716 xs->resid = 0; 1717 } 1718 mfi_put_ccb(ccb); 1719 scsipi_done(xs); 1720 splx(s); 1721 return; 1722 } 1723 1724 mfi_post(sc, ccb); 1725 1726 DNPRINTF(MFI_D_DMA, "%s: mfi_scsipi_request queued %d\n", DEVNAME(sc), 1727 ccb->ccb_dmamap->dm_nsegs); 1728 1729 splx(s); 1730 return; 1731 1732stuffup: 1733 mfi_put_ccb(ccb); 1734 xs->error = XS_DRIVER_STUFFUP; 1735 scsipi_done(xs); 1736 splx(s); 1737} 1738 1739static int 1740mfi_create_sgl(struct mfi_ccb *ccb, int flags) 1741{ 1742 struct mfi_softc *sc = ccb->ccb_sc; 1743 struct mfi_frame_header *hdr; 1744 bus_dma_segment_t *sgd; 1745 union mfi_sgl *sgl; 1746 int error, i; 1747 1748 DNPRINTF(MFI_D_DMA, "%s: mfi_create_sgl %#lx\n", DEVNAME(sc), 1749 (u_long)ccb->ccb_data); 1750 1751 if (!ccb->ccb_data) 1752 return 1; 1753 1754 KASSERT(flags == BUS_DMA_NOWAIT || !cpu_intr_p()); 1755 error = bus_dmamap_load(sc->sc_datadmat, ccb->ccb_dmamap, 1756 ccb->ccb_data, ccb->ccb_len, NULL, flags); 1757 if (error) { 1758 if (error == EFBIG) { 1759 aprint_error_dev(sc->sc_dev, "more than %d dma segs\n", 1760 sc->sc_max_sgl); 1761 } else { 1762 aprint_error_dev(sc->sc_dev, 1763 "error %d loading dma map\n", error); 1764 } 1765 return 1; 1766 } 1767 1768 hdr = &ccb->ccb_frame->mfr_header; 1769 sgl = ccb->ccb_sgl; 1770 sgd = ccb->ccb_dmamap->dm_segs; 1771 for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) { 1772 if (sc->sc_ioptype == MFI_IOP_TBOLT && 1773 (hdr->mfh_cmd == MFI_CMD_PD_SCSI_IO || 1774 hdr->mfh_cmd == MFI_CMD_LD_READ || 1775 hdr->mfh_cmd == MFI_CMD_LD_WRITE)) { 1776 sgl->sg_ieee[i].addr = htole64(sgd[i].ds_addr); 1777 sgl->sg_ieee[i].len = htole32(sgd[i].ds_len); 1778 sgl->sg_ieee[i].flags = 0; 1779 DNPRINTF(MFI_D_DMA, "%s: addr: %#" PRIx64 " len: %#" 1780 PRIx32 "\n", 1781 DEVNAME(sc), sgl->sg64[i].addr, sgl->sg64[i].len); 1782 hdr->mfh_flags |= MFI_FRAME_IEEE_SGL | MFI_FRAME_SGL64; 1783 } else if (sc->sc_64bit_dma) { 1784 sgl->sg64[i].addr = htole64(sgd[i].ds_addr); 1785 sgl->sg64[i].len = htole32(sgd[i].ds_len); 1786 DNPRINTF(MFI_D_DMA, "%s: addr: %#" PRIx64 " len: %#" 1787 PRIx32 "\n", 1788 DEVNAME(sc), sgl->sg64[i].addr, sgl->sg64[i].len); 1789 hdr->mfh_flags |= MFI_FRAME_SGL64; 1790 } else { 1791 sgl->sg32[i].addr = htole32(sgd[i].ds_addr); 1792 sgl->sg32[i].len = htole32(sgd[i].ds_len); 1793 DNPRINTF(MFI_D_DMA, "%s: addr: %#x len: %#x\n", 1794 DEVNAME(sc), sgl->sg32[i].addr, sgl->sg32[i].len); 1795 hdr->mfh_flags |= MFI_FRAME_SGL32; 1796 } 1797 } 1798 1799 if (ccb->ccb_direction == MFI_DATA_IN) { 1800 hdr->mfh_flags |= MFI_FRAME_DIR_READ; 1801 bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0, 1802 ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); 1803 } else { 1804 hdr->mfh_flags |= MFI_FRAME_DIR_WRITE; 1805 bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0, 1806 ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); 1807 } 1808 1809 hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs; 1810 ccb->ccb_frame_size += sc->sc_sgl_size * ccb->ccb_dmamap->dm_nsegs; 1811 ccb->ccb_extra_frames = (ccb->ccb_frame_size - 1) / MFI_FRAME_SIZE; 1812 1813 DNPRINTF(MFI_D_DMA, "%s: sg_count: %d frame_size: %d frames_size: %d" 1814 " dm_nsegs: %d extra_frames: %d\n", 1815 DEVNAME(sc), 1816 hdr->mfh_sg_count, 1817 ccb->ccb_frame_size, 1818 sc->sc_frames_size, 1819 ccb->ccb_dmamap->dm_nsegs, 1820 ccb->ccb_extra_frames); 1821 1822 return 0; 1823} 1824 1825static int 1826mfi_mgmt_internal(struct mfi_softc *sc, uint32_t opc, uint32_t dir, 1827 uint32_t len, void *buf, uint8_t *mbox, bool poll) 1828{ 1829 struct mfi_ccb *ccb; 1830 int rv = 1; 1831 1832 if ((ccb = mfi_get_ccb(sc)) == NULL) 1833 return rv; 1834 rv = mfi_mgmt(ccb, NULL, opc, dir, len, buf, mbox); 1835 if (rv) 1836 return rv; 1837 1838 if (poll) { 1839 rv = 1; 1840 if (mfi_poll(ccb)) 1841 goto done; 1842 } else { 1843 mfi_post(sc, ccb); 1844 1845 DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt_internal sleeping\n", 1846 DEVNAME(sc)); 1847 while (ccb->ccb_state != MFI_CCB_DONE) 1848 tsleep(ccb, PRIBIO, "mfi_mgmt", 0); 1849 1850 if (ccb->ccb_flags & MFI_CCB_F_ERR) 1851 goto done; 1852 } 1853 rv = 0; 1854 1855done: 1856 mfi_put_ccb(ccb); 1857 return rv; 1858} 1859 1860static int 1861mfi_mgmt(struct mfi_ccb *ccb, struct scsipi_xfer *xs, 1862 uint32_t opc, uint32_t dir, uint32_t len, void *buf, uint8_t *mbox) 1863{ 1864 struct mfi_dcmd_frame *dcmd; 1865 1866 DNPRINTF(MFI_D_MISC, "%s: mfi_mgmt %#x\n", DEVNAME(ccb->ccb_sc), opc); 1867 1868 dcmd = &ccb->ccb_frame->mfr_dcmd; 1869 memset(dcmd->mdf_mbox, 0, MFI_MBOX_SIZE); 1870 dcmd->mdf_header.mfh_cmd = MFI_CMD_DCMD; 1871 dcmd->mdf_header.mfh_timeout = 0; 1872 1873 dcmd->mdf_opcode = opc; 1874 dcmd->mdf_header.mfh_data_len = 0; 1875 ccb->ccb_direction = dir; 1876 ccb->ccb_xs = xs; 1877 ccb->ccb_done = mfi_mgmt_done; 1878 1879 ccb->ccb_frame_size = MFI_DCMD_FRAME_SIZE; 1880 1881 /* handle special opcodes */ 1882 if (mbox) 1883 memcpy(dcmd->mdf_mbox, mbox, MFI_MBOX_SIZE); 1884 1885 if (dir != MFI_DATA_NONE) { 1886 dcmd->mdf_header.mfh_data_len = len; 1887 ccb->ccb_data = buf; 1888 ccb->ccb_len = len; 1889 ccb->ccb_sgl = &dcmd->mdf_sgl; 1890 1891 if (mfi_create_sgl(ccb, BUS_DMA_WAITOK)) 1892 return 1; 1893 } 1894 return 0; 1895} 1896 1897static void 1898mfi_mgmt_done(struct mfi_ccb *ccb) 1899{ 1900 struct scsipi_xfer *xs = ccb->ccb_xs; 1901 struct mfi_softc *sc = ccb->ccb_sc; 1902 struct mfi_frame_header *hdr = &ccb->ccb_frame->mfr_header; 1903 1904 DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done %#lx %#lx\n", 1905 DEVNAME(sc), (u_long)ccb, (u_long)ccb->ccb_frame); 1906 1907 if (ccb->ccb_data != NULL) { 1908 DNPRINTF(MFI_D_INTR, "%s: mfi_mgmt_done sync\n", 1909 DEVNAME(sc)); 1910 bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0, 1911 ccb->ccb_dmamap->dm_mapsize, 1912 (ccb->ccb_direction & MFI_DATA_IN) ? 1913 BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); 1914 1915 bus_dmamap_unload(sc->sc_datadmat, ccb->ccb_dmamap); 1916 } 1917 1918 if (hdr->mfh_cmd_status != MFI_STAT_OK) 1919 ccb->ccb_flags |= MFI_CCB_F_ERR; 1920 1921 ccb->ccb_state = MFI_CCB_DONE; 1922 if (xs) { 1923 if (hdr->mfh_cmd_status != MFI_STAT_OK) { 1924 xs->error = XS_DRIVER_STUFFUP; 1925 } else { 1926 xs->error = XS_NOERROR; 1927 xs->status = SCSI_OK; 1928 xs->resid = 0; 1929 } 1930 mfi_put_ccb(ccb); 1931 scsipi_done(xs); 1932 } else 1933 wakeup(ccb); 1934} 1935 1936#if NBIO > 0 1937int 1938mfi_ioctl(device_t dev, u_long cmd, void *addr) 1939{ 1940 struct mfi_softc *sc = device_private(dev); 1941 int error = 0; 1942 int s; 1943 1944 KERNEL_LOCK(1, curlwp); 1945 s = splbio(); 1946 1947 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl ", DEVNAME(sc)); 1948 1949 switch (cmd) { 1950 case BIOCINQ: 1951 DNPRINTF(MFI_D_IOCTL, "inq\n"); 1952 error = mfi_ioctl_inq(sc, (struct bioc_inq *)addr); 1953 break; 1954 1955 case BIOCVOL: 1956 DNPRINTF(MFI_D_IOCTL, "vol\n"); 1957 error = mfi_ioctl_vol(sc, (struct bioc_vol *)addr); 1958 break; 1959 1960 case BIOCDISK: 1961 DNPRINTF(MFI_D_IOCTL, "disk\n"); 1962 error = mfi_ioctl_disk(sc, (struct bioc_disk *)addr); 1963 break; 1964 1965 case BIOCALARM: 1966 DNPRINTF(MFI_D_IOCTL, "alarm\n"); 1967 error = mfi_ioctl_alarm(sc, (struct bioc_alarm *)addr); 1968 break; 1969 1970 case BIOCBLINK: 1971 DNPRINTF(MFI_D_IOCTL, "blink\n"); 1972 error = mfi_ioctl_blink(sc, (struct bioc_blink *)addr); 1973 break; 1974 1975 case BIOCSETSTATE: 1976 DNPRINTF(MFI_D_IOCTL, "setstate\n"); 1977 error = mfi_ioctl_setstate(sc, (struct bioc_setstate *)addr); 1978 break; 1979 1980 default: 1981 DNPRINTF(MFI_D_IOCTL, " invalid ioctl\n"); 1982 error = EINVAL; 1983 } 1984 splx(s); 1985 KERNEL_UNLOCK_ONE(curlwp); 1986 1987 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl return %x\n", DEVNAME(sc), error); 1988 return error; 1989} 1990 1991static int 1992mfi_ioctl_inq(struct mfi_softc *sc, struct bioc_inq *bi) 1993{ 1994 struct mfi_conf *cfg; 1995 int rv = EINVAL; 1996 1997 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_inq\n", DEVNAME(sc)); 1998 1999 if (mfi_get_info(sc)) { 2000 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_inq failed\n", 2001 DEVNAME(sc)); 2002 return EIO; 2003 } 2004 2005 /* get figures */ 2006 cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK); 2007 if (mfi_mgmt_internal(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, 2008 sizeof *cfg, cfg, NULL, false)) 2009 goto freeme; 2010 2011 strlcpy(bi->bi_dev, DEVNAME(sc), sizeof(bi->bi_dev)); 2012 bi->bi_novol = cfg->mfc_no_ld + cfg->mfc_no_hs; 2013 bi->bi_nodisk = sc->sc_info.mci_pd_disks_present; 2014 2015 rv = 0; 2016freeme: 2017 free(cfg, M_DEVBUF); 2018 return rv; 2019} 2020 2021static int 2022mfi_ioctl_vol(struct mfi_softc *sc, struct bioc_vol *bv) 2023{ 2024 int i, per, rv = EINVAL; 2025 uint8_t mbox[MFI_MBOX_SIZE]; 2026 2027 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol %#x\n", 2028 DEVNAME(sc), bv->bv_volid); 2029 2030 if (mfi_mgmt_internal(sc, MR_DCMD_LD_GET_LIST, MFI_DATA_IN, 2031 sizeof(sc->sc_ld_list), &sc->sc_ld_list, NULL, false)) 2032 goto done; 2033 2034 i = bv->bv_volid; 2035 mbox[0] = sc->sc_ld_list.mll_list[i].mll_ld.mld_target; 2036 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol target %#x\n", 2037 DEVNAME(sc), mbox[0]); 2038 2039 if (mfi_mgmt_internal(sc, MR_DCMD_LD_GET_INFO, MFI_DATA_IN, 2040 sizeof(sc->sc_ld_details), &sc->sc_ld_details, mbox, false)) 2041 goto done; 2042 2043 if (bv->bv_volid >= sc->sc_ld_list.mll_no_ld) { 2044 /* go do hotspares */ 2045 rv = mfi_bio_hs(sc, bv->bv_volid, MFI_MGMT_VD, bv); 2046 goto done; 2047 } 2048 2049 strlcpy(bv->bv_dev, sc->sc_ld[i].ld_dev, sizeof(bv->bv_dev)); 2050 2051 switch(sc->sc_ld_list.mll_list[i].mll_state) { 2052 case MFI_LD_OFFLINE: 2053 bv->bv_status = BIOC_SVOFFLINE; 2054 break; 2055 2056 case MFI_LD_PART_DEGRADED: 2057 case MFI_LD_DEGRADED: 2058 bv->bv_status = BIOC_SVDEGRADED; 2059 break; 2060 2061 case MFI_LD_ONLINE: 2062 bv->bv_status = BIOC_SVONLINE; 2063 break; 2064 2065 default: 2066 bv->bv_status = BIOC_SVINVALID; 2067 DNPRINTF(MFI_D_IOCTL, "%s: invalid logical disk state %#x\n", 2068 DEVNAME(sc), 2069 sc->sc_ld_list.mll_list[i].mll_state); 2070 } 2071 2072 /* additional status can modify MFI status */ 2073 switch (sc->sc_ld_details.mld_progress.mlp_in_prog) { 2074 case MFI_LD_PROG_CC: 2075 case MFI_LD_PROG_BGI: 2076 bv->bv_status = BIOC_SVSCRUB; 2077 per = (int)sc->sc_ld_details.mld_progress.mlp_cc.mp_progress; 2078 bv->bv_percent = (per * 100) / 0xffff; 2079 bv->bv_seconds = 2080 sc->sc_ld_details.mld_progress.mlp_cc.mp_elapsed_seconds; 2081 break; 2082 2083 case MFI_LD_PROG_FGI: 2084 case MFI_LD_PROG_RECONSTRUCT: 2085 /* nothing yet */ 2086 break; 2087 } 2088 2089 /* 2090 * The RAID levels are determined per the SNIA DDF spec, this is only 2091 * a subset that is valid for the MFI contrller. 2092 */ 2093 bv->bv_level = sc->sc_ld_details.mld_cfg.mlc_parm.mpa_pri_raid; 2094 if (sc->sc_ld_details.mld_cfg.mlc_parm.mpa_sec_raid == 2095 MFI_DDF_SRL_SPANNED) 2096 bv->bv_level *= 10; 2097 2098 bv->bv_nodisk = sc->sc_ld_details.mld_cfg.mlc_parm.mpa_no_drv_per_span * 2099 sc->sc_ld_details.mld_cfg.mlc_parm.mpa_span_depth; 2100 2101 bv->bv_size = sc->sc_ld_details.mld_size * 512; /* bytes per block */ 2102 2103 rv = 0; 2104done: 2105 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_vol done %x\n", 2106 DEVNAME(sc), rv); 2107 return rv; 2108} 2109 2110static int 2111mfi_ioctl_disk(struct mfi_softc *sc, struct bioc_disk *bd) 2112{ 2113 struct mfi_conf *cfg; 2114 struct mfi_array *ar; 2115 struct mfi_ld_cfg *ld; 2116 struct mfi_pd_details *pd; 2117 struct scsipi_inquiry_data *inqbuf; 2118 char vend[8+16+4+1]; 2119 int i, rv = EINVAL; 2120 int arr, vol, disk; 2121 uint32_t size; 2122 uint8_t mbox[MFI_MBOX_SIZE]; 2123 2124 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_disk %#x\n", 2125 DEVNAME(sc), bd->bd_diskid); 2126 2127 pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK | M_ZERO); 2128 2129 /* send single element command to retrieve size for full structure */ 2130 cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK); 2131 if (mfi_mgmt_internal(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, 2132 sizeof *cfg, cfg, NULL, false)) 2133 goto freeme; 2134 2135 size = cfg->mfc_size; 2136 free(cfg, M_DEVBUF); 2137 2138 /* memory for read config */ 2139 cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO); 2140 if (mfi_mgmt_internal(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, 2141 size, cfg, NULL, false)) 2142 goto freeme; 2143 2144 ar = cfg->mfc_array; 2145 2146 /* calculate offset to ld structure */ 2147 ld = (struct mfi_ld_cfg *)( 2148 ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) + 2149 cfg->mfc_array_size * cfg->mfc_no_array); 2150 2151 vol = bd->bd_volid; 2152 2153 if (vol >= cfg->mfc_no_ld) { 2154 /* do hotspares */ 2155 rv = mfi_bio_hs(sc, bd->bd_volid, MFI_MGMT_SD, bd); 2156 goto freeme; 2157 } 2158 2159 /* find corresponding array for ld */ 2160 for (i = 0, arr = 0; i < vol; i++) 2161 arr += ld[i].mlc_parm.mpa_span_depth; 2162 2163 /* offset disk into pd list */ 2164 disk = bd->bd_diskid % ld[vol].mlc_parm.mpa_no_drv_per_span; 2165 2166 /* offset array index into the next spans */ 2167 arr += bd->bd_diskid / ld[vol].mlc_parm.mpa_no_drv_per_span; 2168 2169 bd->bd_target = ar[arr].pd[disk].mar_enc_slot; 2170 switch (ar[arr].pd[disk].mar_pd_state){ 2171 case MFI_PD_UNCONFIG_GOOD: 2172 bd->bd_status = BIOC_SDUNUSED; 2173 break; 2174 2175 case MFI_PD_HOTSPARE: /* XXX dedicated hotspare part of array? */ 2176 bd->bd_status = BIOC_SDHOTSPARE; 2177 break; 2178 2179 case MFI_PD_OFFLINE: 2180 bd->bd_status = BIOC_SDOFFLINE; 2181 break; 2182 2183 case MFI_PD_FAILED: 2184 bd->bd_status = BIOC_SDFAILED; 2185 break; 2186 2187 case MFI_PD_REBUILD: 2188 bd->bd_status = BIOC_SDREBUILD; 2189 break; 2190 2191 case MFI_PD_ONLINE: 2192 bd->bd_status = BIOC_SDONLINE; 2193 break; 2194 2195 case MFI_PD_UNCONFIG_BAD: /* XXX define new state in bio */ 2196 default: 2197 bd->bd_status = BIOC_SDINVALID; 2198 break; 2199 2200 } 2201 2202 /* get the remaining fields */ 2203 *((uint16_t *)&mbox) = ar[arr].pd[disk].mar_pd.mfp_id; 2204 memset(pd, 0, sizeof(*pd)); 2205 if (mfi_mgmt_internal(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN, 2206 sizeof *pd, pd, mbox, false)) 2207 goto freeme; 2208 2209 bd->bd_size = pd->mpd_size * 512; /* bytes per block */ 2210 2211 /* if pd->mpd_enc_idx is 0 then it is not in an enclosure */ 2212 bd->bd_channel = pd->mpd_enc_idx; 2213 2214 inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data; 2215 memcpy(vend, inqbuf->vendor, sizeof vend - 1); 2216 vend[sizeof vend - 1] = '\0'; 2217 strlcpy(bd->bd_vendor, vend, sizeof(bd->bd_vendor)); 2218 2219 /* XXX find a way to retrieve serial nr from drive */ 2220 /* XXX find a way to get bd_procdev */ 2221 2222 rv = 0; 2223freeme: 2224 free(pd, M_DEVBUF); 2225 free(cfg, M_DEVBUF); 2226 2227 return rv; 2228} 2229 2230static int 2231mfi_ioctl_alarm(struct mfi_softc *sc, struct bioc_alarm *ba) 2232{ 2233 uint32_t opc, dir = MFI_DATA_NONE; 2234 int rv = 0; 2235 int8_t ret; 2236 2237 switch(ba->ba_opcode) { 2238 case BIOC_SADISABLE: 2239 opc = MR_DCMD_SPEAKER_DISABLE; 2240 break; 2241 2242 case BIOC_SAENABLE: 2243 opc = MR_DCMD_SPEAKER_ENABLE; 2244 break; 2245 2246 case BIOC_SASILENCE: 2247 opc = MR_DCMD_SPEAKER_SILENCE; 2248 break; 2249 2250 case BIOC_GASTATUS: 2251 opc = MR_DCMD_SPEAKER_GET; 2252 dir = MFI_DATA_IN; 2253 break; 2254 2255 case BIOC_SATEST: 2256 opc = MR_DCMD_SPEAKER_TEST; 2257 break; 2258 2259 default: 2260 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_alarm biocalarm invalid " 2261 "opcode %x\n", DEVNAME(sc), ba->ba_opcode); 2262 return EINVAL; 2263 } 2264 2265 if (mfi_mgmt_internal(sc, opc, dir, sizeof(ret), &ret, NULL, false)) 2266 rv = EINVAL; 2267 else 2268 if (ba->ba_opcode == BIOC_GASTATUS) 2269 ba->ba_status = ret; 2270 else 2271 ba->ba_status = 0; 2272 2273 return rv; 2274} 2275 2276static int 2277mfi_ioctl_blink(struct mfi_softc *sc, struct bioc_blink *bb) 2278{ 2279 int i, found, rv = EINVAL; 2280 uint8_t mbox[MFI_MBOX_SIZE]; 2281 uint32_t cmd; 2282 struct mfi_pd_list *pd; 2283 2284 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink %x\n", DEVNAME(sc), 2285 bb->bb_status); 2286 2287 /* channel 0 means not in an enclosure so can't be blinked */ 2288 if (bb->bb_channel == 0) 2289 return EINVAL; 2290 2291 pd = malloc(MFI_PD_LIST_SIZE, M_DEVBUF, M_WAITOK); 2292 2293 if (mfi_mgmt_internal(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN, 2294 MFI_PD_LIST_SIZE, pd, NULL, false)) 2295 goto done; 2296 2297 for (i = 0, found = 0; i < pd->mpl_no_pd; i++) 2298 if (bb->bb_channel == pd->mpl_address[i].mpa_enc_index && 2299 bb->bb_target == pd->mpl_address[i].mpa_enc_slot) { 2300 found = 1; 2301 break; 2302 } 2303 2304 if (!found) 2305 goto done; 2306 2307 memset(mbox, 0, sizeof mbox); 2308 2309 *((uint16_t *)&mbox) = pd->mpl_address[i].mpa_pd_id; 2310 2311 switch (bb->bb_status) { 2312 case BIOC_SBUNBLINK: 2313 cmd = MR_DCMD_PD_UNBLINK; 2314 break; 2315 2316 case BIOC_SBBLINK: 2317 cmd = MR_DCMD_PD_BLINK; 2318 break; 2319 2320 case BIOC_SBALARM: 2321 default: 2322 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_blink biocblink invalid " 2323 "opcode %x\n", DEVNAME(sc), bb->bb_status); 2324 goto done; 2325 } 2326 2327 2328 if (mfi_mgmt_internal(sc, cmd, MFI_DATA_NONE, 0, NULL, mbox, false)) 2329 goto done; 2330 2331 rv = 0; 2332done: 2333 free(pd, M_DEVBUF); 2334 return rv; 2335} 2336 2337static int 2338mfi_ioctl_setstate(struct mfi_softc *sc, struct bioc_setstate *bs) 2339{ 2340 struct mfi_pd_list *pd; 2341 int i, found, rv = EINVAL; 2342 uint8_t mbox[MFI_MBOX_SIZE]; 2343 uint32_t cmd; 2344 2345 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate %x\n", DEVNAME(sc), 2346 bs->bs_status); 2347 2348 pd = malloc(MFI_PD_LIST_SIZE, M_DEVBUF, M_WAITOK); 2349 2350 if (mfi_mgmt_internal(sc, MR_DCMD_PD_GET_LIST, MFI_DATA_IN, 2351 MFI_PD_LIST_SIZE, pd, NULL, false)) 2352 goto done; 2353 2354 for (i = 0, found = 0; i < pd->mpl_no_pd; i++) 2355 if (bs->bs_channel == pd->mpl_address[i].mpa_enc_index && 2356 bs->bs_target == pd->mpl_address[i].mpa_enc_slot) { 2357 found = 1; 2358 break; 2359 } 2360 2361 if (!found) 2362 goto done; 2363 2364 memset(mbox, 0, sizeof mbox); 2365 2366 *((uint16_t *)&mbox) = pd->mpl_address[i].mpa_pd_id; 2367 2368 switch (bs->bs_status) { 2369 case BIOC_SSONLINE: 2370 mbox[2] = MFI_PD_ONLINE; 2371 cmd = MD_DCMD_PD_SET_STATE; 2372 break; 2373 2374 case BIOC_SSOFFLINE: 2375 mbox[2] = MFI_PD_OFFLINE; 2376 cmd = MD_DCMD_PD_SET_STATE; 2377 break; 2378 2379 case BIOC_SSHOTSPARE: 2380 mbox[2] = MFI_PD_HOTSPARE; 2381 cmd = MD_DCMD_PD_SET_STATE; 2382 break; 2383/* 2384 case BIOC_SSREBUILD: 2385 cmd = MD_DCMD_PD_REBUILD; 2386 break; 2387*/ 2388 default: 2389 DNPRINTF(MFI_D_IOCTL, "%s: mfi_ioctl_setstate invalid " 2390 "opcode %x\n", DEVNAME(sc), bs->bs_status); 2391 goto done; 2392 } 2393 2394 2395 if (mfi_mgmt_internal(sc, MD_DCMD_PD_SET_STATE, MFI_DATA_NONE, 2396 0, NULL, mbox, false)) 2397 goto done; 2398 2399 rv = 0; 2400done: 2401 free(pd, M_DEVBUF); 2402 return rv; 2403} 2404 2405static int 2406mfi_bio_hs(struct mfi_softc *sc, int volid, int type, void *bio_hs) 2407{ 2408 struct mfi_conf *cfg; 2409 struct mfi_hotspare *hs; 2410 struct mfi_pd_details *pd; 2411 struct bioc_disk *sdhs; 2412 struct bioc_vol *vdhs; 2413 struct scsipi_inquiry_data *inqbuf; 2414 char vend[8+16+4+1]; 2415 int i, rv = EINVAL; 2416 uint32_t size; 2417 uint8_t mbox[MFI_MBOX_SIZE]; 2418 2419 DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs %d\n", DEVNAME(sc), volid); 2420 2421 if (!bio_hs) 2422 return EINVAL; 2423 2424 pd = malloc(sizeof *pd, M_DEVBUF, M_WAITOK | M_ZERO); 2425 2426 /* send single element command to retrieve size for full structure */ 2427 cfg = malloc(sizeof *cfg, M_DEVBUF, M_WAITOK); 2428 if (mfi_mgmt_internal(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, 2429 sizeof *cfg, cfg, NULL, false)) 2430 goto freeme; 2431 2432 size = cfg->mfc_size; 2433 free(cfg, M_DEVBUF); 2434 2435 /* memory for read config */ 2436 cfg = malloc(size, M_DEVBUF, M_WAITOK|M_ZERO); 2437 if (mfi_mgmt_internal(sc, MD_DCMD_CONF_GET, MFI_DATA_IN, 2438 size, cfg, NULL, false)) 2439 goto freeme; 2440 2441 /* calculate offset to hs structure */ 2442 hs = (struct mfi_hotspare *)( 2443 ((uint8_t *)cfg) + offsetof(struct mfi_conf, mfc_array) + 2444 cfg->mfc_array_size * cfg->mfc_no_array + 2445 cfg->mfc_ld_size * cfg->mfc_no_ld); 2446 2447 if (volid < cfg->mfc_no_ld) 2448 goto freeme; /* not a hotspare */ 2449 2450 if (volid > (cfg->mfc_no_ld + cfg->mfc_no_hs)) 2451 goto freeme; /* not a hotspare */ 2452 2453 /* offset into hotspare structure */ 2454 i = volid - cfg->mfc_no_ld; 2455 2456 DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs i %d volid %d no_ld %d no_hs %d " 2457 "hs %p cfg %p id %02x\n", DEVNAME(sc), i, volid, cfg->mfc_no_ld, 2458 cfg->mfc_no_hs, hs, cfg, hs[i].mhs_pd.mfp_id); 2459 2460 /* get pd fields */ 2461 memset(mbox, 0, sizeof mbox); 2462 *((uint16_t *)&mbox) = hs[i].mhs_pd.mfp_id; 2463 if (mfi_mgmt_internal(sc, MR_DCMD_PD_GET_INFO, MFI_DATA_IN, 2464 sizeof *pd, pd, mbox, false)) { 2465 DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs illegal PD\n", 2466 DEVNAME(sc)); 2467 goto freeme; 2468 } 2469 2470 switch (type) { 2471 case MFI_MGMT_VD: 2472 vdhs = bio_hs; 2473 vdhs->bv_status = BIOC_SVONLINE; 2474 vdhs->bv_size = pd->mpd_size * 512; /* bytes per block */ 2475 vdhs->bv_level = -1; /* hotspare */ 2476 vdhs->bv_nodisk = 1; 2477 break; 2478 2479 case MFI_MGMT_SD: 2480 sdhs = bio_hs; 2481 sdhs->bd_status = BIOC_SDHOTSPARE; 2482 sdhs->bd_size = pd->mpd_size * 512; /* bytes per block */ 2483 sdhs->bd_channel = pd->mpd_enc_idx; 2484 sdhs->bd_target = pd->mpd_enc_slot; 2485 inqbuf = (struct scsipi_inquiry_data *)&pd->mpd_inq_data; 2486 memcpy(vend, inqbuf->vendor, sizeof(vend) - 1); 2487 vend[sizeof vend - 1] = '\0'; 2488 strlcpy(sdhs->bd_vendor, vend, sizeof(sdhs->bd_vendor)); 2489 break; 2490 2491 default: 2492 goto freeme; 2493 } 2494 2495 DNPRINTF(MFI_D_IOCTL, "%s: mfi_vol_hs 6\n", DEVNAME(sc)); 2496 rv = 0; 2497freeme: 2498 free(pd, M_DEVBUF); 2499 free(cfg, M_DEVBUF); 2500 2501 return rv; 2502} 2503 2504static int 2505mfi_destroy_sensors(struct mfi_softc *sc) 2506{ 2507 if (sc->sc_sme == NULL) 2508 return 0; 2509 sysmon_envsys_unregister(sc->sc_sme); 2510 sc->sc_sme = NULL; 2511 free(sc->sc_sensor, M_DEVBUF); 2512 return 0; 2513} 2514 2515static int 2516mfi_create_sensors(struct mfi_softc *sc) 2517{ 2518 int i; 2519 int nsensors = sc->sc_ld_cnt + 1; 2520 int rv; 2521 2522 sc->sc_sme = sysmon_envsys_create(); 2523 sc->sc_sensor = malloc(sizeof(envsys_data_t) * nsensors, 2524 M_DEVBUF, M_NOWAIT | M_ZERO); 2525 if (sc->sc_sensor == NULL) { 2526 aprint_error_dev(sc->sc_dev, "can't allocate envsys_data_t\n"); 2527 return ENOMEM; 2528 } 2529 2530 /* BBU */ 2531 sc->sc_sensor[0].units = ENVSYS_INDICATOR; 2532 sc->sc_sensor[0].state = ENVSYS_SINVALID; 2533 sc->sc_sensor[0].value_cur = 0; 2534 /* Enable monitoring for BBU state changes, if present */ 2535 if (sc->sc_info.mci_hw_present & MFI_INFO_HW_BBU) 2536 sc->sc_sensor[0].flags |= ENVSYS_FMONCRITICAL; 2537 snprintf(sc->sc_sensor[0].desc, 2538 sizeof(sc->sc_sensor[0].desc), "%s BBU", DEVNAME(sc)); 2539 if (sysmon_envsys_sensor_attach(sc->sc_sme, &sc->sc_sensor[0])) 2540 goto out; 2541 2542 for (i = 1; i < nsensors; i++) { 2543 sc->sc_sensor[i].units = ENVSYS_DRIVE; 2544 sc->sc_sensor[i].state = ENVSYS_SINVALID; 2545 sc->sc_sensor[i].value_cur = ENVSYS_DRIVE_EMPTY; 2546 /* Enable monitoring for drive state changes */ 2547 sc->sc_sensor[i].flags |= ENVSYS_FMONSTCHANGED; 2548 /* logical drives */ 2549 snprintf(sc->sc_sensor[i].desc, 2550 sizeof(sc->sc_sensor[i].desc), "%s:%d", 2551 DEVNAME(sc), i - 1); 2552 if (sysmon_envsys_sensor_attach(sc->sc_sme, 2553 &sc->sc_sensor[i])) 2554 goto out; 2555 } 2556 2557 sc->sc_sme->sme_name = DEVNAME(sc); 2558 sc->sc_sme->sme_cookie = sc; 2559 sc->sc_sme->sme_refresh = mfi_sensor_refresh; 2560 rv = sysmon_envsys_register(sc->sc_sme); 2561 if (rv != 0) { 2562 aprint_error_dev(sc->sc_dev, 2563 "unable to register with sysmon (rv = %d)\n", rv); 2564 goto out; 2565 } 2566 return 0; 2567 2568out: 2569 free(sc->sc_sensor, M_DEVBUF); 2570 sysmon_envsys_destroy(sc->sc_sme); 2571 sc->sc_sme = NULL; 2572 return EINVAL; 2573} 2574 2575static void 2576mfi_sensor_refresh(struct sysmon_envsys *sme, envsys_data_t *edata) 2577{ 2578 struct mfi_softc *sc = sme->sme_cookie; 2579 struct bioc_vol bv; 2580 int s; 2581 int error; 2582 2583 if (edata->sensor >= sc->sc_ld_cnt + 1) 2584 return; 2585 2586 if (edata->sensor == 0) { 2587 /* BBU */ 2588 struct mfi_bbu_status bbu_stat; 2589 int bbu_status; 2590 if ((sc->sc_info.mci_hw_present & MFI_INFO_HW_BBU) == 0) 2591 return; 2592 2593 KERNEL_LOCK(1, curlwp); 2594 s = splbio(); 2595 bbu_status = mfi_get_bbu(sc, &bbu_stat); 2596 splx(s); 2597 KERNEL_UNLOCK_ONE(curlwp); 2598 switch(bbu_status) { 2599 case MFI_BBU_GOOD: 2600 edata->value_cur = 1; 2601 edata->state = ENVSYS_SVALID; 2602 if (!sc->sc_bbuok) 2603 aprint_normal_dev(sc->sc_dev, 2604 "BBU state changed to good\n"); 2605 sc->sc_bbuok = true; 2606 break; 2607 case MFI_BBU_BAD: 2608 edata->value_cur = 0; 2609 edata->state = ENVSYS_SCRITICAL; 2610 if (sc->sc_bbuok) 2611 aprint_normal_dev(sc->sc_dev, 2612 "BBU state changed to bad\n"); 2613 sc->sc_bbuok = false; 2614 break; 2615 case MFI_BBU_UNKNOWN: 2616 default: 2617 edata->value_cur = 0; 2618 edata->state = ENVSYS_SINVALID; 2619 sc->sc_bbuok = false; 2620 break; 2621 } 2622 return; 2623 } 2624 2625 memset(&bv, 0, sizeof(bv)); 2626 bv.bv_volid = edata->sensor - 1; 2627 KERNEL_LOCK(1, curlwp); 2628 s = splbio(); 2629 error = mfi_ioctl_vol(sc, &bv); 2630 splx(s); 2631 KERNEL_UNLOCK_ONE(curlwp); 2632 if (error) 2633 return; 2634 2635 switch(bv.bv_status) { 2636 case BIOC_SVOFFLINE: 2637 edata->value_cur = ENVSYS_DRIVE_FAIL; 2638 edata->state = ENVSYS_SCRITICAL; 2639 break; 2640 2641 case BIOC_SVDEGRADED: 2642 edata->value_cur = ENVSYS_DRIVE_PFAIL; 2643 edata->state = ENVSYS_SCRITICAL; 2644 break; 2645 2646 case BIOC_SVSCRUB: 2647 case BIOC_SVONLINE: 2648 edata->value_cur = ENVSYS_DRIVE_ONLINE; 2649 edata->state = ENVSYS_SVALID; 2650 break; 2651 2652 case BIOC_SVINVALID: 2653 /* FALLTRHOUGH */ 2654 default: 2655 edata->value_cur = 0; /* unknown */ 2656 edata->state = ENVSYS_SINVALID; 2657 } 2658} 2659 2660#endif /* NBIO > 0 */ 2661 2662static uint32_t 2663mfi_xscale_fw_state(struct mfi_softc *sc) 2664{ 2665 return mfi_read(sc, MFI_OMSG0); 2666} 2667 2668static void 2669mfi_xscale_intr_dis(struct mfi_softc *sc) 2670{ 2671 mfi_write(sc, MFI_OMSK, 0); 2672} 2673 2674static void 2675mfi_xscale_intr_ena(struct mfi_softc *sc) 2676{ 2677 mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR); 2678} 2679 2680static int 2681mfi_xscale_intr(struct mfi_softc *sc) 2682{ 2683 uint32_t status; 2684 2685 status = mfi_read(sc, MFI_OSTS); 2686 if (!ISSET(status, MFI_OSTS_INTR_VALID)) 2687 return 0; 2688 2689 /* write status back to acknowledge interrupt */ 2690 mfi_write(sc, MFI_OSTS, status); 2691 return 1; 2692} 2693 2694static void 2695mfi_xscale_post(struct mfi_softc *sc, struct mfi_ccb *ccb) 2696{ 2697 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_frames), 2698 ccb->ccb_pframe - MFIMEM_DVA(sc->sc_frames), 2699 sc->sc_frames_size, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2700 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_sense), 2701 ccb->ccb_psense - MFIMEM_DVA(sc->sc_sense), 2702 MFI_SENSE_SIZE, BUS_DMASYNC_PREREAD); 2703 2704 mfi_write(sc, MFI_IQP, (ccb->ccb_pframe >> 3) | 2705 ccb->ccb_extra_frames); 2706 ccb->ccb_state = MFI_CCB_RUNNING; 2707} 2708 2709static uint32_t 2710mfi_ppc_fw_state(struct mfi_softc *sc) 2711{ 2712 return mfi_read(sc, MFI_OSP); 2713} 2714 2715static void 2716mfi_ppc_intr_dis(struct mfi_softc *sc) 2717{ 2718 /* Taking a wild guess --dyoung */ 2719 mfi_write(sc, MFI_OMSK, ~(uint32_t)0x0); 2720 mfi_write(sc, MFI_ODC, 0xffffffff); 2721} 2722 2723static void 2724mfi_ppc_intr_ena(struct mfi_softc *sc) 2725{ 2726 mfi_write(sc, MFI_ODC, 0xffffffff); 2727 mfi_write(sc, MFI_OMSK, ~0x80000004); 2728} 2729 2730static int 2731mfi_ppc_intr(struct mfi_softc *sc) 2732{ 2733 uint32_t status; 2734 2735 status = mfi_read(sc, MFI_OSTS); 2736 if (!ISSET(status, MFI_OSTS_PPC_INTR_VALID)) 2737 return 0; 2738 2739 /* write status back to acknowledge interrupt */ 2740 mfi_write(sc, MFI_ODC, status); 2741 return 1; 2742} 2743 2744static void 2745mfi_ppc_post(struct mfi_softc *sc, struct mfi_ccb *ccb) 2746{ 2747 mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe | 2748 (ccb->ccb_extra_frames << 1)); 2749 ccb->ccb_state = MFI_CCB_RUNNING; 2750} 2751 2752u_int32_t 2753mfi_gen2_fw_state(struct mfi_softc *sc) 2754{ 2755 return (mfi_read(sc, MFI_OSP)); 2756} 2757 2758void 2759mfi_gen2_intr_dis(struct mfi_softc *sc) 2760{ 2761 mfi_write(sc, MFI_OMSK, 0xffffffff); 2762 mfi_write(sc, MFI_ODC, 0xffffffff); 2763} 2764 2765void 2766mfi_gen2_intr_ena(struct mfi_softc *sc) 2767{ 2768 mfi_write(sc, MFI_ODC, 0xffffffff); 2769 mfi_write(sc, MFI_OMSK, ~MFI_OSTS_GEN2_INTR_VALID); 2770} 2771 2772int 2773mfi_gen2_intr(struct mfi_softc *sc) 2774{ 2775 u_int32_t status; 2776 2777 status = mfi_read(sc, MFI_OSTS); 2778 if (!ISSET(status, MFI_OSTS_GEN2_INTR_VALID)) 2779 return (0); 2780 2781 /* write status back to acknowledge interrupt */ 2782 mfi_write(sc, MFI_ODC, status); 2783 2784 return (1); 2785} 2786 2787void 2788mfi_gen2_post(struct mfi_softc *sc, struct mfi_ccb *ccb) 2789{ 2790 mfi_write(sc, MFI_IQP, 0x1 | ccb->ccb_pframe | 2791 (ccb->ccb_extra_frames << 1)); 2792 ccb->ccb_state = MFI_CCB_RUNNING; 2793} 2794 2795u_int32_t 2796mfi_skinny_fw_state(struct mfi_softc *sc) 2797{ 2798 return (mfi_read(sc, MFI_OSP)); 2799} 2800 2801void 2802mfi_skinny_intr_dis(struct mfi_softc *sc) 2803{ 2804 mfi_write(sc, MFI_OMSK, 0); 2805} 2806 2807void 2808mfi_skinny_intr_ena(struct mfi_softc *sc) 2809{ 2810 mfi_write(sc, MFI_OMSK, ~0x00000001); 2811} 2812 2813int 2814mfi_skinny_intr(struct mfi_softc *sc) 2815{ 2816 u_int32_t status; 2817 2818 status = mfi_read(sc, MFI_OSTS); 2819 if (!ISSET(status, MFI_OSTS_SKINNY_INTR_VALID)) 2820 return (0); 2821 2822 /* write status back to acknowledge interrupt */ 2823 mfi_write(sc, MFI_OSTS, status); 2824 2825 return (1); 2826} 2827 2828void 2829mfi_skinny_post(struct mfi_softc *sc, struct mfi_ccb *ccb) 2830{ 2831 mfi_write(sc, MFI_IQPL, 0x1 | ccb->ccb_pframe | 2832 (ccb->ccb_extra_frames << 1)); 2833 mfi_write(sc, MFI_IQPH, 0x00000000); 2834 ccb->ccb_state = MFI_CCB_RUNNING; 2835} 2836 2837#define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000008) 2838 2839void 2840mfi_tbolt_intr_ena(struct mfi_softc *sc) 2841{ 2842 mfi_write(sc, MFI_OMSK, ~MFI_FUSION_ENABLE_INTERRUPT_MASK); 2843 mfi_read(sc, MFI_OMSK); 2844} 2845 2846void 2847mfi_tbolt_intr_dis(struct mfi_softc *sc) 2848{ 2849 mfi_write(sc, MFI_OMSK, 0xFFFFFFFF); 2850 mfi_read(sc, MFI_OMSK); 2851} 2852 2853int 2854mfi_tbolt_intr(struct mfi_softc *sc) 2855{ 2856 int32_t status; 2857 2858 status = mfi_read(sc, MFI_OSTS); 2859 2860 if (ISSET(status, 0x1)) { 2861 mfi_write(sc, MFI_OSTS, status); 2862 mfi_read(sc, MFI_OSTS); 2863 if (ISSET(status, MFI_STATE_CHANGE_INTERRUPT)) 2864 return 0; 2865 return 1; 2866 } 2867 if (!ISSET(status, MFI_FUSION_ENABLE_INTERRUPT_MASK)) 2868 return 0; 2869 mfi_read(sc, MFI_OSTS); 2870 return 1; 2871} 2872 2873u_int32_t 2874mfi_tbolt_fw_state(struct mfi_softc *sc) 2875{ 2876 return mfi_read(sc, MFI_OSP); 2877} 2878 2879void 2880mfi_tbolt_post(struct mfi_softc *sc, struct mfi_ccb *ccb) 2881{ 2882 if (sc->sc_MFA_enabled) { 2883 if ((ccb->ccb_flags & MFI_CCB_F_TBOLT) == 0) 2884 mfi_tbolt_build_mpt_ccb(ccb); 2885 mfi_write(sc, MFI_IQPL, 2886 ccb->ccb_tb_request_desc.words & 0xFFFFFFFF); 2887 mfi_write(sc, MFI_IQPH, 2888 ccb->ccb_tb_request_desc.words >> 32); 2889 ccb->ccb_state = MFI_CCB_RUNNING; 2890 return; 2891 } 2892 uint64_t bus_add = ccb->ccb_pframe; 2893 bus_add |= (MFI_REQ_DESCRIPT_FLAGS_MFA 2894 << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 2895 mfi_write(sc, MFI_IQPL, bus_add); 2896 mfi_write(sc, MFI_IQPH, bus_add >> 32); 2897 ccb->ccb_state = MFI_CCB_RUNNING; 2898} 2899 2900static void 2901mfi_tbolt_build_mpt_ccb(struct mfi_ccb *ccb) 2902{ 2903 union mfi_mpi2_request_descriptor *req_desc = &ccb->ccb_tb_request_desc; 2904 struct mfi_mpi2_request_raid_scsi_io *io_req = ccb->ccb_tb_io_request; 2905 struct mpi25_ieee_sge_chain64 *mpi25_ieee_chain; 2906 2907 io_req->Function = MPI2_FUNCTION_PASSTHRU_IO_REQUEST; 2908 io_req->SGLOffset0 = 2909 offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL) / 4; 2910 io_req->ChainOffset = 2911 offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL) / 16; 2912 2913 mpi25_ieee_chain = 2914 (struct mpi25_ieee_sge_chain64 *)&io_req->SGL.IeeeChain; 2915 mpi25_ieee_chain->Address = ccb->ccb_pframe; 2916 2917 /* 2918 In MFI pass thru, nextChainOffset will always be zero to 2919 indicate the end of the chain. 2920 */ 2921 mpi25_ieee_chain->Flags= MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT 2922 | MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR; 2923 2924 /* setting the length to the maximum length */ 2925 mpi25_ieee_chain->Length = 1024; 2926 2927 req_desc->header.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << 2928 MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 2929 ccb->ccb_flags |= MFI_CCB_F_TBOLT; 2930 bus_dmamap_sync(ccb->ccb_sc->sc_dmat, 2931 MFIMEM_MAP(ccb->ccb_sc->sc_tbolt_reqmsgpool), 2932 ccb->ccb_tb_pio_request - 2933 MFIMEM_DVA(ccb->ccb_sc->sc_tbolt_reqmsgpool), 2934 MEGASAS_THUNDERBOLT_NEW_MSG_SIZE, 2935 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2936} 2937 2938/* 2939 * Description: 2940 * This function will prepare message pools for the Thunderbolt controller 2941 */ 2942static int 2943mfi_tbolt_init_desc_pool(struct mfi_softc *sc) 2944{ 2945 uint32_t offset = 0; 2946 uint8_t *addr = MFIMEM_KVA(sc->sc_tbolt_reqmsgpool); 2947 2948 /* Request Decriptors alignement restrictions */ 2949 KASSERT(((uintptr_t)addr & 0xFF) == 0); 2950 2951 /* Skip request message pool */ 2952 addr = &addr[MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * (sc->sc_max_cmds + 1)]; 2953 2954 /* Reply Frame Pool is initialized */ 2955 sc->sc_reply_frame_pool = (struct mfi_mpi2_reply_header *) addr; 2956 KASSERT(((uintptr_t)addr & 0xFF) == 0); 2957 2958 offset = (uintptr_t)sc->sc_reply_frame_pool 2959 - (uintptr_t)MFIMEM_KVA(sc->sc_tbolt_reqmsgpool); 2960 sc->sc_reply_frame_busaddr = 2961 MFIMEM_DVA(sc->sc_tbolt_reqmsgpool) + offset; 2962 2963 /* initializing reply address to 0xFFFFFFFF */ 2964 memset((uint8_t *)sc->sc_reply_frame_pool, 0xFF, 2965 (MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size)); 2966 2967 /* Skip Reply Frame Pool */ 2968 addr += MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size; 2969 sc->sc_reply_pool_limit = (void *)addr; 2970 2971 offset = MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size; 2972 sc->sc_sg_frame_busaddr = sc->sc_reply_frame_busaddr + offset; 2973 2974 /* initialize the last_reply_idx to 0 */ 2975 sc->sc_last_reply_idx = 0; 2976 offset = (sc->sc_sg_frame_busaddr + (MEGASAS_MAX_SZ_CHAIN_FRAME * 2977 sc->sc_max_cmds)) - MFIMEM_DVA(sc->sc_tbolt_reqmsgpool); 2978 KASSERT(offset <= sc->sc_tbolt_reqmsgpool->am_size); 2979 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_reqmsgpool), 0, 2980 MFIMEM_MAP(sc->sc_tbolt_reqmsgpool)->dm_mapsize, 2981 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 2982 return 0; 2983} 2984 2985/* 2986 * This routine prepare and issue INIT2 frame to the Firmware 2987 */ 2988 2989static int 2990mfi_tbolt_init_MFI_queue(struct mfi_softc *sc) 2991{ 2992 struct mpi2_ioc_init_request *mpi2IocInit; 2993 struct mfi_init_frame *mfi_init; 2994 struct mfi_ccb *ccb; 2995 bus_addr_t phyAddress; 2996 mfi_address *mfiAddressTemp; 2997 int s; 2998 char *verbuf; 2999 char wqbuf[10]; 3000 3001 /* Check if initialization is already completed */ 3002 if (sc->sc_MFA_enabled) { 3003 return 1; 3004 } 3005 3006 mpi2IocInit = 3007 (struct mpi2_ioc_init_request *)MFIMEM_KVA(sc->sc_tbolt_ioc_init); 3008 3009 s = splbio(); 3010 if ((ccb = mfi_get_ccb(sc)) == NULL) { 3011 splx(s); 3012 return (EBUSY); 3013 } 3014 3015 3016 mfi_init = &ccb->ccb_frame->mfr_init; 3017 3018 memset(mpi2IocInit, 0, sizeof(struct mpi2_ioc_init_request)); 3019 mpi2IocInit->Function = MPI2_FUNCTION_IOC_INIT; 3020 mpi2IocInit->WhoInit = MPI2_WHOINIT_HOST_DRIVER; 3021 3022 /* set MsgVersion and HeaderVersion host driver was built with */ 3023 mpi2IocInit->MsgVersion = MPI2_VERSION; 3024 mpi2IocInit->HeaderVersion = MPI2_HEADER_VERSION; 3025 mpi2IocInit->SystemRequestFrameSize = MEGASAS_THUNDERBOLT_NEW_MSG_SIZE/4; 3026 mpi2IocInit->ReplyDescriptorPostQueueDepth = 3027 (uint16_t)sc->sc_reply_pool_size; 3028 mpi2IocInit->ReplyFreeQueueDepth = 0; /* Not supported by MR. */ 3029 3030 /* Get physical address of reply frame pool */ 3031 phyAddress = sc->sc_reply_frame_busaddr; 3032 mfiAddressTemp = 3033 (mfi_address *)&mpi2IocInit->ReplyDescriptorPostQueueAddress; 3034 mfiAddressTemp->u.addressLow = (uint32_t)phyAddress; 3035 mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32); 3036 3037 /* Get physical address of request message pool */ 3038 phyAddress = MFIMEM_DVA(sc->sc_tbolt_reqmsgpool); 3039 mfiAddressTemp = (mfi_address *)&mpi2IocInit->SystemRequestFrameBaseAddress; 3040 mfiAddressTemp->u.addressLow = (uint32_t)phyAddress; 3041 mfiAddressTemp->u.addressHigh = (uint32_t)((uint64_t)phyAddress >> 32); 3042 3043 mpi2IocInit->ReplyFreeQueueAddress = 0; /* Not supported by MR. */ 3044 mpi2IocInit->TimeStamp = time_uptime; 3045 3046 verbuf = MFIMEM_KVA(sc->sc_tbolt_verbuf); 3047 snprintf(verbuf, strlen(MEGASAS_VERSION) + 2, "%s\n", 3048 MEGASAS_VERSION); 3049 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_verbuf), 0, 3050 MFIMEM_MAP(sc->sc_tbolt_verbuf)->dm_mapsize, BUS_DMASYNC_PREWRITE); 3051 mfi_init->driver_ver_lo = htole32(MFIMEM_DVA(sc->sc_tbolt_verbuf)); 3052 mfi_init->driver_ver_hi = 3053 htole32((uint64_t)MFIMEM_DVA(sc->sc_tbolt_verbuf) >> 32); 3054 3055 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_ioc_init), 0, 3056 MFIMEM_MAP(sc->sc_tbolt_ioc_init)->dm_mapsize, 3057 BUS_DMASYNC_PREWRITE); 3058 /* Get the physical address of the mpi2 ioc init command */ 3059 phyAddress = MFIMEM_DVA(sc->sc_tbolt_ioc_init); 3060 mfi_init->mif_qinfo_new_addr_lo = htole32(phyAddress); 3061 mfi_init->mif_qinfo_new_addr_hi = htole32((uint64_t)phyAddress >> 32); 3062 3063 mfi_init->mif_header.mfh_cmd = MFI_CMD_INIT; 3064 mfi_init->mif_header.mfh_data_len = sizeof(struct mpi2_ioc_init_request); 3065 if (mfi_poll(ccb) != 0) { 3066 aprint_error_dev(sc->sc_dev, "failed to send IOC init2 " 3067 "command at 0x%" PRIx64 "\n", 3068 (uint64_t)ccb->ccb_pframe); 3069 splx(s); 3070 return 1; 3071 } 3072 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_verbuf), 0, 3073 MFIMEM_MAP(sc->sc_tbolt_verbuf)->dm_mapsize, BUS_DMASYNC_POSTWRITE); 3074 bus_dmamap_sync(sc->sc_dmat, MFIMEM_MAP(sc->sc_tbolt_ioc_init), 0, 3075 MFIMEM_MAP(sc->sc_tbolt_ioc_init)->dm_mapsize, 3076 BUS_DMASYNC_POSTWRITE); 3077 mfi_put_ccb(ccb); 3078 splx(s); 3079 3080 if (mfi_init->mif_header.mfh_cmd_status == 0) { 3081 sc->sc_MFA_enabled = 1; 3082 } 3083 else { 3084 aprint_error_dev(sc->sc_dev, "Init command Failed %x\n", 3085 mfi_init->mif_header.mfh_cmd_status); 3086 return 1; 3087 } 3088 3089 snprintf(wqbuf, sizeof(wqbuf), "%swq", DEVNAME(sc)); 3090 if (workqueue_create(&sc->sc_ldsync_wq, wqbuf, mfi_tbolt_sync_map_info, 3091 sc, PRIBIO, IPL_BIO, 0) != 0) { 3092 aprint_error_dev(sc->sc_dev, "workqueue_create failed\n"); 3093 return 1; 3094 } 3095 workqueue_enqueue(sc->sc_ldsync_wq, &sc->sc_ldsync_wk, NULL); 3096 return 0; 3097} 3098 3099int 3100mfi_tbolt_intrh(void *arg) 3101{ 3102 struct mfi_softc *sc = arg; 3103 struct mfi_ccb *ccb; 3104 union mfi_mpi2_reply_descriptor *desc; 3105 int smid, num_completed; 3106 3107 if (!mfi_tbolt_intr(sc)) 3108 return 0; 3109 3110 DNPRINTF(MFI_D_INTR, "%s: mfi_tbolt_intrh %#lx %#lx\n", DEVNAME(sc), 3111 (u_long)sc, (u_long)sc->sc_last_reply_idx); 3112 3113 KASSERT(sc->sc_last_reply_idx < sc->sc_reply_pool_size); 3114 3115 desc = (union mfi_mpi2_reply_descriptor *) 3116 ((uintptr_t)sc->sc_reply_frame_pool + 3117 sc->sc_last_reply_idx * MEGASAS_THUNDERBOLT_REPLY_SIZE); 3118 3119 bus_dmamap_sync(sc->sc_dmat, 3120 MFIMEM_MAP(sc->sc_tbolt_reqmsgpool), 3121 MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * (sc->sc_max_cmds + 1), 3122 MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size, 3123 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 3124 num_completed = 0; 3125 while ((desc->header.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK) != 3126 MPI2_RPY_DESCRIPT_FLAGS_UNUSED) { 3127 smid = desc->header.SMID; 3128 KASSERT(smid > 0 && smid <= sc->sc_max_cmds); 3129 ccb = &sc->sc_ccb[smid - 1]; 3130 DNPRINTF(MFI_D_INTR, 3131 "%s: mfi_tbolt_intr SMID %#x reply_idx %#x " 3132 "desc %#" PRIx64 " ccb %p\n", DEVNAME(sc), smid, 3133 sc->sc_last_reply_idx, desc->words, ccb); 3134 KASSERT(ccb->ccb_state == MFI_CCB_RUNNING); 3135 if (ccb->ccb_flags & MFI_CCB_F_TBOLT_IO && 3136 ccb->ccb_tb_io_request->ChainOffset != 0) { 3137 bus_dmamap_sync(sc->sc_dmat, 3138 MFIMEM_MAP(sc->sc_tbolt_reqmsgpool), 3139 ccb->ccb_tb_psg_frame - 3140 MFIMEM_DVA(sc->sc_tbolt_reqmsgpool), 3141 MEGASAS_MAX_SZ_CHAIN_FRAME, BUS_DMASYNC_POSTREAD); 3142 } 3143 if (ccb->ccb_flags & MFI_CCB_F_TBOLT_IO) { 3144 bus_dmamap_sync(sc->sc_dmat, 3145 MFIMEM_MAP(sc->sc_tbolt_reqmsgpool), 3146 ccb->ccb_tb_pio_request - 3147 MFIMEM_DVA(sc->sc_tbolt_reqmsgpool), 3148 MEGASAS_THUNDERBOLT_NEW_MSG_SIZE, 3149 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 3150 } 3151 if (ccb->ccb_done) 3152 ccb->ccb_done(ccb); 3153 else 3154 ccb->ccb_state = MFI_CCB_DONE; 3155 sc->sc_last_reply_idx++; 3156 if (sc->sc_last_reply_idx >= sc->sc_reply_pool_size) { 3157 sc->sc_last_reply_idx = 0; 3158 } 3159 desc->words = ~0x0; 3160 /* Get the next reply descriptor */ 3161 desc = (union mfi_mpi2_reply_descriptor *) 3162 ((uintptr_t)sc->sc_reply_frame_pool + 3163 sc->sc_last_reply_idx * MEGASAS_THUNDERBOLT_REPLY_SIZE); 3164 num_completed++; 3165 } 3166 if (num_completed == 0) 3167 return 0; 3168 3169 bus_dmamap_sync(sc->sc_dmat, 3170 MFIMEM_MAP(sc->sc_tbolt_reqmsgpool), 3171 MEGASAS_THUNDERBOLT_NEW_MSG_SIZE * (sc->sc_max_cmds + 1), 3172 MEGASAS_THUNDERBOLT_REPLY_SIZE * sc->sc_reply_pool_size, 3173 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3174 mfi_write(sc, MFI_RPI, sc->sc_last_reply_idx); 3175 return 1; 3176} 3177 3178 3179int 3180mfi_tbolt_scsi_ld_io(struct mfi_ccb *ccb, struct scsipi_xfer *xs, 3181 uint64_t blockno, uint32_t blockcnt) 3182{ 3183 struct scsipi_periph *periph = xs->xs_periph; 3184 struct mfi_mpi2_request_raid_scsi_io *io_req; 3185 int sge_count; 3186 3187 DNPRINTF(MFI_D_CMD, "%s: mfi_tbolt_scsi_ld_io: %d\n", 3188 device_xname(periph->periph_channel->chan_adapter->adapt_dev), 3189 periph->periph_target); 3190 3191 if (!xs->data) 3192 return 1; 3193 3194 ccb->ccb_done = mfi_tbolt_scsi_ld_done; 3195 ccb->ccb_xs = xs; 3196 ccb->ccb_data = xs->data; 3197 ccb->ccb_len = xs->datalen; 3198 3199 io_req = ccb->ccb_tb_io_request; 3200 3201 /* Just the CDB length,rest of the Flags are zero */ 3202 io_req->IoFlags = xs->cmdlen; 3203 memset(io_req->CDB.CDB32, 0, 32); 3204 memcpy(io_req->CDB.CDB32, &xs->cmdstore, xs->cmdlen); 3205 3206 io_req->RaidContext.TargetID = periph->periph_target; 3207 io_req->RaidContext.Status = 0; 3208 io_req->RaidContext.exStatus = 0; 3209 io_req->RaidContext.timeoutValue = MFI_FUSION_FP_DEFAULT_TIMEOUT; 3210 io_req->Function = MPI2_FUNCTION_LD_IO_REQUEST; 3211 io_req->DevHandle = periph->periph_target; 3212 3213 ccb->ccb_tb_request_desc.header.RequestFlags = 3214 (MFI_REQ_DESCRIPT_FLAGS_LD_IO << MFI_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 3215 io_req->DataLength = blockcnt * MFI_SECTOR_LEN; 3216 3217 if (xs->xs_control & XS_CTL_DATA_IN) { 3218 io_req->Control = MPI2_SCSIIO_CONTROL_READ; 3219 ccb->ccb_direction = MFI_DATA_IN; 3220 } else { 3221 io_req->Control = MPI2_SCSIIO_CONTROL_WRITE; 3222 ccb->ccb_direction = MFI_DATA_OUT; 3223 } 3224 3225 sge_count = mfi_tbolt_create_sgl(ccb, 3226 (xs->xs_control & XS_CTL_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK 3227 ); 3228 if (sge_count < 0) 3229 return 1; 3230 KASSERT(sge_count <= ccb->ccb_sc->sc_max_sgl); 3231 io_req->RaidContext.numSGE = sge_count; 3232 io_req->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING; 3233 io_req->SGLOffset0 = 3234 offsetof(struct mfi_mpi2_request_raid_scsi_io, SGL) / 4; 3235 3236 io_req->SenseBufferLowAddress = htole32(ccb->ccb_psense); 3237 io_req->SenseBufferLength = MFI_SENSE_SIZE; 3238 3239 ccb->ccb_flags |= MFI_CCB_F_TBOLT | MFI_CCB_F_TBOLT_IO; 3240 bus_dmamap_sync(ccb->ccb_sc->sc_dmat, 3241 MFIMEM_MAP(ccb->ccb_sc->sc_tbolt_reqmsgpool), 3242 ccb->ccb_tb_pio_request - 3243 MFIMEM_DVA(ccb->ccb_sc->sc_tbolt_reqmsgpool), 3244 MEGASAS_THUNDERBOLT_NEW_MSG_SIZE, 3245 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 3246 3247 return 0; 3248} 3249 3250 3251static void 3252mfi_tbolt_scsi_ld_done(struct mfi_ccb *ccb) 3253{ 3254 struct mfi_mpi2_request_raid_scsi_io *io_req = ccb->ccb_tb_io_request; 3255 mfi_scsi_xs_done(ccb, io_req->RaidContext.Status, 3256 io_req->RaidContext.exStatus); 3257} 3258 3259static int 3260mfi_tbolt_create_sgl(struct mfi_ccb *ccb, int flags) 3261{ 3262 struct mfi_softc *sc = ccb->ccb_sc; 3263 bus_dma_segment_t *sgd; 3264 int error, i, sge_idx, sge_count; 3265 struct mfi_mpi2_request_raid_scsi_io *io_req; 3266 struct mpi25_ieee_sge_chain64 *sgl_ptr; 3267 3268 DNPRINTF(MFI_D_DMA, "%s: mfi_tbolt_create_sgl %#lx\n", DEVNAME(sc), 3269 (u_long)ccb->ccb_data); 3270 3271 if (!ccb->ccb_data) 3272 return -1; 3273 3274 KASSERT(flags == BUS_DMA_NOWAIT || !cpu_intr_p()); 3275 error = bus_dmamap_load(sc->sc_datadmat, ccb->ccb_dmamap, 3276 ccb->ccb_data, ccb->ccb_len, NULL, flags); 3277 if (error) { 3278 if (error == EFBIG) 3279 aprint_error_dev(sc->sc_dev, "more than %d dma segs\n", 3280 sc->sc_max_sgl); 3281 else 3282 aprint_error_dev(sc->sc_dev, 3283 "error %d loading dma map\n", error); 3284 return -1; 3285 } 3286 3287 io_req = ccb->ccb_tb_io_request; 3288 sgl_ptr = &io_req->SGL.IeeeChain.Chain64; 3289 sge_count = ccb->ccb_dmamap->dm_nsegs; 3290 sgd = ccb->ccb_dmamap->dm_segs; 3291 KASSERT(sge_count <= sc->sc_max_sgl); 3292 KASSERT(sge_count <= 3293 (MEGASAS_THUNDERBOLT_MAX_SGE_IN_MAINMSG - 1 + 3294 MEGASAS_THUNDERBOLT_MAX_SGE_IN_CHAINMSG)); 3295 3296 if (sge_count > MEGASAS_THUNDERBOLT_MAX_SGE_IN_MAINMSG) { 3297 /* One element to store the chain info */ 3298 sge_idx = MEGASAS_THUNDERBOLT_MAX_SGE_IN_MAINMSG - 1; 3299 DNPRINTF(MFI_D_DMA, 3300 "mfi sge_idx %d sge_count %d io_req paddr 0x%" PRIx64 "\n", 3301 sge_idx, sge_count, ccb->ccb_tb_pio_request); 3302 } else { 3303 sge_idx = sge_count; 3304 } 3305 3306 for (i = 0; i < sge_idx; i++) { 3307 sgl_ptr->Address = htole64(sgd[i].ds_addr); 3308 sgl_ptr->Length = htole32(sgd[i].ds_len); 3309 sgl_ptr->Flags = 0; 3310 if (sge_idx < sge_count) { 3311 DNPRINTF(MFI_D_DMA, 3312 "sgl %p %d 0x%" PRIx64 " len 0x%" PRIx32 3313 " flags 0x%x\n", sgl_ptr, i, 3314 sgl_ptr->Address, sgl_ptr->Length, 3315 sgl_ptr->Flags); 3316 } 3317 sgl_ptr++; 3318 } 3319 io_req->ChainOffset = 0; 3320 if (sge_idx < sge_count) { 3321 struct mpi25_ieee_sge_chain64 *sg_chain; 3322 io_req->ChainOffset = MEGASAS_THUNDERBOLT_CHAIN_OFF_MAINMSG; 3323 sg_chain = sgl_ptr; 3324 /* Prepare chain element */ 3325 sg_chain->NextChainOffset = 0; 3326 sg_chain->Flags = (MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | 3327 MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR); 3328 sg_chain->Length = (sizeof(mpi2_sge_io_union) * 3329 (sge_count - sge_idx)); 3330 sg_chain->Address = ccb->ccb_tb_psg_frame; 3331 DNPRINTF(MFI_D_DMA, 3332 "sgl %p chain 0x%" PRIx64 " len 0x%" PRIx32 3333 " flags 0x%x\n", sg_chain, sg_chain->Address, 3334 sg_chain->Length, sg_chain->Flags); 3335 sgl_ptr = &ccb->ccb_tb_sg_frame->IeeeChain.Chain64; 3336 for (; i < sge_count; i++) { 3337 sgl_ptr->Address = htole64(sgd[i].ds_addr); 3338 sgl_ptr->Length = htole32(sgd[i].ds_len); 3339 sgl_ptr->Flags = 0; 3340 DNPRINTF(MFI_D_DMA, 3341 "sgl %p %d 0x%" PRIx64 " len 0x%" PRIx32 3342 " flags 0x%x\n", sgl_ptr, i, sgl_ptr->Address, 3343 sgl_ptr->Length, sgl_ptr->Flags); 3344 sgl_ptr++; 3345 } 3346 bus_dmamap_sync(sc->sc_dmat, 3347 MFIMEM_MAP(sc->sc_tbolt_reqmsgpool), 3348 ccb->ccb_tb_psg_frame - MFIMEM_DVA(sc->sc_tbolt_reqmsgpool), 3349 MEGASAS_MAX_SZ_CHAIN_FRAME, BUS_DMASYNC_PREREAD); 3350 } 3351 3352 if (ccb->ccb_direction == MFI_DATA_IN) { 3353 bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0, 3354 ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD); 3355 } else { 3356 bus_dmamap_sync(sc->sc_datadmat, ccb->ccb_dmamap, 0, 3357 ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); 3358 } 3359 return sge_count; 3360} 3361 3362/* 3363 * The ThunderBolt HW has an option for the driver to directly 3364 * access the underlying disks and operate on the RAID. To 3365 * do this there needs to be a capability to keep the RAID controller 3366 * and driver in sync. The FreeBSD driver does not take advantage 3367 * of this feature since it adds a lot of complexity and slows down 3368 * performance. Performance is gained by using the controller's 3369 * cache etc. 3370 * 3371 * Even though this driver doesn't access the disks directly, an 3372 * AEN like command is used to inform the RAID firmware to "sync" 3373 * with all LD's via the MFI_DCMD_LD_MAP_GET_INFO command. This 3374 * command in write mode will return when the RAID firmware has 3375 * detected a change to the RAID state. Examples of this type 3376 * of change are removing a disk. Once the command returns then 3377 * the driver needs to acknowledge this and "sync" all LD's again. 3378 * This repeats until we shutdown. Then we need to cancel this 3379 * pending command. 3380 * 3381 * If this is not done right the RAID firmware will not remove a 3382 * pulled drive and the RAID won't go degraded etc. Effectively, 3383 * stopping any RAID mangement to functions. 3384 * 3385 * Doing another LD sync, requires the use of an event since the 3386 * driver needs to do a mfi_wait_command and can't do that in an 3387 * interrupt thread. 3388 * 3389 * The driver could get the RAID state via the MFI_DCMD_LD_MAP_GET_INFO 3390 * That requires a bunch of structure and it is simplier to just do 3391 * the MFI_DCMD_LD_GET_LIST versus walking the RAID map. 3392 */ 3393 3394void 3395mfi_tbolt_sync_map_info(struct work *w, void *v) 3396{ 3397 struct mfi_softc *sc = v; 3398 int i; 3399 struct mfi_ccb *ccb = NULL; 3400 uint8_t mbox[MFI_MBOX_SIZE]; 3401 struct mfi_ld *ld_sync = NULL; 3402 size_t ld_size; 3403 int s; 3404 3405 DNPRINTF(MFI_D_SYNC, "%s: mfi_tbolt_sync_map_info\n", DEVNAME(sc)); 3406again: 3407 s = splbio(); 3408 if (sc->sc_ldsync_ccb != NULL) { 3409 splx(s); 3410 return; 3411 } 3412 3413 if (mfi_mgmt_internal(sc, MR_DCMD_LD_GET_LIST, MFI_DATA_IN, 3414 sizeof(sc->sc_ld_list), &sc->sc_ld_list, NULL, false)) { 3415 aprint_error_dev(sc->sc_dev, "MR_DCMD_LD_GET_LIST failed\n"); 3416 goto err; 3417 } 3418 3419 ld_size = sizeof(*ld_sync) * sc->sc_ld_list.mll_no_ld; 3420 3421 ld_sync = (struct mfi_ld *) malloc(ld_size, M_DEVBUF, 3422 M_WAITOK | M_ZERO); 3423 if (ld_sync == NULL) { 3424 aprint_error_dev(sc->sc_dev, "Failed to allocate sync\n"); 3425 goto err; 3426 } 3427 for (i = 0; i < sc->sc_ld_list.mll_no_ld; i++) { 3428 ld_sync[i] = sc->sc_ld_list.mll_list[i].mll_ld; 3429 } 3430 3431 if ((ccb = mfi_get_ccb(sc)) == NULL) { 3432 aprint_error_dev(sc->sc_dev, "Failed to get sync command\n"); 3433 free(ld_sync, M_DEVBUF); 3434 goto err; 3435 } 3436 sc->sc_ldsync_ccb = ccb; 3437 3438 memset(mbox, 0, MFI_MBOX_SIZE); 3439 mbox[0] = sc->sc_ld_list.mll_no_ld; 3440 mbox[1] = MFI_DCMD_MBOX_PEND_FLAG; 3441 if (mfi_mgmt(ccb, NULL, MR_DCMD_LD_MAP_GET_INFO, MFI_DATA_OUT, 3442 ld_size, ld_sync, mbox)) { 3443 aprint_error_dev(sc->sc_dev, "Failed to create sync command\n"); 3444 goto err; 3445 } 3446 /* 3447 * we won't sleep on this command, so we have to override 3448 * the callback set up by mfi_mgmt() 3449 */ 3450 ccb->ccb_done = mfi_sync_map_complete; 3451 3452 mfi_post(sc, ccb); 3453 splx(s); 3454 return; 3455 3456err: 3457 if (ld_sync) 3458 free(ld_sync, M_DEVBUF); 3459 if (ccb) 3460 mfi_put_ccb(ccb); 3461 sc->sc_ldsync_ccb = NULL; 3462 splx(s); 3463 kpause("ldsyncp", 0, hz, NULL); 3464 goto again; 3465} 3466 3467static void 3468mfi_sync_map_complete(struct mfi_ccb *ccb) 3469{ 3470 struct mfi_softc *sc = ccb->ccb_sc; 3471 bool aborted = !sc->sc_running; 3472 3473 DNPRINTF(MFI_D_SYNC, "%s: mfi_sync_map_complete\n", 3474 DEVNAME(ccb->ccb_sc)); 3475 KASSERT(sc->sc_ldsync_ccb == ccb); 3476 mfi_mgmt_done(ccb); 3477 free(ccb->ccb_data, M_DEVBUF); 3478 if (ccb->ccb_flags & MFI_CCB_F_ERR) { 3479 aprint_error_dev(sc->sc_dev, "sync command failed\n"); 3480 aborted = true; 3481 } 3482 mfi_put_ccb(ccb); 3483 sc->sc_ldsync_ccb = NULL; 3484 3485 /* set it up again so the driver can catch more events */ 3486 if (!aborted) { 3487 workqueue_enqueue(sc->sc_ldsync_wq, &sc->sc_ldsync_wk, NULL); 3488 } 3489} 3490 3491static int 3492mfifopen(dev_t dev, int flag, int mode, struct lwp *l) 3493{ 3494 struct mfi_softc *sc; 3495 3496 if ((sc = device_lookup_private(&mfi_cd, minor(dev))) == NULL) 3497 return (ENXIO); 3498 return (0); 3499} 3500 3501static int 3502mfifclose(dev_t dev, int flag, int mode, struct lwp *l) 3503{ 3504 struct mfi_softc *sc; 3505 3506 sc = device_lookup_private(&mfi_cd, minor(dev)); 3507 return (0); 3508} 3509 3510static int 3511mfifioctl(dev_t dev, u_long cmd, void *data, int flag, 3512 struct lwp *l) 3513{ 3514 struct mfi_softc *sc; 3515 struct mfi_ioc_packet *ioc = data; 3516 uint8_t *udata; 3517 struct mfi_ccb *ccb = NULL; 3518 int ctx, i, s, error; 3519 union mfi_sense_ptr sense_ptr; 3520 3521 switch(cmd) { 3522 case MFI_CMD: 3523 sc = device_lookup_private(&mfi_cd, ioc->mfi_adapter_no); 3524 break; 3525 default: 3526 return ENOTTY; 3527 } 3528 if (sc == NULL) 3529 return (ENXIO); 3530 if (sc->sc_opened) 3531 return (EBUSY); 3532 3533 switch(cmd) { 3534 case MFI_CMD: 3535 error = kauth_authorize_device_passthru(l->l_cred, dev, 3536 KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL, data); 3537 if (error) 3538 return error; 3539 if (ioc->mfi_sge_count > MAX_IOCTL_SGE) 3540 return EINVAL; 3541 s = splbio(); 3542 if ((ccb = mfi_get_ccb(sc)) == NULL) 3543 return ENOMEM; 3544 ccb->ccb_data = NULL; 3545 ctx = ccb->ccb_frame->mfr_header.mfh_context; 3546 memcpy(ccb->ccb_frame, ioc->mfi_frame.raw, 3547 sizeof(*ccb->ccb_frame)); 3548 ccb->ccb_frame->mfr_header.mfh_context = ctx; 3549 ccb->ccb_frame->mfr_header.mfh_scsi_status = 0; 3550 ccb->ccb_frame->mfr_header.mfh_pad0 = 0; 3551 ccb->ccb_frame_size = 3552 (sizeof(union mfi_sgl) * ioc->mfi_sge_count) + 3553 ioc->mfi_sgl_off; 3554 if (ioc->mfi_sge_count > 0) { 3555 ccb->ccb_sgl = (union mfi_sgl *) 3556 &ccb->ccb_frame->mfr_bytes[ioc->mfi_sgl_off]; 3557 } 3558 if (ccb->ccb_frame->mfr_header.mfh_flags & MFI_FRAME_DIR_READ) 3559 ccb->ccb_direction = MFI_DATA_IN; 3560 if (ccb->ccb_frame->mfr_header.mfh_flags & MFI_FRAME_DIR_WRITE) 3561 ccb->ccb_direction = MFI_DATA_OUT; 3562 ccb->ccb_len = ccb->ccb_frame->mfr_header.mfh_data_len; 3563 if (ccb->ccb_len > MAXPHYS) { 3564 error = ENOMEM; 3565 goto out; 3566 } 3567 if (ccb->ccb_len && 3568 (ccb->ccb_direction & (MFI_DATA_IN | MFI_DATA_OUT)) != 0) { 3569 udata = malloc(ccb->ccb_len, M_DEVBUF, M_WAITOK|M_ZERO); 3570 if (udata == NULL) { 3571 error = ENOMEM; 3572 goto out; 3573 } 3574 ccb->ccb_data = udata; 3575 if (ccb->ccb_direction & MFI_DATA_OUT) { 3576 for (i = 0; i < ioc->mfi_sge_count; i++) { 3577 error = copyin(ioc->mfi_sgl[i].iov_base, 3578 udata, ioc->mfi_sgl[i].iov_len); 3579 if (error) 3580 goto out; 3581 udata = &udata[ 3582 ioc->mfi_sgl[i].iov_len]; 3583 } 3584 } 3585 if (mfi_create_sgl(ccb, BUS_DMA_WAITOK)) { 3586 error = EIO; 3587 goto out; 3588 } 3589 } 3590 if (ccb->ccb_frame->mfr_header.mfh_cmd == MFI_CMD_PD_SCSI_IO) { 3591 ccb->ccb_frame->mfr_io.mif_sense_addr_lo = 3592 htole32(ccb->ccb_psense); 3593 ccb->ccb_frame->mfr_io.mif_sense_addr_hi = 0; 3594 } 3595 ccb->ccb_done = mfi_mgmt_done; 3596 mfi_post(sc, ccb); 3597 while (ccb->ccb_state != MFI_CCB_DONE) 3598 tsleep(ccb, PRIBIO, "mfi_fioc", 0); 3599 3600 if (ccb->ccb_direction & MFI_DATA_IN) { 3601 udata = ccb->ccb_data; 3602 for (i = 0; i < ioc->mfi_sge_count; i++) { 3603 error = copyout(udata, 3604 ioc->mfi_sgl[i].iov_base, 3605 ioc->mfi_sgl[i].iov_len); 3606 if (error) 3607 goto out; 3608 udata = &udata[ 3609 ioc->mfi_sgl[i].iov_len]; 3610 } 3611 } 3612 if (ioc->mfi_sense_len) { 3613 memcpy(&sense_ptr.sense_ptr_data[0], 3614 &ioc->mfi_frame.raw[ioc->mfi_sense_off], 3615 sizeof(sense_ptr.sense_ptr_data)); 3616 error = copyout(ccb->ccb_sense, 3617 sense_ptr.user_space, 3618 sizeof(sense_ptr.sense_ptr_data)); 3619 if (error) 3620 goto out; 3621 } 3622 memcpy(ioc->mfi_frame.raw, ccb->ccb_frame, 3623 sizeof(*ccb->ccb_frame)); 3624 break; 3625 default: 3626 printf("mfifioctl unhandled cmd 0x%lx\n", cmd); 3627 return ENOTTY; 3628 } 3629 3630out: 3631 if (ccb->ccb_data) 3632 free(ccb->ccb_data, M_DEVBUF); 3633 if (ccb) 3634 mfi_put_ccb(ccb); 3635 splx(s); 3636 return error; 3637} 3638