1 /* $OpenBSD: mpi.c,v 1.27 2006/06/08 12:27:59 dlg Exp $ */ 2 3 /* 4 * Copyright (c) 2005, 2006 David Gwynne <dlg@openbsd.org> 5 * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> 6 * 7 * Permission to use, copy, modify, and distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <sys/param.h> 21 #include <sys/systm.h> 22 #include <sys/buf.h> 23 #include <sys/device.h> 24 #include <sys/proc.h> 25 #include <sys/malloc.h> 26 #include <sys/kernel.h> 27 28 #include <machine/bus.h> 29 30 #include <scsi/scsi_all.h> 31 #include <scsi/scsiconf.h> 32 33 #include <dev/ic/mpireg.h> 34 #include <dev/ic/mpivar.h> 35 36 #ifdef MPI_DEBUG 37 #define DPRINTF(x...) do { if (mpidebug) printf(x); } while (0) 38 #define DPRINTFN(n, x...) do { if (mpidebug > (n)) printf(x); } while (0) 39 int mpidebug = 11; 40 #else 41 #define DPRINTF(x...) /* x */ 42 #define DPRINTFN(n, x...) /* n, x */ 43 #endif 44 45 struct cfdriver mpi_cd = { 46 NULL, "mpi", DV_DULL 47 }; 48 49 int mpi_scsi_cmd(struct scsi_xfer *); 50 void mpi_scsi_cmd_done(struct mpi_ccb *); 51 void mpi_minphys(struct buf *bp); 52 int mpi_scsi_ioctl(struct scsi_link *, u_long, caddr_t, 53 int, struct proc *); 54 55 struct scsi_adapter mpi_switch = { 56 mpi_scsi_cmd, mpi_minphys, NULL, NULL, mpi_scsi_ioctl 57 }; 58 59 struct scsi_device mpi_dev = { 60 NULL, NULL, NULL, NULL 61 }; 62 63 struct mpi_dmamem *mpi_dmamem_alloc(struct mpi_softc *, size_t); 64 void mpi_dmamem_free(struct mpi_softc *, 65 struct mpi_dmamem *); 66 int mpi_alloc_ccbs(struct mpi_softc *); 67 struct mpi_ccb *mpi_get_ccb(struct mpi_softc *); 68 void mpi_put_ccb(struct mpi_softc *, struct mpi_ccb *); 69 int mpi_alloc_replies(struct mpi_softc *); 70 void mpi_push_replies(struct mpi_softc *); 71 72 void mpi_start(struct mpi_softc *, struct mpi_ccb *); 73 int mpi_complete(struct mpi_softc *, struct mpi_ccb *, int); 74 int mpi_poll(struct mpi_softc *, struct mpi_ccb *, int); 75 76 void mpi_timeout_xs(void *); 77 int mpi_load_xs(struct mpi_ccb *); 78 79 u_int32_t mpi_read(struct mpi_softc *, bus_size_t); 80 void mpi_write(struct mpi_softc *, bus_size_t, u_int32_t); 81 int mpi_wait_eq(struct mpi_softc *, bus_size_t, u_int32_t, 82 u_int32_t); 83 int mpi_wait_ne(struct mpi_softc *, bus_size_t, u_int32_t, 84 u_int32_t); 85 86 int mpi_init(struct mpi_softc *); 87 int mpi_reset_soft(struct mpi_softc *); 88 int mpi_reset_hard(struct mpi_softc *); 89 90 int mpi_handshake_send(struct mpi_softc *, void *, size_t); 91 int mpi_handshake_recv_dword(struct mpi_softc *, 92 u_int32_t *); 93 int mpi_handshake_recv(struct mpi_softc *, void *, size_t); 94 95 void mpi_empty_done(struct mpi_ccb *); 96 97 int mpi_iocinit(struct mpi_softc *); 98 int mpi_iocfacts(struct mpi_softc *); 99 int mpi_portfacts(struct mpi_softc *); 100 int mpi_eventnotify(struct mpi_softc *); 101 void mpi_eventnotify_done(struct mpi_ccb *); 102 int mpi_portenable(struct mpi_softc *); 103 104 int mpi_cfg_hdr(struct mpi_softc *, u_int8_t, u_int8_t, 105 u_int32_t, struct mpi_cfg_hdr *); 106 int mpi_cfg_page(struct mpi_softc *, u_int32_t, 107 struct mpi_cfg_hdr *, int, void *, size_t); 108 109 #define DEVNAME(s) ((s)->sc_dev.dv_xname) 110 111 #define dwordsof(s) (sizeof(s) / sizeof(u_int32_t)) 112 #define sizeofa(s) (sizeof(s) / sizeof((s)[0])) 113 114 #define mpi_read_db(s) mpi_read((s), MPI_DOORBELL) 115 #define mpi_write_db(s, v) mpi_write((s), MPI_DOORBELL, (v)) 116 #define mpi_read_intr(s) mpi_read((s), MPI_INTR_STATUS) 117 #define mpi_write_intr(s, v) mpi_write((s), MPI_INTR_STATUS, (v)) 118 #define mpi_pop_reply(s) mpi_read((s), MPI_REPLY_QUEUE) 119 #define mpi_push_reply(s, v) mpi_write((s), MPI_REPLY_QUEUE, (v)) 120 121 #define mpi_wait_db_int(s) mpi_wait_ne((s), MPI_INTR_STATUS, \ 122 MPI_INTR_STATUS_DOORBELL, 0) 123 #define mpi_wait_db_ack(s) mpi_wait_eq((s), MPI_INTR_STATUS, \ 124 MPI_INTR_STATUS_IOCDOORBELL, 0) 125 126 int 127 mpi_attach(struct mpi_softc *sc) 128 { 129 struct mpi_ccb *ccb; 130 131 printf("\n"); 132 133 /* disable interrupts */ 134 mpi_write(sc, MPI_INTR_MASK, 135 MPI_INTR_MASK_REPLY | MPI_INTR_MASK_DOORBELL); 136 137 if (mpi_init(sc) != 0) { 138 printf("%s: unable to initialise\n", DEVNAME(sc)); 139 return (1); 140 } 141 142 if (mpi_iocfacts(sc) != 0) { 143 printf("%s: unable to get iocfacts\n", DEVNAME(sc)); 144 return (1); 145 } 146 147 if (mpi_alloc_ccbs(sc) != 0) { 148 /* error already printed */ 149 return (1); 150 } 151 152 if (mpi_alloc_replies(sc) != 0) { 153 printf("%s: unable to allocate reply space\n", DEVNAME(sc)); 154 goto free_ccbs; 155 } 156 157 if (mpi_iocinit(sc) != 0) { 158 printf("%s: unable to send iocinit\n", DEVNAME(sc)); 159 goto free_ccbs; 160 } 161 162 /* spin until we're operational */ 163 if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE, 164 MPI_DOORBELL_STATE_OPER) != 0) { 165 printf("%s: state: 0x%08x\n", DEVNAME(sc), 166 mpi_read_db(sc) & MPI_DOORBELL_STATE); 167 printf("%s: operational state timeout\n", DEVNAME(sc)); 168 goto free_ccbs; 169 } 170 171 mpi_push_replies(sc); 172 173 if (mpi_portfacts(sc) != 0) { 174 printf("%s: unable to get portfacts\n", DEVNAME(sc)); 175 goto free_replies; 176 } 177 178 #if notyet 179 if (mpi_eventnotify(sc) != 0) { 180 printf("%s: unable to get portfacts\n", DEVNAME(sc)); 181 goto free_replies; 182 } 183 #endif 184 185 if (mpi_portenable(sc) != 0) { 186 printf("%s: unable to enable port\n", DEVNAME(sc)); 187 goto free_replies; 188 } 189 190 /* we should be good to go now, attach scsibus */ 191 sc->sc_link.device = &mpi_dev; 192 sc->sc_link.adapter = &mpi_switch; 193 sc->sc_link.adapter_softc = sc; 194 sc->sc_link.adapter_target = sc->sc_target; 195 sc->sc_link.adapter_buswidth = sc->sc_buswidth; 196 sc->sc_link.openings = sc->sc_maxcmds / sc->sc_buswidth; 197 198 config_found(&sc->sc_dev, &sc->sc_link, scsiprint); 199 200 /* XXX enable interrupts */ 201 mpi_write(sc, MPI_INTR_MASK, MPI_INTR_MASK_DOORBELL); 202 203 return (0); 204 205 free_replies: 206 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies), 207 0, PAGE_SIZE, BUS_DMASYNC_POSTREAD); 208 mpi_dmamem_free(sc, sc->sc_replies); 209 free_ccbs: 210 while ((ccb = mpi_get_ccb(sc)) != NULL) 211 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 212 mpi_dmamem_free(sc, sc->sc_requests); 213 free(sc->sc_ccbs, M_DEVBUF); 214 215 return(1); 216 } 217 218 void 219 mpi_detach(struct mpi_softc *sc) 220 { 221 222 } 223 224 int 225 mpi_intr(void *arg) 226 { 227 struct mpi_softc *sc = arg; 228 struct mpi_ccb *ccb; 229 struct mpi_msg_reply *reply = NULL; 230 u_int32_t reply_dva; 231 char *reply_addr; 232 u_int32_t reg, id; 233 int rv = 0; 234 235 while ((reg = mpi_pop_reply(sc)) != 0xffffffff) { 236 237 DPRINTF("%s: %s reply_queue: 0x%08x\n", DEVNAME(sc), __func__, 238 reg); 239 240 if (reg & MPI_REPLY_QUEUE_ADDRESS) { 241 bus_dmamap_sync(sc->sc_dmat, 242 MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE, 243 BUS_DMASYNC_POSTREAD); 244 245 reply_dva = (reg & MPI_REPLY_QUEUE_ADDRESS_MASK) << 1; 246 247 reply_addr = MPI_DMA_KVA(sc->sc_replies); 248 reply_addr += reply_dva - 249 (u_int32_t)MPI_DMA_DVA(sc->sc_replies); 250 reply = (struct mpi_msg_reply *)reply_addr; 251 252 id = letoh32(reply->msg_context); 253 254 bus_dmamap_sync(sc->sc_dmat, 255 MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE, 256 BUS_DMASYNC_PREREAD); 257 } else { 258 switch (reg & MPI_REPLY_QUEUE_TYPE_MASK) { 259 case MPI_REPLY_QUEUE_TYPE_INIT: 260 id = reg & MPI_REPLY_QUEUE_CONTEXT; 261 break; 262 263 default: 264 panic("%s: unsupported context reply\n", 265 DEVNAME(sc)); 266 } 267 } 268 269 DPRINTF("%s: %s id: %d\n", DEVNAME(sc), __func__, id); 270 271 ccb = &sc->sc_ccbs[id]; 272 273 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests), 274 ccb->ccb_offset, MPI_REQUEST_SIZE, BUS_DMASYNC_POSTWRITE); 275 ccb->ccb_state = MPI_CCB_READY; 276 ccb->ccb_reply = reply; 277 ccb->ccb_reply_dva = reply_dva; 278 279 ccb->ccb_done(ccb); 280 rv = 1; 281 } 282 283 return (rv); 284 } 285 286 struct mpi_dmamem * 287 mpi_dmamem_alloc(struct mpi_softc *sc, size_t size) 288 { 289 struct mpi_dmamem *mdm; 290 int nsegs; 291 292 mdm = malloc(sizeof(struct mpi_dmamem), M_DEVBUF, M_NOWAIT); 293 if (mdm == NULL) 294 return (NULL); 295 296 bzero(mdm, sizeof(struct mpi_dmamem)); 297 mdm->mdm_size = size; 298 299 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 300 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0) 301 goto mdmfree; 302 303 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg, 304 1, &nsegs, BUS_DMA_NOWAIT) != 0) 305 goto destroy; 306 307 if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size, 308 &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0) 309 goto free; 310 311 if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size, 312 NULL, BUS_DMA_NOWAIT) != 0) 313 goto unmap; 314 315 bzero(mdm->mdm_kva, size); 316 return (mdm); 317 318 unmap: 319 bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size); 320 free: 321 bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1); 322 destroy: 323 bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map); 324 mdmfree: 325 free(mdm, M_DEVBUF); 326 327 return (NULL); 328 } 329 330 void 331 mpi_dmamem_free(struct mpi_softc *sc, struct mpi_dmamem *mdm) 332 { 333 bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map); 334 bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size); 335 bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1); 336 bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map); 337 free(mdm, M_DEVBUF); 338 } 339 340 int 341 mpi_alloc_ccbs(struct mpi_softc *sc) 342 { 343 struct mpi_ccb *ccb; 344 u_int8_t *cmd; 345 int i; 346 347 TAILQ_INIT(&sc->sc_ccb_free); 348 349 sc->sc_ccbs = malloc(sizeof(struct mpi_ccb) * sc->sc_maxcmds, 350 M_DEVBUF, M_WAITOK); 351 if (sc->sc_ccbs == NULL) { 352 printf("%s: unable to allocate ccbs\n", DEVNAME(sc)); 353 return (1); 354 } 355 bzero(sc->sc_ccbs, sizeof(struct mpi_ccb) * sc->sc_maxcmds); 356 357 sc->sc_requests = mpi_dmamem_alloc(sc, 358 MPI_REQUEST_SIZE * sc->sc_maxcmds); 359 if (sc->sc_requests == NULL) { 360 printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc)); 361 goto free_ccbs; 362 } 363 cmd = MPI_DMA_KVA(sc->sc_requests); 364 bzero(cmd, MPI_REQUEST_SIZE * sc->sc_maxcmds); 365 366 for (i = 0; i < sc->sc_maxcmds; i++) { 367 ccb = &sc->sc_ccbs[i]; 368 369 if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, 370 sc->sc_max_sgl_len, MAXPHYS, 0, 0, 371 &ccb->ccb_dmamap) != 0) { 372 printf("%s: unable to create dma map\n", DEVNAME(sc)); 373 goto free_maps; 374 } 375 376 ccb->ccb_sc = sc; 377 ccb->ccb_id = i; 378 ccb->ccb_offset = MPI_REQUEST_SIZE * i; 379 380 ccb->ccb_cmd = &cmd[ccb->ccb_offset]; 381 ccb->ccb_cmd_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_requests) + 382 ccb->ccb_offset; 383 384 mpi_put_ccb(sc, ccb); 385 } 386 387 return (0); 388 389 free_maps: 390 while ((ccb = mpi_get_ccb(sc)) != NULL) 391 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 392 393 mpi_dmamem_free(sc, sc->sc_requests); 394 free_ccbs: 395 free(sc->sc_ccbs, M_DEVBUF); 396 397 return (1); 398 } 399 400 struct mpi_ccb * 401 mpi_get_ccb(struct mpi_softc *sc) 402 { 403 struct mpi_ccb *ccb; 404 405 ccb = TAILQ_FIRST(&sc->sc_ccb_free); 406 if (ccb == NULL) 407 return (NULL); 408 409 TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link); 410 411 ccb->ccb_state = MPI_CCB_READY; 412 413 return (ccb); 414 } 415 416 void 417 mpi_put_ccb(struct mpi_softc *sc, struct mpi_ccb *ccb) 418 { 419 ccb->ccb_state = MPI_CCB_FREE; 420 ccb->ccb_xs = NULL; 421 ccb->ccb_done = NULL; 422 bzero(ccb->ccb_cmd, MPI_REQUEST_SIZE); 423 TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link); 424 } 425 426 int 427 mpi_alloc_replies(struct mpi_softc *sc) 428 { 429 sc->sc_replies = mpi_dmamem_alloc(sc, PAGE_SIZE); 430 if (sc->sc_replies == NULL) 431 return (1); 432 433 return (0); 434 } 435 436 void 437 mpi_push_replies(struct mpi_softc *sc) 438 { 439 paddr_t reply; 440 int i; 441 442 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies), 443 0, PAGE_SIZE, BUS_DMASYNC_PREREAD); 444 445 for (i = 0; i < PAGE_SIZE / MPI_REPLY_SIZE; i++) { 446 reply = (u_int32_t)MPI_DMA_DVA(sc->sc_replies) + 447 MPI_REPLY_SIZE * i; 448 mpi_push_reply(sc, reply); 449 } 450 } 451 452 void 453 mpi_start(struct mpi_softc *sc, struct mpi_ccb *ccb) 454 { 455 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests), 456 ccb->ccb_offset, MPI_REQUEST_SIZE, BUS_DMASYNC_PREWRITE); 457 458 ccb->ccb_state = MPI_CCB_QUEUED; 459 mpi_write(sc, MPI_REQ_QUEUE, ccb->ccb_cmd_dva); 460 } 461 462 int 463 mpi_complete(struct mpi_softc *sc, struct mpi_ccb *nccb, int timeout) 464 { 465 struct mpi_ccb *ccb; 466 struct mpi_msg_reply *reply = NULL; 467 u_int32_t reply_dva; 468 char *reply_addr; 469 u_int32_t reg, id; 470 471 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 472 473 do { 474 reg = mpi_pop_reply(sc); 475 if (reg == 0xffffffff) { 476 if (timeout-- == 0) 477 return (1); 478 479 delay(1000); 480 continue; 481 } 482 483 DPRINTF("%s: %s reply_queue: 0x%08x\n", DEVNAME(sc), __func__, 484 reg); 485 486 if (reg & MPI_REPLY_QUEUE_ADDRESS) { 487 bus_dmamap_sync(sc->sc_dmat, 488 MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE, 489 BUS_DMASYNC_POSTREAD); 490 491 reply_dva = (reg & MPI_REPLY_QUEUE_ADDRESS_MASK) << 1; 492 493 reply_addr = MPI_DMA_KVA(sc->sc_replies); 494 reply_addr += reply_dva - 495 (u_int32_t)MPI_DMA_DVA(sc->sc_replies); 496 reply = (struct mpi_msg_reply *)reply_addr; 497 498 id = letoh32(reply->msg_context); 499 500 bus_dmamap_sync(sc->sc_dmat, 501 MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE, 502 BUS_DMASYNC_PREREAD); 503 } else { 504 switch (reg & MPI_REPLY_QUEUE_TYPE_MASK) { 505 case MPI_REPLY_QUEUE_TYPE_INIT: 506 id = reg & MPI_REPLY_QUEUE_CONTEXT; 507 break; 508 509 default: 510 panic("%s: unsupported context reply\n", 511 DEVNAME(sc)); 512 } 513 } 514 515 DPRINTF("%s: %s id: %d\n", DEVNAME(sc), __func__, id); 516 517 ccb = &sc->sc_ccbs[id]; 518 519 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests), 520 ccb->ccb_offset, MPI_REQUEST_SIZE, BUS_DMASYNC_POSTWRITE); 521 ccb->ccb_state = MPI_CCB_READY; 522 ccb->ccb_reply = reply; 523 ccb->ccb_reply_dva = reply_dva; 524 525 ccb->ccb_done(ccb); 526 527 } while (nccb->ccb_id != id); 528 529 return (0); 530 } 531 532 int 533 mpi_poll(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout) 534 { 535 int error; 536 int s; 537 538 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 539 540 s = splbio(); 541 mpi_start(sc, ccb); 542 error = mpi_complete(sc, ccb, timeout); 543 splx(s); 544 545 return (error); 546 } 547 548 int 549 mpi_scsi_cmd(struct scsi_xfer *xs) 550 { 551 struct scsi_link *link = xs->sc_link; 552 struct mpi_softc *sc = link->adapter_softc; 553 struct mpi_ccb *ccb; 554 struct mpi_ccb_bundle *mcb; 555 struct mpi_msg_scsi_io *io; 556 int s; 557 558 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 559 560 if (xs->cmdlen > MPI_CDB_LEN) { 561 DPRINTF("%s: CBD too big %d", DEVNAME(sc), xs->cmdlen); 562 bzero(&xs->sense, sizeof(xs->sense)); 563 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70; 564 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 565 xs->sense.add_sense_code = 0x20; 566 xs->error = XS_SENSE; 567 scsi_done(xs); 568 return (COMPLETE); 569 } 570 571 s = splbio(); 572 ccb = mpi_get_ccb(sc); 573 splx(s); 574 if (ccb == NULL) { 575 xs->error = XS_DRIVER_STUFFUP; 576 scsi_done(xs); 577 return (COMPLETE); 578 } 579 DPRINTF("%s: ccb_id: %d xs->flags: 0x%x\n", DEVNAME(sc), ccb->ccb_id, 580 xs->flags); 581 582 ccb->ccb_xs = xs; 583 ccb->ccb_done = mpi_scsi_cmd_done; 584 585 mcb = ccb->ccb_cmd; 586 io = &mcb->mcb_io; 587 588 io->function = MPI_FUNCTION_SCSI_IO_REQUEST; 589 /* 590 * bus is always 0 591 * io->bus = htole16(sc->sc_bus); 592 */ 593 io->target_id = link->target; 594 595 io->cdb_length = xs->cmdlen; 596 io->sense_buf_len = sizeof(xs->sense); 597 io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64; 598 599 io->msg_context = htole32(ccb->ccb_id); 600 601 io->lun[0] = htobe16(link->lun); 602 603 switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { 604 case SCSI_DATA_IN: 605 io->control = htole32(MPI_SCSIIO_DATA_DIR_READ); 606 break; 607 case SCSI_DATA_OUT: 608 io->control = htole32(MPI_SCSIIO_DATA_DIR_WRITE); 609 break; 610 default: 611 io->control = htole32(MPI_SCSIIO_DATA_DIR_NONE); 612 break; 613 } 614 615 bcopy(xs->cmd, io->cdb, xs->cmdlen); 616 617 io->data_length = htole32(xs->datalen); 618 619 io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva + 620 ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb)); 621 622 if (mpi_load_xs(ccb) != 0) { 623 s = splbio(); 624 mpi_put_ccb(sc, ccb); 625 splx(s); 626 xs->error = XS_DRIVER_STUFFUP; 627 scsi_done(xs); 628 return (COMPLETE); 629 } 630 631 timeout_set(&xs->stimeout, mpi_timeout_xs, ccb); 632 633 if (xs->flags & SCSI_POLL) { 634 if (mpi_poll(sc, ccb, xs->timeout) != 0) 635 xs->error = XS_DRIVER_STUFFUP; 636 return (COMPLETE); 637 } 638 639 mpi_start(sc, ccb); 640 return (SUCCESSFULLY_QUEUED); 641 } 642 643 void 644 mpi_scsi_cmd_done(struct mpi_ccb *ccb) 645 { 646 struct mpi_softc *sc = ccb->ccb_sc; 647 struct scsi_xfer *xs = ccb->ccb_xs; 648 struct mpi_ccb_bundle *mcb = ccb->ccb_cmd; 649 bus_dmamap_t dmap = ccb->ccb_dmamap; 650 struct mpi_msg_scsi_io_error *sie = ccb->ccb_reply; 651 652 if (xs->datalen != 0) { 653 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 654 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD : 655 BUS_DMASYNC_POSTWRITE); 656 657 bus_dmamap_unload(sc->sc_dmat, dmap); 658 } 659 660 /* timeout_del */ 661 xs->error = XS_NOERROR; 662 xs->resid = 0; 663 xs->flags |= ITSDONE; 664 DPRINTFN(10, "%s: xs cmd: 0x%02x len: %d error: 0x%02x flags 0x%x\n", 665 DEVNAME(sc), xs->cmd->opcode, xs->datalen, xs->error, xs->flags); 666 667 if (sie == NULL) { 668 /* no scsi error, we're ok so drop out early */ 669 xs->status = SCSI_OK; 670 mpi_put_ccb(sc, ccb); 671 scsi_done(xs); 672 return; 673 } 674 675 #ifdef MPI_DEBUG 676 if (mpidebug > 10) { 677 printf("%s: target_id: %d bus: %d msg_length: %d " 678 "function: 0x%02x\n", DEVNAME(sc), sie->target_id, 679 sie->bus, sie->msg_length, sie->function); 680 681 printf("%s: cdb_length: %d sense_buf_length: %d " 682 "msg_flags: 0x%02x\n", DEVNAME(sc), sie->cdb_length, 683 sie->bus, sie->msg_flags); 684 685 printf("%s: msg_context: 0x%08x\n", DEVNAME(sc), 686 letoh32(sie->msg_context)); 687 688 printf("%s: scsi_status: 0x%02x scsi_state: 0x%02x " 689 "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status, 690 sie->scsi_state, letoh16(sie->ioc_status)); 691 692 printf("%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 693 letoh32(sie->ioc_loginfo)); 694 695 printf("%s: transfer_count: %d\n", DEVNAME(sc), 696 letoh32(sie->transfer_count)); 697 698 printf("%s: sense_count: %d\n", DEVNAME(sc), 699 letoh32(sie->sense_count)); 700 701 printf("%s: response_info: 0x%08x\n", DEVNAME(sc), 702 letoh32(sie->response_info)); 703 704 printf("%s: tag: 0x%04x\n", DEVNAME(sc), letoh16(sie->tag)); 705 } 706 #endif /* MPI_DEBUG */ 707 708 xs->status = sie->scsi_status; 709 switch (letoh16(sie->ioc_status)) { 710 case MPI_IOCSTATUS_SCSI_DATA_OVERRUN: 711 xs->error = XS_DRIVER_STUFFUP; 712 break; 713 714 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: 715 /* 716 * Yikes! Tagged queue full comes through this path! 717 * 718 * So we'll change it to a status error and anything 719 * that returns status should probably be a status 720 * error as well. 721 */ 722 xs->resid = xs->datalen - letoh32(sie->transfer_count); 723 if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_NO_SCSI_STATUS) { 724 xs->error = XS_DRIVER_STUFFUP; 725 break; 726 } 727 /* FALLTHROUGH */ 728 case MPI_IOCSTATUS_SUCCESS: 729 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: 730 switch (xs->status) { 731 case SCSI_OK: 732 xs->resid = 0; 733 break; 734 735 case SCSI_CHECK: 736 xs->error = XS_SENSE; 737 break; 738 739 case SCSI_BUSY: 740 xs->error = XS_BUSY; 741 break; 742 743 case SCSI_QUEUE_FULL: 744 xs->error = XS_TIMEOUT; 745 xs->retries++; 746 break; 747 default: 748 printf("%s: invalid status code %d\n", xs->status); 749 xs->error = XS_DRIVER_STUFFUP; 750 break; 751 } 752 break; 753 754 case MPI_IOCSTATUS_BUSY: 755 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: 756 xs->error = XS_BUSY; 757 break; 758 759 case MPI_IOCSTATUS_SCSI_INVALID_BUS: 760 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: 761 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 762 xs->error = XS_SELTIMEOUT; 763 break; 764 765 case MPI_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: 766 xs->error = XS_DRIVER_STUFFUP; 767 break; 768 769 case MPI_IOCSTATUS_SCSI_TASK_TERMINATED: 770 xs->error = XS_DRIVER_STUFFUP; 771 break; 772 773 case MPI_IOCSTATUS_SCSI_TASK_MGMT_FAILED: 774 /* XXX */ 775 xs->error = XS_DRIVER_STUFFUP; 776 break; 777 778 case MPI_IOCSTATUS_SCSI_IOC_TERMINATED: 779 /* XXX */ 780 xs->error = XS_DRIVER_STUFFUP; 781 break; 782 783 case MPI_IOCSTATUS_SCSI_EXT_TERMINATED: 784 /* XXX This is a bus-reset */ 785 xs->error = XS_DRIVER_STUFFUP; 786 break; 787 788 default: 789 /* XXX unrecognized HBA error */ 790 xs->error = XS_DRIVER_STUFFUP; 791 break; 792 } 793 794 if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_AUTOSENSE_VALID) { 795 bcopy(&mcb->mcb_sense, &xs->sense, sizeof(xs->sense)); 796 } else if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_AUTOSENSE_FAILED) { 797 /* This will cause the scsi layer to issue a REQUEST SENSE */ 798 if (xs->status == SCSI_CHECK) 799 xs->error = XS_BUSY; 800 } 801 802 DPRINTFN(10, "%s: xs error: 0x%02x len: %d\n", DEVNAME(sc), 803 xs->error, xs->status); 804 mpi_push_reply(sc, ccb->ccb_reply_dva); 805 mpi_put_ccb(sc, ccb); 806 scsi_done(xs); 807 } 808 809 void 810 mpi_timeout_xs(void *arg) 811 { 812 /* XXX */ 813 } 814 815 int 816 mpi_load_xs(struct mpi_ccb *ccb) 817 { 818 struct mpi_softc *sc = ccb->ccb_sc; 819 struct scsi_xfer *xs = ccb->ccb_xs; 820 struct mpi_ccb_bundle *mcb = ccb->ccb_cmd; 821 struct mpi_msg_scsi_io *io = &mcb->mcb_io; 822 struct mpi_sge *sge, *nsge = &mcb->mcb_sgl[0]; 823 struct mpi_sge *ce = NULL, *nce; 824 u_int64_t ce_dva; 825 bus_dmamap_t dmap = ccb->ccb_dmamap; 826 u_int32_t addr, flags; 827 int i, error; 828 829 if (xs->datalen == 0) { 830 nsge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | 831 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL); 832 return (0); 833 } 834 835 error = bus_dmamap_load(sc->sc_dmat, dmap, 836 xs->data, xs->datalen, NULL, 837 (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 838 if (error) { 839 printf("%s: error %d loading dmamap\n", DEVNAME(sc), error); 840 return (1); 841 } 842 843 flags = MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64; 844 if (xs->flags & SCSI_DATA_OUT) 845 flags |= MPI_SGE_FL_DIR_OUT; 846 847 if (dmap->dm_nsegs > sc->sc_first_sgl_len) { 848 ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1]; 849 io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4; 850 } 851 852 for (i = 0; i < dmap->dm_nsegs; i++) { 853 854 if (nsge == ce) { 855 nsge++; 856 sge->sg_hdr |= htole32(MPI_SGE_FL_LAST); 857 858 DPRINTFN(5, "%s: - 0x%08x 0x%08x 0x%08x\n", 859 DEVNAME(sc), sge->sg_hdr, 860 sge->sg_hi_addr, sge->sg_lo_addr); 861 862 if ((dmap->dm_nsegs - i) > sc->sc_maxchdepth) { 863 nce = &nsge[sc->sc_maxchdepth - 1]; 864 addr = ((u_int8_t *)nce - (u_int8_t *)ce) / 4; 865 addr = addr << 16 | 866 sizeof(struct mpi_sge) * sc->sc_maxchdepth; 867 } else { 868 nce = NULL; 869 addr = sizeof(struct mpi_sge) * 870 (dmap->dm_nsegs - i); 871 } 872 873 ce->sg_hdr = htole32(MPI_SGE_FL_TYPE_CHAIN | 874 MPI_SGE_FL_SIZE_64 | addr); 875 876 ce_dva = MPI_DMA_DVA(sc->sc_requests) + ccb->ccb_offset; 877 ce_dva += (u_int8_t *)nsge - (u_int8_t *)mcb; 878 879 addr = (u_int32_t)(ce_dva >> 32); 880 ce->sg_hi_addr = htole32(addr); 881 addr = (u_int32_t)ce_dva; 882 ce->sg_lo_addr = htole32(addr); 883 884 DPRINTFN(5, "%s: ce: 0x%08x 0x%08x 0x%08x\n", 885 DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr, 886 ce->sg_lo_addr); 887 888 ce = nce; 889 } 890 891 DPRINTFN(5, "%s: %d: %d 0x%016llx\n", DEVNAME(sc), 892 i, dmap->dm_segs[i].ds_len, 893 (unsigned long long)dmap->dm_segs[i].ds_addr); 894 895 sge = nsge; 896 897 sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len); 898 addr = (u_int32_t)((unsigned long long)dmap->dm_segs[i].ds_addr >> 32); 899 sge->sg_hi_addr = htole32(addr); 900 addr = (u_int32_t)dmap->dm_segs[i].ds_addr; 901 sge->sg_lo_addr = htole32(addr); 902 903 DPRINTFN(5, "%s: %d: 0x%08x 0x%08x 0x%08x\n", DEVNAME(sc), 904 i, sge->sg_hdr, sge->sg_hi_addr, sge->sg_lo_addr); 905 906 nsge = sge + 1; 907 } 908 909 /* terminate list */ 910 sge->sg_hdr |= htole32(MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | 911 MPI_SGE_FL_EOL); 912 913 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 914 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD : 915 BUS_DMASYNC_PREWRITE); 916 917 return (0); 918 } 919 920 void 921 mpi_minphys(struct buf *bp) 922 { 923 /* XXX */ 924 if (bp->b_bcount > MAXPHYS) 925 bp->b_bcount = MAXPHYS; 926 minphys(bp); 927 } 928 929 int 930 mpi_scsi_ioctl(struct scsi_link *a, u_long b, caddr_t c, int d, struct proc *e) 931 { 932 return (0); 933 } 934 935 u_int32_t 936 mpi_read(struct mpi_softc *sc, bus_size_t r) 937 { 938 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 939 BUS_SPACE_BARRIER_READ); 940 return (bus_space_read_4(sc->sc_iot, sc->sc_ioh, r)); 941 } 942 943 void 944 mpi_write(struct mpi_softc *sc, bus_size_t r, u_int32_t v) 945 { 946 bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v); 947 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 948 BUS_SPACE_BARRIER_WRITE); 949 } 950 951 int 952 mpi_wait_eq(struct mpi_softc *sc, bus_size_t r, u_int32_t mask, 953 u_int32_t target) 954 { 955 int i; 956 957 for (i = 0; i < 10000; i++) { 958 if ((mpi_read(sc, r) & mask) == target) 959 return (0); 960 delay(1000); 961 } 962 963 return (1); 964 } 965 966 int 967 mpi_wait_ne(struct mpi_softc *sc, bus_size_t r, u_int32_t mask, 968 u_int32_t target) 969 { 970 int i; 971 972 for (i = 0; i < 10000; i++) { 973 if ((mpi_read(sc, r) & mask) != target) 974 return (0); 975 delay(1000); 976 } 977 978 return (1); 979 } 980 981 int 982 mpi_init(struct mpi_softc *sc) 983 { 984 u_int32_t db; 985 int i; 986 987 /* spin until the IOC leaves the RESET state */ 988 if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE, 989 MPI_DOORBELL_STATE_RESET) != 0) { 990 DPRINTF("%s: %s timeout waiting to leave reset state\n", 991 DEVNAME(sc), __func__); 992 return (1); 993 } 994 995 /* check current ownership */ 996 db = mpi_read_db(sc); 997 if ((db & MPI_DOORBELL_WHOINIT) == MPI_DOORBELL_WHOINIT_PCIPEER) { 998 DPRINTF("%s: %s initialised by pci peer\n", DEVNAME(sc), 999 __func__); 1000 return (0); 1001 } 1002 1003 for (i = 0; i < 5; i++) { 1004 switch (db & MPI_DOORBELL_STATE) { 1005 case MPI_DOORBELL_STATE_READY: 1006 DPRINTF("%s: %s ioc is ready\n", DEVNAME(sc), 1007 __func__); 1008 return (0); 1009 1010 case MPI_DOORBELL_STATE_OPER: 1011 case MPI_DOORBELL_STATE_FAULT: 1012 DPRINTF("%s: %s ioc is being reset\n", DEVNAME(sc), 1013 __func__); 1014 if (mpi_reset_soft(sc) != 0) 1015 mpi_reset_hard(sc); 1016 break; 1017 1018 case MPI_DOORBELL_STATE_RESET: 1019 DPRINTF("%s: %s waiting to come out of reset\n", 1020 DEVNAME(sc), __func__); 1021 if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE, 1022 MPI_DOORBELL_STATE_RESET) != 0) 1023 return (1); 1024 break; 1025 } 1026 db = mpi_read_db(sc); 1027 } 1028 1029 return (1); 1030 } 1031 1032 int 1033 mpi_reset_soft(struct mpi_softc *sc) 1034 { 1035 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 1036 1037 if (mpi_read_db(sc) & MPI_DOORBELL_INUSE) 1038 return (1); 1039 1040 mpi_write_db(sc, 1041 MPI_DOORBELL_FUNCTION(MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)); 1042 if (mpi_wait_eq(sc, MPI_INTR_STATUS, 1043 MPI_INTR_STATUS_IOCDOORBELL, 0) != 0) 1044 return (1); 1045 1046 if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE, 1047 MPI_DOORBELL_STATE_READY) != 0) 1048 return (1); 1049 1050 return (0); 1051 } 1052 1053 int 1054 mpi_reset_hard(struct mpi_softc *sc) 1055 { 1056 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 1057 1058 /* enable diagnostic register */ 1059 mpi_write(sc, MPI_WRITESEQ, 0xff); 1060 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_1); 1061 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_2); 1062 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_3); 1063 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_4); 1064 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_5); 1065 1066 /* reset ioc */ 1067 mpi_write(sc, MPI_HOSTDIAG, MPI_HOSTDIAG_RESET_ADAPTER); 1068 1069 delay(10000); 1070 1071 /* disable diagnostic register */ 1072 mpi_write(sc, MPI_WRITESEQ, 0xff); 1073 1074 /* restore pci bits? */ 1075 1076 /* firmware bits? */ 1077 return (0); 1078 } 1079 1080 int 1081 mpi_handshake_send(struct mpi_softc *sc, void *buf, size_t dwords) 1082 { 1083 u_int32_t *query = buf; 1084 int i; 1085 1086 /* make sure the doorbell is not in use. */ 1087 if (mpi_read_db(sc) & MPI_DOORBELL_INUSE) 1088 return (1); 1089 1090 /* clear pending doorbell interrupts */ 1091 if (mpi_read_intr(sc) & MPI_INTR_STATUS_DOORBELL) 1092 mpi_write_intr(sc, 0); 1093 1094 /* 1095 * first write the doorbell with the handshake function and the 1096 * dword count. 1097 */ 1098 mpi_write_db(sc, MPI_DOORBELL_FUNCTION(MPI_FUNCTION_HANDSHAKE) | 1099 MPI_DOORBELL_DWORDS(dwords)); 1100 1101 /* 1102 * the doorbell used bit will be set because a doorbell function has 1103 * started. Wait for the interrupt and then ack it. 1104 */ 1105 if (mpi_wait_db_int(sc) != 0) 1106 return (1); 1107 mpi_write_intr(sc, 0); 1108 1109 /* poll for the acknowledgement. */ 1110 if (mpi_wait_db_ack(sc) != 0) 1111 return (1); 1112 1113 /* write the query through the doorbell. */ 1114 for (i = 0; i < dwords; i++) { 1115 mpi_write_db(sc, htole32(query[i])); 1116 if (mpi_wait_db_ack(sc) != 0) 1117 return (1); 1118 } 1119 1120 return (0); 1121 } 1122 1123 int 1124 mpi_handshake_recv_dword(struct mpi_softc *sc, u_int32_t *dword) 1125 { 1126 u_int16_t *words = (u_int16_t *)dword; 1127 int i; 1128 1129 for (i = 0; i < 2; i++) { 1130 if (mpi_wait_db_int(sc) != 0) 1131 return (1); 1132 words[i] = letoh16(mpi_read_db(sc) & MPI_DOORBELL_DATA_MASK); 1133 mpi_write_intr(sc, 0); 1134 } 1135 1136 return (0); 1137 } 1138 1139 int 1140 mpi_handshake_recv(struct mpi_softc *sc, void *buf, size_t dwords) 1141 { 1142 struct mpi_msg_reply *reply = buf; 1143 u_int32_t *dbuf = buf, dummy; 1144 int i; 1145 1146 /* get the first dword so we can read the length out of the header. */ 1147 if (mpi_handshake_recv_dword(sc, &dbuf[0]) != 0) 1148 return (1); 1149 1150 DPRINTFN(10, "%s: %s dwords: %d reply: %d\n", DEVNAME(sc), __func__, 1151 dwords, reply->msg_length); 1152 1153 /* 1154 * the total length, in dwords, is in the message length field of the 1155 * reply header. 1156 */ 1157 for (i = 1; i < MIN(dwords, reply->msg_length); i++) { 1158 if (mpi_handshake_recv_dword(sc, &dbuf[i]) != 0) 1159 return (1); 1160 } 1161 1162 /* if there's extra stuff to come off the ioc, discard it */ 1163 while (i++ < reply->msg_length) { 1164 if (mpi_handshake_recv_dword(sc, &dummy) != 0) 1165 return (1); 1166 DPRINTFN(10, "%s: %s dummy read: 0x%08x\n", DEVNAME(sc), 1167 __func__, dummy); 1168 } 1169 1170 /* wait for the doorbell used bit to be reset and clear the intr */ 1171 if (mpi_wait_db_int(sc) != 0) 1172 return (1); 1173 mpi_write_intr(sc, 0); 1174 1175 return (0); 1176 } 1177 1178 void 1179 mpi_empty_done(struct mpi_ccb *ccb) 1180 { 1181 /* nothing to do */ 1182 } 1183 1184 int 1185 mpi_iocfacts(struct mpi_softc *sc) 1186 { 1187 struct mpi_msg_iocfacts_request ifq; 1188 struct mpi_msg_iocfacts_reply ifp; 1189 1190 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 1191 1192 bzero(&ifq, sizeof(ifq)); 1193 bzero(&ifp, sizeof(ifp)); 1194 1195 ifq.function = MPI_FUNCTION_IOC_FACTS; 1196 ifq.chain_offset = 0; 1197 ifq.msg_flags = 0; 1198 ifq.msg_context = htole32(0xdeadbeef); 1199 1200 if (mpi_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) { 1201 DPRINTF("%s: %s send failed\n", DEVNAME(sc), __func__); 1202 return (1); 1203 } 1204 1205 if (mpi_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) { 1206 DPRINTF("%s: %s recv failed\n", DEVNAME(sc), __func__); 1207 return (1); 1208 } 1209 1210 #ifdef MPI_DEBUG 1211 if (mpidebug) { 1212 printf("%s: func: 0x%02x len: %d msgver: %d.%d\n", 1213 DEVNAME(sc), ifp.function, ifp.msg_length, 1214 ifp.msg_version_maj, ifp.msg_version_min); 1215 1216 printf("%s: msgflags: 0x%02x iocnumber: 0x%02x " 1217 "hdrver: %d.%d\n", DEVNAME(sc), ifp.msg_flags, 1218 ifp.ioc_number, ifp.header_version_maj, 1219 ifp.header_version_min); 1220 1221 printf("%s: message context: 0x%08x\n", DEVNAME(sc), 1222 letoh32(ifp.msg_context)); 1223 1224 printf("%s: iocstatus: 0x%04x ioexcept: 0x%04x\n", 1225 DEVNAME(sc), letoh16(ifp.ioc_status), 1226 letoh16(ifp.ioc_exceptions)); 1227 1228 printf("%s: iocloginfo: 0x%08x\n", DEVNAME(sc), 1229 letoh32(ifp.ioc_loginfo)); 1230 1231 printf("%s: flags: 0x%02x blocksize: %d whoinit: 0x%02x " 1232 "maxchdepth: %d\n", DEVNAME(sc), ifp.flags, 1233 ifp.block_size, ifp.whoinit, ifp.max_chain_depth); 1234 1235 printf("%s: reqfrsize: %d replyqdepth: %d\n", DEVNAME(sc), 1236 letoh16(ifp.request_frame_size), 1237 letoh16(ifp.reply_queue_depth)); 1238 1239 printf("%s: productid: 0x%04x\n", DEVNAME(sc), 1240 letoh16(ifp.product_id)); 1241 1242 printf("%s: hostmfahiaddr: 0x%08x\n", DEVNAME(sc), 1243 letoh32(ifp.current_host_mfa_hi_addr)); 1244 1245 printf("%s: event_state: 0x%02x number_of_ports: %d " 1246 "global_credits: %d\n", 1247 DEVNAME(sc), ifp.event_state, ifp.number_of_ports, 1248 letoh16(ifp.global_credits)); 1249 1250 printf("%s: sensebufhiaddr: 0x%08x\n", DEVNAME(sc), 1251 letoh32(ifp.current_sense_buffer_hi_addr)); 1252 1253 printf("%s: maxbus: %d maxdev: %d replyfrsize: %d\n", 1254 DEVNAME(sc), ifp.max_buses, ifp.max_devices, 1255 letoh16(ifp.current_reply_frame_size)); 1256 1257 printf("%s: fw_image_size: %d\n", DEVNAME(sc), 1258 letoh32(ifp.fw_image_size)); 1259 1260 printf("%s: ioc_capabilities: 0x%08x\n", DEVNAME(sc), 1261 letoh32(ifp.ioc_capabilities)); 1262 1263 printf("%s: fw_version: %d.%d fw_version_unit: 0x%02x " 1264 "fw_version_dev: 0x%02x\n", DEVNAME(sc), 1265 ifp.fw_version_maj, ifp.fw_version_min, 1266 ifp.fw_version_unit, ifp.fw_version_dev); 1267 1268 printf("%s: hi_priority_queue_depth: 0x%04x\n", DEVNAME(sc), 1269 letoh16(ifp.hi_priority_queue_depth)); 1270 1271 printf("%s: host_page_buffer_sge: hdr: 0x%08x " 1272 "addr 0x%08x %08x\n", DEVNAME(sc), 1273 letoh32(ifp.host_page_buffer_sge.sg_hdr), 1274 letoh32(ifp.host_page_buffer_sge.sg_hi_addr), 1275 letoh32(ifp.host_page_buffer_sge.sg_lo_addr)); 1276 } 1277 #endif /* MPI_DEBUG */ 1278 1279 sc->sc_maxcmds = letoh16(ifp.global_credits); 1280 sc->sc_buswidth = (ifp.max_devices == 0) ? 256 : ifp.max_devices; 1281 sc->sc_maxchdepth = ifp.max_chain_depth; 1282 1283 /* 1284 * you can fit sg elements on the end of the io cmd if they fit in the 1285 * request frame size. 1286 */ 1287 sc->sc_first_sgl_len = ((letoh16(ifp.request_frame_size) * 4) - 1288 sizeof(struct mpi_msg_scsi_io)) / sizeof(struct mpi_sge); 1289 DPRINTF("%s: first sgl len: %d\n", DEVNAME(sc), 1290 sc->sc_first_sgl_len); 1291 1292 /* the sgl tailing the io cmd loses an entry to the chain element. */ 1293 sc->sc_max_sgl_len = MPI_MAX_SGL - 1; 1294 /* the sgl chains lose an entry for each chain element */ 1295 sc->sc_max_sgl_len -= (MPI_MAX_SGL - sc->sc_first_sgl_len) / 1296 sc->sc_maxchdepth; 1297 DPRINTF("%s: max sgl len: %d\n", DEVNAME(sc), sc->sc_max_sgl_len); 1298 1299 return (0); 1300 } 1301 1302 int 1303 mpi_iocinit(struct mpi_softc *sc) 1304 { 1305 struct mpi_msg_iocinit_request iiq; 1306 struct mpi_msg_iocinit_reply iip; 1307 u_int32_t hi_addr; 1308 1309 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 1310 1311 bzero(&iiq, sizeof(iiq)); 1312 bzero(&iip, sizeof(iip)); 1313 1314 iiq.function = MPI_FUNCTION_IOC_INIT; 1315 iiq.whoinit = MPI_WHOINIT_HOST_DRIVER; 1316 1317 iiq.max_devices = (sc->sc_buswidth == 256) ? 0 : sc->sc_buswidth; 1318 iiq.max_buses = 1; 1319 1320 iiq.msg_context = htole32(0xd00fd00f); 1321 1322 iiq.reply_frame_size = htole16(MPI_REPLY_SIZE); 1323 1324 hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_requests) >> 32); 1325 iiq.host_mfa_hi_addr = htole32(hi_addr); 1326 iiq.sense_buffer_hi_addr = htole32(hi_addr); 1327 1328 hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_replies) >> 32); 1329 iiq.reply_fifo_host_signalling_addr = htole32(hi_addr); 1330 1331 iiq.msg_version_maj = 0x01; 1332 iiq.msg_version_min = 0x02; 1333 1334 iiq.hdr_version_unit = 0x0d; 1335 iiq.hdr_version_dev = 0x00; 1336 1337 if (mpi_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) { 1338 DPRINTF("%s: %s send failed\n", DEVNAME(sc), __func__); 1339 return (1); 1340 } 1341 1342 if (mpi_handshake_recv(sc, &iip, dwordsof(iip)) != 0) { 1343 DPRINTF("%s: %s recv failed\n", DEVNAME(sc), __func__); 1344 return (1); 1345 } 1346 1347 #ifdef MPI_DEBUG 1348 if (mpidebug) { 1349 printf("%s: function: 0x%02x msg_length: %d " 1350 "whoinit: 0x%02x\n", DEVNAME(sc), iip.function, 1351 iip.msg_length, iip.whoinit); 1352 1353 printf("%s: msg_flags: 0x%02x max_buses: %d max_devices: %d " 1354 "flags: 0x%02x\n", DEVNAME(sc), iip.msg_flags, 1355 iip.max_buses, iip.max_devices, iip.flags); 1356 1357 printf("%s: msg_context: 0x%08x\n", DEVNAME(sc), 1358 letoh32(iip.msg_context)); 1359 1360 printf("%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1361 letoh16(iip.ioc_status)); 1362 1363 printf("%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1364 letoh32(iip.ioc_loginfo)); 1365 } 1366 #endif /* MPI_DEBUG */ 1367 1368 return (0); 1369 } 1370 1371 int 1372 mpi_portfacts(struct mpi_softc *sc) 1373 { 1374 struct mpi_ccb *ccb; 1375 struct mpi_msg_portfacts_request *pfq; 1376 struct mpi_msg_portfacts_reply *pfp; 1377 int s; 1378 1379 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 1380 1381 s = splbio(); 1382 ccb = mpi_get_ccb(sc); 1383 splx(s); 1384 if (ccb == NULL) { 1385 DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__); 1386 return (1); 1387 } 1388 1389 ccb->ccb_done = mpi_empty_done; 1390 pfq = ccb->ccb_cmd; 1391 1392 pfq->function = MPI_FUNCTION_PORT_FACTS; 1393 pfq->chain_offset = 0; 1394 pfq->msg_flags = 0; 1395 pfq->port_number = 0; 1396 pfq->msg_context = htole32(ccb->ccb_id); 1397 1398 if (mpi_poll(sc, ccb, 50000) != 0) { 1399 DPRINTF("%s: %s poll\n", DEVNAME(sc), __func__); 1400 return (1); 1401 } 1402 1403 pfp = ccb->ccb_reply; 1404 if (pfp == NULL) { 1405 DPRINTF("%s: empty portfacts reply\n", DEVNAME(sc)); 1406 return (1); 1407 } 1408 1409 #ifdef MPI_DEBUG 1410 if (mpidebug) { 1411 printf("%s: function: 0x%02x msg_length: %d\n", DEVNAME(sc), 1412 pfp->function, pfp->msg_length); 1413 1414 printf("%s: msg_flags: 0x%02x port_number: %d\n", DEVNAME(sc), 1415 pfp->msg_flags, pfp->port_number); 1416 1417 printf("%s: msg_context: 0x%08x\n", DEVNAME(sc), 1418 letoh32(pfp->msg_context)); 1419 1420 printf("%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1421 letoh16(pfp->ioc_status)); 1422 1423 printf("%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1424 letoh32(pfp->ioc_loginfo)); 1425 1426 printf("%s: max_devices: %d port_type: 0x%02x\n", DEVNAME(sc), 1427 letoh16(pfp->max_devices), pfp->port_type); 1428 1429 printf("%s: protocol_flags: 0x%04x port_scsi_id: %d\n", 1430 DEVNAME(sc), letoh16(pfp->protocol_flags), 1431 letoh16(pfp->port_scsi_id)); 1432 1433 printf("%s: max_persistent_ids: %d " 1434 "max_posted_cmd_buffers: %d\n", DEVNAME(sc), 1435 letoh16(pfp->max_persistent_ids), 1436 letoh16(pfp->max_posted_cmd_buffers)); 1437 1438 printf("%s: max_lan_buckets: %d\n", DEVNAME(sc), 1439 letoh16(pfp->max_lan_buckets)); 1440 } 1441 #endif /* MPI_DEBUG */ 1442 1443 sc->sc_porttype = pfp->port_type; 1444 sc->sc_target = letoh16(pfp->port_scsi_id); 1445 1446 mpi_push_reply(sc, ccb->ccb_reply_dva); 1447 mpi_put_ccb(sc, ccb); 1448 1449 return (0); 1450 } 1451 1452 int 1453 mpi_eventnotify(struct mpi_softc *sc) 1454 { 1455 struct mpi_ccb *ccb; 1456 struct mpi_msg_event_request *enq; 1457 int s; 1458 1459 s = splbio(); 1460 ccb = mpi_get_ccb(sc); 1461 splx(s); 1462 if (ccb == NULL) { 1463 DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__); 1464 return (1); 1465 } 1466 1467 ccb->ccb_done = mpi_eventnotify_done; 1468 enq = ccb->ccb_cmd; 1469 1470 enq->function = MPI_FUNCTION_EVENT_NOTIFICATION; 1471 enq->chain_offset = 0; 1472 enq->ev_switch = 1; 1473 enq->msg_context = htole32(ccb->ccb_id); 1474 1475 mpi_start(sc, ccb); 1476 1477 return (0); 1478 } 1479 1480 void 1481 mpi_eventnotify_done(struct mpi_ccb *ccb) 1482 { 1483 struct mpi_softc *sc = ccb->ccb_sc; 1484 struct mpi_msg_event_reply *enp = ccb->ccb_reply; 1485 u_int32_t *data; 1486 int i; 1487 1488 printf("%s: %s\n", DEVNAME(sc), __func__); 1489 1490 printf("%s: function: 0x%02x msg_length: %d data_length: %d\n", 1491 DEVNAME(sc), enp->function, enp->msg_length, 1492 letoh16(enp->data_length)); 1493 1494 printf("%s: ack_required: %d msg_flags 0x%02x\n", DEVNAME(sc), 1495 enp->msg_flags, enp->msg_flags); 1496 1497 printf("%s: msg_context: 0x%08x\n", DEVNAME(sc), 1498 letoh32(enp->msg_context)); 1499 1500 printf("%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1501 letoh16(enp->ioc_status)); 1502 1503 printf("%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1504 letoh32(enp->ioc_loginfo)); 1505 1506 data = ccb->ccb_reply; 1507 data += dwordsof(struct mpi_msg_event_reply); 1508 for (i = 0; i < letoh16(enp->data_length); i++) { 1509 printf("%s: data[%d]: 0x%08x\n", DEVNAME(sc), i, data[i]); 1510 } 1511 } 1512 1513 int 1514 mpi_portenable(struct mpi_softc *sc) 1515 { 1516 struct mpi_ccb *ccb; 1517 struct mpi_msg_portenable_request *peq; 1518 struct mpi_msg_portenable_repy *pep; 1519 int s; 1520 1521 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 1522 1523 s = splbio(); 1524 ccb = mpi_get_ccb(sc); 1525 splx(s); 1526 if (ccb == NULL) { 1527 DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__); 1528 return (1); 1529 } 1530 1531 ccb->ccb_done = mpi_empty_done; 1532 peq = ccb->ccb_cmd; 1533 1534 peq->function = MPI_FUNCTION_PORT_ENABLE; 1535 peq->port_number = 0; 1536 peq->msg_context = htole32(ccb->ccb_id); 1537 1538 if (mpi_poll(sc, ccb, 50000) != 0) { 1539 DPRINTF("%s: %s poll\n", DEVNAME(sc), __func__); 1540 return (1); 1541 } 1542 1543 pep = ccb->ccb_reply; 1544 if (pep == NULL) { 1545 DPRINTF("%s: empty portenable reply\n", DEVNAME(sc)); 1546 return (1); 1547 } 1548 1549 mpi_push_reply(sc, ccb->ccb_reply_dva); 1550 mpi_put_ccb(sc, ccb); 1551 1552 return (0); 1553 } 1554 1555 int 1556 mpi_cfg_hdr(struct mpi_softc *sc, u_int8_t type, u_int8_t number, 1557 u_int32_t address, struct mpi_cfg_hdr *hdr) 1558 { 1559 struct mpi_ccb *ccb; 1560 struct mpi_msg_config_request *cq; 1561 struct mpi_msg_config_reply *cp; 1562 int s; 1563 1564 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 1565 1566 s = splbio(); 1567 ccb = mpi_get_ccb(sc); 1568 splx(s); 1569 if (ccb == NULL) { 1570 DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__); 1571 return (1); 1572 } 1573 1574 ccb->ccb_done = mpi_empty_done; 1575 cq = ccb->ccb_cmd; 1576 1577 cq->function = MPI_FUNCTION_CONFIG; 1578 cq->msg_context = htole32(ccb->ccb_id); 1579 1580 cq->action = MPI_CONFIG_REQ_ACTION_PAGE_HEADER; 1581 1582 cq->config_header.page_number = number; 1583 cq->config_header.page_type = type; 1584 cq->page_address = htole32(address); 1585 cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | 1586 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL); 1587 1588 if (mpi_poll(sc, ccb, 50000) != 0) { 1589 DPRINTF("%s: %s poll\n", DEVNAME(sc), __func__); 1590 return (1); 1591 } 1592 1593 cp = ccb->ccb_reply; 1594 if (cp == NULL) 1595 panic("%s: unable to fetch config header\n", DEVNAME(sc)); 1596 1597 #ifdef MPI_DEBUG 1598 if (mpidebug) { 1599 printf("%s: action: 0x%02x msg_length: %d function: 0x%02x\n", 1600 DEVNAME(sc), cp->action, cp->msg_length, cp->function); 1601 1602 printf("%s: ext_page_length: %d ext_page_type: 0x%02x " 1603 "msg_flags: 0x%02x\n", DEVNAME(sc), 1604 letoh16(cp->ext_page_length), cp->ext_page_type, 1605 cp->msg_flags); 1606 1607 printf("%s: msg_context: 0x%08x\n", DEVNAME(sc), 1608 letoh32(cp->msg_context)); 1609 1610 printf("%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1611 letoh16(cp->ioc_status)); 1612 1613 printf("%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1614 letoh32(cp->ioc_loginfo)); 1615 1616 printf("%s: page_version: 0x%02x page_length: %d " 1617 "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc), 1618 cp->config_header.page_version, 1619 cp->config_header.page_length, 1620 cp->config_header.page_number, 1621 cp->config_header.page_type); 1622 } 1623 #endif /* MPI_DEBUG */ 1624 1625 *hdr = cp->config_header; 1626 1627 mpi_push_reply(sc, ccb->ccb_reply_dva); 1628 mpi_put_ccb(sc, ccb); 1629 1630 return (0); 1631 } 1632 1633 int 1634 mpi_cfg_page(struct mpi_softc *sc, u_int32_t address, struct mpi_cfg_hdr *hdr, 1635 int read, void *page, size_t len) 1636 { 1637 struct mpi_ccb *ccb; 1638 struct mpi_msg_config_request *cq; 1639 struct mpi_msg_config_reply *cp; 1640 u_int64_t dva; 1641 char *kva; 1642 int s; 1643 1644 DPRINTF("%s: %s\n", DEVNAME(sc), __func__); 1645 1646 if (len > MPI_REQUEST_SIZE - sizeof(struct mpi_msg_config_request) || 1647 len < hdr->page_length * 4) 1648 return (1); 1649 1650 s = splbio(); 1651 ccb = mpi_get_ccb(sc); 1652 splx(s); 1653 if (ccb == NULL) { 1654 DPRINTF("%s: %s ccb_get\n", DEVNAME(sc), __func__); 1655 return (1); 1656 } 1657 1658 ccb->ccb_done = mpi_empty_done; 1659 cq = ccb->ccb_cmd; 1660 1661 cq->function = MPI_FUNCTION_CONFIG; 1662 cq->msg_context = htole32(ccb->ccb_id); 1663 1664 cq->action = (read ? MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT : 1665 MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT); 1666 1667 cq->config_header = *hdr; 1668 cq->config_header.page_type &= MPI_CONFIG_REQ_PAGE_TYPE_MASK; 1669 cq->page_address = htole32(address); 1670 cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | 1671 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL | len); 1672 1673 /* bounce the page via the request space to avoid more bus_dma games */ 1674 dva = MPI_DMA_DVA(sc->sc_requests) + ccb->ccb_offset + 1675 sizeof(struct mpi_msg_config_request); 1676 cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32)); 1677 cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva); 1678 1679 kva = MPI_DMA_KVA(sc->sc_requests); 1680 kva += ccb->ccb_offset + sizeof(struct mpi_msg_config_request); 1681 if (!read) 1682 bcopy(page, kva, len); 1683 1684 if (mpi_poll(sc, ccb, 50000) != 0) { 1685 DPRINTF("%s: %s poll\n", DEVNAME(sc), __func__); 1686 return (1); 1687 } 1688 1689 cp = ccb->ccb_reply; 1690 if (cp == NULL) { 1691 mpi_put_ccb(sc, ccb); 1692 return (1); 1693 } 1694 1695 #ifdef MPI_DEBUG 1696 if (mpidebug) { 1697 printf("%s: action: 0x%02x msg_length: %d function: 0x%02x\n", 1698 DEVNAME(sc), cp->action, cp->msg_length, cp->function); 1699 1700 printf("%s: ext_page_length: %d ext_page_type: 0x%02x " 1701 "msg_flags: 0x%02x\n", DEVNAME(sc), 1702 letoh16(cp->ext_page_length), cp->ext_page_type, 1703 cp->msg_flags); 1704 1705 printf("%s: msg_context: 0x%08x\n", DEVNAME(sc), 1706 letoh32(cp->msg_context)); 1707 1708 printf("%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1709 letoh16(cp->ioc_status)); 1710 1711 printf("%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1712 letoh32(cp->ioc_loginfo)); 1713 1714 printf("%s: page_version: 0x%02x page_length: %d " 1715 "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc), 1716 cp->config_header.page_version, 1717 cp->config_header.page_length, 1718 cp->config_header.page_number, 1719 cp->config_header.page_type); 1720 } 1721 #endif /* MPI_DEBUG */ 1722 1723 if (read) 1724 bcopy(kva, page, len); 1725 1726 mpi_push_reply(sc, ccb->ccb_reply_dva); 1727 mpi_put_ccb(sc, ccb); 1728 1729 return (0); 1730 } 1731