1 /* $OpenBSD: mpi.c,v 1.80 2006/11/28 12:54:12 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 uint32_t mpi_debug = 0 38 /* | MPI_D_CMD */ 39 /* | MPI_D_INTR */ 40 /* | MPI_D_MISC */ 41 /* | MPI_D_DMA */ 42 /* | MPI_D_IOCTL */ 43 /* | MPI_D_RW */ 44 /* | MPI_D_MEM */ 45 /* | MPI_D_CCB */ 46 /* | MPI_D_PPR */ 47 /* | MPI_D_RAID */ 48 /* | MPI_D_EVT */ 49 ; 50 #endif 51 52 struct cfdriver mpi_cd = { 53 NULL, "mpi", DV_DULL 54 }; 55 56 int mpi_scsi_cmd(struct scsi_xfer *); 57 void mpi_scsi_cmd_done(struct mpi_ccb *); 58 void mpi_minphys(struct buf *bp); 59 int mpi_scsi_ioctl(struct scsi_link *, u_long, caddr_t, 60 int, struct proc *); 61 62 struct scsi_adapter mpi_switch = { 63 mpi_scsi_cmd, mpi_minphys, NULL, NULL, mpi_scsi_ioctl 64 }; 65 66 struct scsi_device mpi_dev = { 67 NULL, NULL, NULL, NULL 68 }; 69 70 struct mpi_dmamem *mpi_dmamem_alloc(struct mpi_softc *, size_t); 71 void mpi_dmamem_free(struct mpi_softc *, 72 struct mpi_dmamem *); 73 int mpi_alloc_ccbs(struct mpi_softc *); 74 struct mpi_ccb *mpi_get_ccb(struct mpi_softc *); 75 void mpi_put_ccb(struct mpi_softc *, struct mpi_ccb *); 76 int mpi_alloc_replies(struct mpi_softc *); 77 void mpi_push_replies(struct mpi_softc *); 78 79 void mpi_start(struct mpi_softc *, struct mpi_ccb *); 80 int mpi_complete(struct mpi_softc *, struct mpi_ccb *, int); 81 int mpi_poll(struct mpi_softc *, struct mpi_ccb *, int); 82 int mpi_reply(struct mpi_softc *, u_int32_t); 83 84 void mpi_squash_ppr(struct mpi_softc *); 85 void mpi_run_ppr(struct mpi_softc *); 86 int mpi_ppr(struct mpi_softc *, struct scsi_link *, 87 struct mpi_cfg_raid_physdisk *, int, int, int); 88 int mpi_inq(struct mpi_softc *, u_int16_t, int); 89 90 void mpi_timeout_xs(void *); 91 int mpi_load_xs(struct mpi_ccb *); 92 93 u_int32_t mpi_read(struct mpi_softc *, bus_size_t); 94 void mpi_write(struct mpi_softc *, bus_size_t, u_int32_t); 95 int mpi_wait_eq(struct mpi_softc *, bus_size_t, u_int32_t, 96 u_int32_t); 97 int mpi_wait_ne(struct mpi_softc *, bus_size_t, u_int32_t, 98 u_int32_t); 99 100 int mpi_init(struct mpi_softc *); 101 int mpi_reset_soft(struct mpi_softc *); 102 int mpi_reset_hard(struct mpi_softc *); 103 104 int mpi_handshake_send(struct mpi_softc *, void *, size_t); 105 int mpi_handshake_recv_dword(struct mpi_softc *, 106 u_int32_t *); 107 int mpi_handshake_recv(struct mpi_softc *, void *, size_t); 108 109 void mpi_empty_done(struct mpi_ccb *); 110 111 int mpi_iocinit(struct mpi_softc *); 112 int mpi_iocfacts(struct mpi_softc *); 113 int mpi_portfacts(struct mpi_softc *); 114 int mpi_portenable(struct mpi_softc *); 115 void mpi_get_raid(struct mpi_softc *); 116 int mpi_fwupload(struct mpi_softc *); 117 118 int mpi_eventnotify(struct mpi_softc *); 119 void mpi_eventnotify_done(struct mpi_ccb *); 120 void mpi_eventack(struct mpi_softc *, 121 struct mpi_msg_event_reply *); 122 void mpi_eventack_done(struct mpi_ccb *); 123 void mpi_evt_sas(void *, void *); 124 125 int mpi_cfg_header(struct mpi_softc *, u_int8_t, u_int8_t, 126 u_int32_t, struct mpi_cfg_hdr *); 127 int mpi_cfg_page(struct mpi_softc *, u_int32_t, 128 struct mpi_cfg_hdr *, int, void *, size_t); 129 130 #define DEVNAME(s) ((s)->sc_dev.dv_xname) 131 132 #define dwordsof(s) (sizeof(s) / sizeof(u_int32_t)) 133 #define sizeofa(s) (sizeof(s) / sizeof((s)[0])) 134 135 #define mpi_read_db(s) mpi_read((s), MPI_DOORBELL) 136 #define mpi_write_db(s, v) mpi_write((s), MPI_DOORBELL, (v)) 137 #define mpi_read_intr(s) mpi_read((s), MPI_INTR_STATUS) 138 #define mpi_write_intr(s, v) mpi_write((s), MPI_INTR_STATUS, (v)) 139 #define mpi_pop_reply(s) mpi_read((s), MPI_REPLY_QUEUE) 140 #define mpi_push_reply(s, v) mpi_write((s), MPI_REPLY_QUEUE, (v)) 141 142 #define mpi_wait_db_int(s) mpi_wait_ne((s), MPI_INTR_STATUS, \ 143 MPI_INTR_STATUS_DOORBELL, 0) 144 #define mpi_wait_db_ack(s) mpi_wait_eq((s), MPI_INTR_STATUS, \ 145 MPI_INTR_STATUS_IOCDOORBELL, 0) 146 147 int 148 mpi_attach(struct mpi_softc *sc) 149 { 150 struct mpi_ccb *ccb; 151 152 printf("\n"); 153 154 /* disable interrupts */ 155 mpi_write(sc, MPI_INTR_MASK, 156 MPI_INTR_MASK_REPLY | MPI_INTR_MASK_DOORBELL); 157 158 if (mpi_init(sc) != 0) { 159 printf("%s: unable to initialise\n", DEVNAME(sc)); 160 return (1); 161 } 162 163 if (mpi_iocfacts(sc) != 0) { 164 printf("%s: unable to get iocfacts\n", DEVNAME(sc)); 165 return (1); 166 } 167 168 if (mpi_alloc_ccbs(sc) != 0) { 169 /* error already printed */ 170 return (1); 171 } 172 173 if (mpi_alloc_replies(sc) != 0) { 174 printf("%s: unable to allocate reply space\n", DEVNAME(sc)); 175 goto free_ccbs; 176 } 177 178 if (mpi_iocinit(sc) != 0) { 179 printf("%s: unable to send iocinit\n", DEVNAME(sc)); 180 goto free_ccbs; 181 } 182 183 /* spin until we're operational */ 184 if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE, 185 MPI_DOORBELL_STATE_OPER) != 0) { 186 printf("%s: state: 0x%08x\n", DEVNAME(sc), 187 mpi_read_db(sc) & MPI_DOORBELL_STATE); 188 printf("%s: operational state timeout\n", DEVNAME(sc)); 189 goto free_ccbs; 190 } 191 192 mpi_push_replies(sc); 193 194 if (mpi_portfacts(sc) != 0) { 195 printf("%s: unable to get portfacts\n", DEVNAME(sc)); 196 goto free_replies; 197 } 198 199 #ifdef notyet 200 if (mpi_eventnotify(sc) != 0) { 201 printf("%s: unable to get portfacts\n", DEVNAME(sc)); 202 goto free_replies; 203 } 204 #endif 205 206 if (mpi_portenable(sc) != 0) { 207 printf("%s: unable to enable port\n", DEVNAME(sc)); 208 goto free_replies; 209 } 210 211 if (mpi_fwupload(sc) != 0) { 212 printf("%s: unable to upload firmware\n", DEVNAME(sc)); 213 goto free_replies; 214 } 215 216 if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SCSI) 217 mpi_squash_ppr(sc); 218 219 /* we should be good to go now, attach scsibus */ 220 sc->sc_link.device = &mpi_dev; 221 sc->sc_link.adapter = &mpi_switch; 222 sc->sc_link.adapter_softc = sc; 223 sc->sc_link.adapter_target = sc->sc_target; 224 sc->sc_link.adapter_buswidth = sc->sc_buswidth; 225 sc->sc_link.openings = sc->sc_maxcmds / sc->sc_buswidth; 226 227 228 /* config_found() returns the scsibus we should attach to */ 229 sc->sc_scsibus = (struct scsibus_softc *) config_found(&sc->sc_dev, 230 &sc->sc_link, scsiprint); 231 232 /* get raid pages */ 233 mpi_get_raid(sc); 234 235 /* do domain validation */ 236 if (sc->sc_porttype == MPI_PORTFACTS_PORTTYPE_SCSI) 237 mpi_run_ppr(sc); 238 239 /* enable interrupts */ 240 mpi_write(sc, MPI_INTR_MASK, MPI_INTR_MASK_DOORBELL); 241 242 return (0); 243 244 free_replies: 245 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies), 246 0, PAGE_SIZE, BUS_DMASYNC_POSTREAD); 247 mpi_dmamem_free(sc, sc->sc_replies); 248 free_ccbs: 249 while ((ccb = mpi_get_ccb(sc)) != NULL) 250 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 251 mpi_dmamem_free(sc, sc->sc_requests); 252 free(sc->sc_ccbs, M_DEVBUF); 253 254 return(1); 255 } 256 257 void 258 mpi_squash_ppr(struct mpi_softc *sc) 259 { 260 struct mpi_cfg_hdr hdr; 261 struct mpi_cfg_spi_dev_pg1 page; 262 int i; 263 264 DNPRINTF(MPI_D_PPR, "%s: mpi_squash_ppr\n", DEVNAME(sc)); 265 266 for (i = 0; i < sc->sc_buswidth; i++) { 267 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 268 1, i, &hdr) != 0) 269 return; 270 271 if (mpi_cfg_page(sc, i, &hdr, 1, &page, sizeof(page)) != 0) 272 return; 273 274 DNPRINTF(MPI_D_PPR, "%s: target: %d req_params1: 0x%02x " 275 "req_offset: 0x%02x req_period: 0x%02x " 276 "req_params2: 0x%02x conf: 0x%08x\n", DEVNAME(sc), i, 277 page.req_params1, page.req_offset, page.req_period, 278 page.req_params2, letoh32(page.configuration)); 279 280 page.req_params1 = 0x0; 281 page.req_offset = 0x0; 282 page.req_period = 0x0; 283 page.req_params2 = 0x0; 284 page.configuration = htole32(0x0); 285 286 if (mpi_cfg_page(sc, i, &hdr, 0, &page, sizeof(page)) != 0) 287 return; 288 } 289 } 290 291 void 292 mpi_run_ppr(struct mpi_softc *sc) 293 { 294 struct mpi_cfg_hdr hdr; 295 struct mpi_cfg_spi_port_pg0 port_pg; 296 struct mpi_cfg_ioc_pg3 *physdisk_pg; 297 struct mpi_cfg_raid_physdisk *physdisk_list, *physdisk; 298 size_t pagelen; 299 struct scsi_link *link; 300 int i, tries; 301 302 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_PORT, 0, 0x0, 303 &hdr) != 0) { 304 DNPRINTF(MPI_D_PPR, "%s: mpi_run_ppr unable to fetch header\n", 305 DEVNAME(sc)); 306 return; 307 } 308 309 if (mpi_cfg_page(sc, 0x0, &hdr, 1, &port_pg, sizeof(port_pg)) != 0) { 310 DNPRINTF(MPI_D_PPR, "%s: mpi_run_ppr unable to fetch page\n", 311 DEVNAME(sc)); 312 return; 313 } 314 315 for (i = 0; i < sc->sc_buswidth; i++) { 316 link = sc->sc_scsibus->sc_link[i][0]; 317 if (link == NULL) 318 continue; 319 320 /* do not ppr volumes */ 321 if (link->flags & SDEV_VIRTUAL) 322 continue; 323 324 tries = 0; 325 while (mpi_ppr(sc, link, NULL, port_pg.min_period, 326 port_pg.max_offset, tries) == EAGAIN) 327 tries++; 328 } 329 330 if ((sc->sc_flags & MPI_F_RAID) == 0) 331 return; 332 333 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 3, 0x0, 334 &hdr) != 0) { 335 DNPRINTF(MPI_D_RAID|MPI_D_PPR, "%s: mpi_run_ppr unable to " 336 "fetch ioc pg 3 header\n", DEVNAME(sc)); 337 return; 338 } 339 340 pagelen = hdr.page_length * 4; /* dwords to bytes */ 341 physdisk_pg = malloc(pagelen, M_TEMP, M_WAITOK); 342 if (physdisk_pg == NULL) { 343 DNPRINTF(MPI_D_RAID|MPI_D_PPR, "%s: mpi_run_ppr unable to " 344 "allocate ioc pg 3\n", DEVNAME(sc)); 345 return; 346 } 347 physdisk_list = (struct mpi_cfg_raid_physdisk *)(physdisk_pg + 1); 348 349 if (mpi_cfg_page(sc, 0, &hdr, 1, physdisk_pg, pagelen) != 0) { 350 DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s: mpi_run_ppr unable to " 351 "fetch ioc page 3\n", DEVNAME(sc)); 352 goto out; 353 } 354 355 DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s: no_phys_disks: %d\n", DEVNAME(sc), 356 physdisk_pg->no_phys_disks); 357 358 for (i = 0; i < physdisk_pg->no_phys_disks; i++) { 359 physdisk = &physdisk_list[i]; 360 361 DNPRINTF(MPI_D_PPR|MPI_D_PPR, "%s: id: %d bus: %d ioc: %d " 362 "num: %d\n", DEVNAME(sc), physdisk->phys_disk_id, 363 physdisk->phys_disk_bus, physdisk->phys_disk_ioc, 364 physdisk->phys_disk_num); 365 366 if (physdisk->phys_disk_ioc != sc->sc_ioc_number) 367 continue; 368 369 tries = 0; 370 while (mpi_ppr(sc, NULL, physdisk, port_pg.min_period, 371 port_pg.max_offset, tries) == EAGAIN) 372 tries++; 373 } 374 375 out: 376 free(physdisk_pg, M_TEMP); 377 } 378 379 int 380 mpi_ppr(struct mpi_softc *sc, struct scsi_link *link, 381 struct mpi_cfg_raid_physdisk *physdisk, int period, int offset, int try) 382 { 383 struct mpi_cfg_hdr hdr0, hdr1; 384 struct mpi_cfg_spi_dev_pg0 pg0; 385 struct mpi_cfg_spi_dev_pg1 pg1; 386 u_int32_t address; 387 int id; 388 int raid = 0; 389 390 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr period: %d offset: %d try: %d " 391 "link quirks: 0x%x\n", DEVNAME(sc), period, offset, try, 392 link->quirks); 393 394 if (try >= 3) 395 return (EIO); 396 397 if (physdisk == NULL) { 398 if ((link->inqdata.device & SID_TYPE) == T_PROCESSOR) 399 return (EIO); 400 401 address = link->target; 402 id = link->target; 403 } else { 404 raid = 1; 405 address = (physdisk->phys_disk_bus << 8) | 406 (physdisk->phys_disk_id); 407 id = physdisk->phys_disk_num; 408 } 409 410 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 0, 411 address, &hdr0) != 0) { 412 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch header 0\n", 413 DEVNAME(sc)); 414 return (EIO); 415 } 416 417 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_SCSI_SPI_DEV, 1, 418 address, &hdr1) != 0) { 419 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch header 1\n", 420 DEVNAME(sc)); 421 return (EIO); 422 } 423 424 #ifdef MPI_DEBUG 425 if (mpi_cfg_page(sc, address, &hdr0, 1, &pg0, sizeof(pg0)) != 0) { 426 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch page 0\n", 427 DEVNAME(sc)); 428 return (EIO); 429 } 430 431 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 0 neg_params1: 0x%02x " 432 "neg_offset: %d neg_period: 0x%02x neg_params2: 0x%02x " 433 "info: 0x%08x\n", DEVNAME(sc), pg0.neg_params1, pg0.neg_offset, 434 pg0.neg_period, pg0.neg_params2, letoh32(pg0.information)); 435 #endif 436 437 if (mpi_cfg_page(sc, address, &hdr1, 1, &pg1, sizeof(pg1)) != 0) { 438 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to fetch page 1\n", 439 DEVNAME(sc)); 440 return (EIO); 441 } 442 443 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x " 444 "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x " 445 "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset, 446 pg1.req_period, pg1.req_params2, letoh32(pg1.configuration)); 447 448 pg1.req_params1 = 0; 449 pg1.req_offset = offset; 450 pg1.req_period = period; 451 pg1.req_params2 &= ~MPI_CFG_SPI_DEV_1_REQPARAMS_WIDTH; 452 453 if (raid || !(link->quirks & SDEV_NOSYNC)) { 454 pg1.req_params2 |= MPI_CFG_SPI_DEV_1_REQPARAMS_WIDTH_WIDE; 455 456 switch (try) { 457 case 0: /* U320 */ 458 break; 459 case 1: /* U160 */ 460 pg1.req_period = 0x09; 461 break; 462 case 2: /* U80 */ 463 pg1.req_period = 0x0a; 464 break; 465 } 466 467 if (pg1.req_period < 0x09) { 468 /* Ultra320: enable QAS & PACKETIZED */ 469 pg1.req_params1 |= MPI_CFG_SPI_DEV_1_REQPARAMS_QAS | 470 MPI_CFG_SPI_DEV_1_REQPARAMS_PACKETIZED; 471 } 472 if (pg1.req_period < 0xa) { 473 /* >= Ultra160: enable dual xfers */ 474 pg1.req_params1 |= 475 MPI_CFG_SPI_DEV_1_REQPARAMS_DUALXFERS; 476 } 477 } 478 479 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x " 480 "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x " 481 "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset, 482 pg1.req_period, pg1.req_params2, letoh32(pg1.configuration)); 483 484 if (mpi_cfg_page(sc, address, &hdr1, 0, &pg1, sizeof(pg1)) != 0) { 485 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to write page 1\n", 486 DEVNAME(sc)); 487 return (EIO); 488 } 489 490 if (mpi_cfg_page(sc, address, &hdr1, 1, &pg1, sizeof(pg1)) != 0) { 491 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to read page 1\n", 492 DEVNAME(sc)); 493 return (EIO); 494 } 495 496 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 1 req_params1: 0x%02x " 497 "req_offset: 0x%02x req_period: 0x%02x req_params2: 0x%02x " 498 "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset, 499 pg1.req_period, pg1.req_params2, letoh32(pg1.configuration)); 500 501 if (mpi_inq(sc, id, raid) != 0) { 502 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to do inquiry against " 503 "target %d\n", DEVNAME(sc), link->target); 504 return (EIO); 505 } 506 507 if (mpi_cfg_page(sc, address, &hdr0, 1, &pg0, sizeof(pg0)) != 0) { 508 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to read page 0 after " 509 "inquiry\n", DEVNAME(sc)); 510 return (EIO); 511 } 512 513 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr dev pg 0 neg_params1: 0x%02x " 514 "neg_offset: %d neg_period: 0x%02x neg_params2: 0x%02x " 515 "info: 0x%08x\n", DEVNAME(sc), pg0.neg_params1, pg0.neg_offset, 516 pg0.neg_period, pg0.neg_params2, letoh32(pg0.information)); 517 518 if (!(letoh32(pg0.information) & 0x07) && (try == 0)) { 519 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr U320 ppr rejected\n", 520 DEVNAME(sc)); 521 return (EAGAIN); 522 } 523 524 if ((((letoh32(pg0.information) >> 8) & 0xff) > 0x09) && (try == 1)) { 525 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr U160 ppr rejected\n", 526 DEVNAME(sc)); 527 return (EAGAIN); 528 } 529 530 if (letoh32(pg0.information) & 0x0e) { 531 DNPRINTF(MPI_D_PPR, "%s: mpi_ppr ppr rejected: %0x\n", 532 DEVNAME(sc), letoh32(pg0.information)); 533 return (EAGAIN); 534 } 535 536 switch(pg0.neg_period) { 537 case 0x08: 538 period = 160; 539 break; 540 case 0x09: 541 period = 80; 542 break; 543 case 0x0a: 544 period = 40; 545 break; 546 case 0x0b: 547 period = 20; 548 break; 549 case 0x0c: 550 period = 10; 551 break; 552 default: 553 period = 0; 554 break; 555 } 556 557 printf("%s: %s %d %s at %dMHz width %dbit offset %d " 558 "QAS %d DT %d IU %d\n", DEVNAME(sc), raid ? "phys disk" : "target", 559 id, period ? "Sync" : "Async", period, 560 (pg0.neg_params2 & MPI_CFG_SPI_DEV_0_NEGPARAMS_WIDTH_WIDE) ? 16 : 8, 561 pg0.neg_offset, 562 (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_QAS) ? 1 : 0, 563 (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_DUALXFERS) ? 1 : 0, 564 (pg0.neg_params1 & MPI_CFG_SPI_DEV_0_NEGPARAMS_PACKETIZED) ? 1 : 0); 565 566 return (0); 567 } 568 569 int 570 mpi_inq(struct mpi_softc *sc, u_int16_t target, int physdisk) 571 { 572 struct mpi_ccb *ccb; 573 struct scsi_inquiry inq; 574 struct { 575 struct mpi_msg_scsi_io io; 576 struct mpi_sge sge; 577 struct scsi_inquiry_data inqbuf; 578 struct scsi_sense_data sense; 579 } __packed *bundle; 580 struct mpi_msg_scsi_io *io; 581 struct mpi_sge *sge; 582 u_int64_t addr; 583 584 DNPRINTF(MPI_D_PPR, "%s: mpi_inq\n", DEVNAME(sc)); 585 586 bzero(&inq, sizeof(inq)); 587 inq.opcode = INQUIRY; 588 589 ccb = mpi_get_ccb(sc); 590 if (ccb == NULL) 591 return (1); 592 593 ccb->ccb_done = mpi_empty_done; 594 595 bundle = ccb->ccb_cmd; 596 io = &bundle->io; 597 sge = &bundle->sge; 598 599 io->function = physdisk ? MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : 600 MPI_FUNCTION_SCSI_IO_REQUEST; 601 /* 602 * bus is always 0 603 * io->bus = htole16(sc->sc_bus); 604 */ 605 io->target_id = target; 606 607 io->cdb_length = sizeof(inq); 608 io->sense_buf_len = sizeof(struct scsi_sense_data); 609 io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64; 610 611 io->msg_context = htole32(ccb->ccb_id); 612 613 /* 614 * always lun 0 615 * io->lun[0] = htobe16(link->lun); 616 */ 617 618 io->direction = MPI_SCSIIO_DIR_READ; 619 io->tagging = MPI_SCSIIO_ATTR_NO_DISCONNECT; 620 621 bcopy(&inq, io->cdb, sizeof(inq)); 622 623 io->data_length = htole32(sizeof(struct scsi_inquiry_data)); 624 625 io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva + 626 ((u_int8_t *)&bundle->sense - (u_int8_t *)bundle)); 627 628 sge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64 | 629 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL | 630 (u_int32_t)sizeof(inq)); 631 632 addr = ccb->ccb_cmd_dva + 633 ((u_int8_t *)&bundle->inqbuf - (u_int8_t *)bundle); 634 sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32)); 635 sge->sg_lo_addr = htole32((u_int32_t)addr); 636 637 if (mpi_poll(sc, ccb, 5000) != 0) 638 return (1); 639 640 if (ccb->ccb_rcb != NULL) 641 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 642 643 mpi_put_ccb(sc, ccb); 644 645 return (0); 646 } 647 648 void 649 mpi_detach(struct mpi_softc *sc) 650 { 651 652 } 653 654 int 655 mpi_intr(void *arg) 656 { 657 struct mpi_softc *sc = arg; 658 u_int32_t reg; 659 int rv = 0; 660 661 while ((reg = mpi_pop_reply(sc)) != 0xffffffff) { 662 mpi_reply(sc, reg); 663 rv = 1; 664 } 665 666 return (rv); 667 } 668 669 int 670 mpi_reply(struct mpi_softc *sc, u_int32_t reg) 671 { 672 struct mpi_ccb *ccb; 673 struct mpi_rcb *rcb = NULL; 674 struct mpi_msg_reply *reply = NULL; 675 u_int32_t reply_dva; 676 int id; 677 int i; 678 679 DNPRINTF(MPI_D_INTR, "%s: mpi_reply reg: 0x%08x\n", DEVNAME(sc), reg); 680 681 if (reg & MPI_REPLY_QUEUE_ADDRESS) { 682 bus_dmamap_sync(sc->sc_dmat, 683 MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE, 684 BUS_DMASYNC_POSTREAD); 685 686 reply_dva = (reg & MPI_REPLY_QUEUE_ADDRESS_MASK) << 1; 687 688 i = (reply_dva - (u_int32_t)MPI_DMA_DVA(sc->sc_replies)) / 689 MPI_REPLY_SIZE; 690 rcb = &sc->sc_rcbs[i]; 691 reply = rcb->rcb_reply; 692 693 id = letoh32(reply->msg_context); 694 695 bus_dmamap_sync(sc->sc_dmat, 696 MPI_DMA_MAP(sc->sc_replies), 0, PAGE_SIZE, 697 BUS_DMASYNC_PREREAD); 698 } else { 699 switch (reg & MPI_REPLY_QUEUE_TYPE_MASK) { 700 case MPI_REPLY_QUEUE_TYPE_INIT: 701 id = reg & MPI_REPLY_QUEUE_CONTEXT; 702 break; 703 704 default: 705 panic("%s: unsupported context reply\n", 706 DEVNAME(sc)); 707 } 708 } 709 710 DNPRINTF(MPI_D_INTR, "%s: mpi_reply id: %d reply: %p\n", 711 DEVNAME(sc), id, reply); 712 713 ccb = &sc->sc_ccbs[id]; 714 715 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests), 716 ccb->ccb_offset, MPI_REQUEST_SIZE, 717 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); 718 ccb->ccb_state = MPI_CCB_READY; 719 ccb->ccb_rcb = rcb; 720 721 ccb->ccb_done(ccb); 722 723 return (id); 724 } 725 726 struct mpi_dmamem * 727 mpi_dmamem_alloc(struct mpi_softc *sc, size_t size) 728 { 729 struct mpi_dmamem *mdm; 730 int nsegs; 731 732 mdm = malloc(sizeof(struct mpi_dmamem), M_DEVBUF, M_NOWAIT); 733 if (mdm == NULL) 734 return (NULL); 735 736 bzero(mdm, sizeof(struct mpi_dmamem)); 737 mdm->mdm_size = size; 738 739 if (bus_dmamap_create(sc->sc_dmat, size, 1, size, 0, 740 BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &mdm->mdm_map) != 0) 741 goto mdmfree; 742 743 if (bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0, &mdm->mdm_seg, 744 1, &nsegs, BUS_DMA_NOWAIT) != 0) 745 goto destroy; 746 747 if (bus_dmamem_map(sc->sc_dmat, &mdm->mdm_seg, nsegs, size, 748 &mdm->mdm_kva, BUS_DMA_NOWAIT) != 0) 749 goto free; 750 751 if (bus_dmamap_load(sc->sc_dmat, mdm->mdm_map, mdm->mdm_kva, size, 752 NULL, BUS_DMA_NOWAIT) != 0) 753 goto unmap; 754 755 bzero(mdm->mdm_kva, size); 756 757 DNPRINTF(MPI_D_MEM, "%s: mpi_dmamem_alloc size: %d mdm: %#x " 758 "map: %#x nsegs: %d segs: %#x kva: %x\n", 759 DEVNAME(sc), size, mdm->mdm_map, nsegs, mdm->mdm_seg, mdm->mdm_kva); 760 761 return (mdm); 762 763 unmap: 764 bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, size); 765 free: 766 bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1); 767 destroy: 768 bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map); 769 mdmfree: 770 free(mdm, M_DEVBUF); 771 772 return (NULL); 773 } 774 775 void 776 mpi_dmamem_free(struct mpi_softc *sc, struct mpi_dmamem *mdm) 777 { 778 DNPRINTF(MPI_D_MEM, "%s: mpi_dmamem_free %#x\n", DEVNAME(sc), mdm); 779 780 bus_dmamap_unload(sc->sc_dmat, mdm->mdm_map); 781 bus_dmamem_unmap(sc->sc_dmat, mdm->mdm_kva, mdm->mdm_size); 782 bus_dmamem_free(sc->sc_dmat, &mdm->mdm_seg, 1); 783 bus_dmamap_destroy(sc->sc_dmat, mdm->mdm_map); 784 free(mdm, M_DEVBUF); 785 } 786 787 int 788 mpi_alloc_ccbs(struct mpi_softc *sc) 789 { 790 struct mpi_ccb *ccb; 791 u_int8_t *cmd; 792 int i; 793 794 TAILQ_INIT(&sc->sc_ccb_free); 795 796 sc->sc_ccbs = malloc(sizeof(struct mpi_ccb) * sc->sc_maxcmds, 797 M_DEVBUF, M_WAITOK); 798 if (sc->sc_ccbs == NULL) { 799 printf("%s: unable to allocate ccbs\n", DEVNAME(sc)); 800 return (1); 801 } 802 bzero(sc->sc_ccbs, sizeof(struct mpi_ccb) * sc->sc_maxcmds); 803 804 sc->sc_requests = mpi_dmamem_alloc(sc, 805 MPI_REQUEST_SIZE * sc->sc_maxcmds); 806 if (sc->sc_requests == NULL) { 807 printf("%s: unable to allocate ccb dmamem\n", DEVNAME(sc)); 808 goto free_ccbs; 809 } 810 cmd = MPI_DMA_KVA(sc->sc_requests); 811 bzero(cmd, MPI_REQUEST_SIZE * sc->sc_maxcmds); 812 813 for (i = 0; i < sc->sc_maxcmds; i++) { 814 ccb = &sc->sc_ccbs[i]; 815 816 if (bus_dmamap_create(sc->sc_dmat, MAXPHYS, 817 sc->sc_max_sgl_len, MAXPHYS, 0, 0, 818 &ccb->ccb_dmamap) != 0) { 819 printf("%s: unable to create dma map\n", DEVNAME(sc)); 820 goto free_maps; 821 } 822 823 ccb->ccb_sc = sc; 824 ccb->ccb_id = i; 825 ccb->ccb_offset = MPI_REQUEST_SIZE * i; 826 827 ccb->ccb_cmd = &cmd[ccb->ccb_offset]; 828 ccb->ccb_cmd_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_requests) + 829 ccb->ccb_offset; 830 831 DNPRINTF(MPI_D_CCB, "%s: mpi_alloc_ccbs(%d) ccb: %#x map: %#x " 832 "sc: %#x id: %#x offs: %#x cmd: %#x dva: %#x\n", 833 DEVNAME(sc), i, ccb, ccb->ccb_dmamap, ccb->ccb_sc, 834 ccb->ccb_id, ccb->ccb_offset, ccb->ccb_cmd, 835 ccb->ccb_cmd_dva); 836 837 mpi_put_ccb(sc, ccb); 838 } 839 840 return (0); 841 842 free_maps: 843 while ((ccb = mpi_get_ccb(sc)) != NULL) 844 bus_dmamap_destroy(sc->sc_dmat, ccb->ccb_dmamap); 845 846 mpi_dmamem_free(sc, sc->sc_requests); 847 free_ccbs: 848 free(sc->sc_ccbs, M_DEVBUF); 849 850 return (1); 851 } 852 853 struct mpi_ccb * 854 mpi_get_ccb(struct mpi_softc *sc) 855 { 856 struct mpi_ccb *ccb; 857 858 ccb = TAILQ_FIRST(&sc->sc_ccb_free); 859 if (ccb == NULL) { 860 DNPRINTF(MPI_D_CCB, "%s: mpi_get_ccb == NULL\n", DEVNAME(sc)); 861 return (NULL); 862 } 863 864 TAILQ_REMOVE(&sc->sc_ccb_free, ccb, ccb_link); 865 866 ccb->ccb_state = MPI_CCB_READY; 867 868 DNPRINTF(MPI_D_CCB, "%s: mpi_get_ccb %#x\n", DEVNAME(sc), ccb); 869 870 return (ccb); 871 } 872 873 void 874 mpi_put_ccb(struct mpi_softc *sc, struct mpi_ccb *ccb) 875 { 876 DNPRINTF(MPI_D_CCB, "%s: mpi_put_ccb %#x\n", DEVNAME(sc), ccb); 877 878 ccb->ccb_state = MPI_CCB_FREE; 879 ccb->ccb_xs = NULL; 880 ccb->ccb_done = NULL; 881 bzero(ccb->ccb_cmd, MPI_REQUEST_SIZE); 882 TAILQ_INSERT_TAIL(&sc->sc_ccb_free, ccb, ccb_link); 883 } 884 885 int 886 mpi_alloc_replies(struct mpi_softc *sc) 887 { 888 DNPRINTF(MPI_D_MISC, "%s: mpi_alloc_replies\n", DEVNAME(sc)); 889 890 sc->sc_rcbs = malloc(MPI_REPLY_COUNT * sizeof(struct mpi_rcb), 891 M_DEVBUF, M_WAITOK); 892 if (sc->sc_rcbs == NULL) 893 return (1); 894 895 sc->sc_replies = mpi_dmamem_alloc(sc, PAGE_SIZE); 896 if (sc->sc_replies == NULL) { 897 free(sc->sc_rcbs, M_DEVBUF); 898 return (1); 899 } 900 901 return (0); 902 } 903 904 void 905 mpi_push_replies(struct mpi_softc *sc) 906 { 907 struct mpi_rcb *rcb; 908 char *kva = MPI_DMA_KVA(sc->sc_replies); 909 int i; 910 911 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_replies), 912 0, PAGE_SIZE, BUS_DMASYNC_PREREAD); 913 914 for (i = 0; i < MPI_REPLY_COUNT; i++) { 915 rcb = &sc->sc_rcbs[i]; 916 917 rcb->rcb_reply = kva + MPI_REPLY_SIZE * i; 918 rcb->rcb_reply_dva = (u_int32_t)MPI_DMA_DVA(sc->sc_replies) + 919 MPI_REPLY_SIZE * i; 920 mpi_push_reply(sc, rcb->rcb_reply_dva); 921 } 922 } 923 924 void 925 mpi_start(struct mpi_softc *sc, struct mpi_ccb *ccb) 926 { 927 DNPRINTF(MPI_D_RW, "%s: mpi_start %#x\n", DEVNAME(sc), 928 ccb->ccb_cmd_dva); 929 930 bus_dmamap_sync(sc->sc_dmat, MPI_DMA_MAP(sc->sc_requests), 931 ccb->ccb_offset, MPI_REQUEST_SIZE, 932 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); 933 934 ccb->ccb_state = MPI_CCB_QUEUED; 935 mpi_write(sc, MPI_REQ_QUEUE, ccb->ccb_cmd_dva); 936 } 937 938 int 939 mpi_complete(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout) 940 { 941 u_int32_t reg; 942 int id = -1; 943 944 DNPRINTF(MPI_D_INTR, "%s: mpi_complete timeout %d\n", DEVNAME(sc), 945 timeout); 946 947 do { 948 reg = mpi_pop_reply(sc); 949 if (reg == 0xffffffff) { 950 if (timeout-- == 0) 951 return (1); 952 953 delay(1000); 954 continue; 955 } 956 957 id = mpi_reply(sc, reg); 958 959 } while (ccb->ccb_id != id); 960 961 return (0); 962 } 963 964 int 965 mpi_poll(struct mpi_softc *sc, struct mpi_ccb *ccb, int timeout) 966 { 967 int error; 968 int s; 969 970 DNPRINTF(MPI_D_CMD, "%s: mpi_poll\n", DEVNAME(sc)); 971 972 s = splbio(); 973 mpi_start(sc, ccb); 974 error = mpi_complete(sc, ccb, timeout); 975 splx(s); 976 977 return (error); 978 } 979 980 int 981 mpi_scsi_cmd(struct scsi_xfer *xs) 982 { 983 struct scsi_link *link = xs->sc_link; 984 struct mpi_softc *sc = link->adapter_softc; 985 struct mpi_ccb *ccb; 986 struct mpi_ccb_bundle *mcb; 987 struct mpi_msg_scsi_io *io; 988 int s; 989 990 DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd\n", DEVNAME(sc)); 991 992 if (xs->cmdlen > MPI_CDB_LEN) { 993 DNPRINTF(MPI_D_CMD, "%s: CBD too big %d\n", 994 DEVNAME(sc), xs->cmdlen); 995 bzero(&xs->sense, sizeof(xs->sense)); 996 xs->sense.error_code = SSD_ERRCODE_VALID | 0x70; 997 xs->sense.flags = SKEY_ILLEGAL_REQUEST; 998 xs->sense.add_sense_code = 0x20; 999 xs->error = XS_SENSE; 1000 s = splbio(); 1001 scsi_done(xs); 1002 splx(s); 1003 return (COMPLETE); 1004 } 1005 1006 s = splbio(); 1007 ccb = mpi_get_ccb(sc); 1008 splx(s); 1009 if (ccb == NULL) { 1010 xs->error = XS_DRIVER_STUFFUP; 1011 s = splbio(); 1012 scsi_done(xs); 1013 splx(s); 1014 return (COMPLETE); 1015 } 1016 DNPRINTF(MPI_D_CMD, "%s: ccb_id: %d xs->flags: 0x%x\n", 1017 DEVNAME(sc), ccb->ccb_id, xs->flags); 1018 1019 ccb->ccb_xs = xs; 1020 ccb->ccb_done = mpi_scsi_cmd_done; 1021 1022 mcb = ccb->ccb_cmd; 1023 io = &mcb->mcb_io; 1024 1025 io->function = MPI_FUNCTION_SCSI_IO_REQUEST; 1026 /* 1027 * bus is always 0 1028 * io->bus = htole16(sc->sc_bus); 1029 */ 1030 io->target_id = link->target; 1031 1032 io->cdb_length = xs->cmdlen; 1033 io->sense_buf_len = sizeof(xs->sense); 1034 io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64; 1035 1036 io->msg_context = htole32(ccb->ccb_id); 1037 1038 io->lun[0] = htobe16(link->lun); 1039 1040 switch (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT)) { 1041 case SCSI_DATA_IN: 1042 io->direction = MPI_SCSIIO_DIR_READ; 1043 break; 1044 case SCSI_DATA_OUT: 1045 io->direction = MPI_SCSIIO_DIR_WRITE; 1046 break; 1047 default: 1048 io->direction = MPI_SCSIIO_DIR_NONE; 1049 break; 1050 } 1051 1052 if (link->quirks & SDEV_NOTAGS) 1053 io->tagging = MPI_SCSIIO_ATTR_UNTAGGED; 1054 else 1055 io->tagging = MPI_SCSIIO_ATTR_SIMPLE_Q; 1056 1057 bcopy(xs->cmd, io->cdb, xs->cmdlen); 1058 1059 io->data_length = htole32(xs->datalen); 1060 1061 io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva + 1062 ((u_int8_t *)&mcb->mcb_sense - (u_int8_t *)mcb)); 1063 1064 if (mpi_load_xs(ccb) != 0) { 1065 xs->error = XS_DRIVER_STUFFUP; 1066 s = splbio(); 1067 mpi_put_ccb(sc, ccb); 1068 scsi_done(xs); 1069 splx(s); 1070 return (COMPLETE); 1071 } 1072 1073 timeout_set(&xs->stimeout, mpi_timeout_xs, ccb); 1074 1075 if (xs->flags & SCSI_POLL) { 1076 if (mpi_poll(sc, ccb, xs->timeout) != 0) 1077 xs->error = XS_DRIVER_STUFFUP; 1078 return (COMPLETE); 1079 } 1080 1081 s = splbio(); 1082 mpi_start(sc, ccb); 1083 splx(s); 1084 return (SUCCESSFULLY_QUEUED); 1085 } 1086 1087 void 1088 mpi_scsi_cmd_done(struct mpi_ccb *ccb) 1089 { 1090 struct mpi_softc *sc = ccb->ccb_sc; 1091 struct scsi_xfer *xs = ccb->ccb_xs; 1092 struct mpi_ccb_bundle *mcb = ccb->ccb_cmd; 1093 bus_dmamap_t dmap = ccb->ccb_dmamap; 1094 struct mpi_msg_scsi_io_error *sie; 1095 1096 if (xs->datalen != 0) { 1097 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 1098 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_POSTREAD : 1099 BUS_DMASYNC_POSTWRITE); 1100 1101 bus_dmamap_unload(sc->sc_dmat, dmap); 1102 } 1103 1104 /* timeout_del */ 1105 xs->error = XS_NOERROR; 1106 xs->resid = 0; 1107 xs->flags |= ITSDONE; 1108 1109 if (ccb->ccb_rcb == NULL) { 1110 /* no scsi error, we're ok so drop out early */ 1111 xs->status = SCSI_OK; 1112 mpi_put_ccb(sc, ccb); 1113 scsi_done(xs); 1114 return; 1115 } 1116 1117 sie = ccb->ccb_rcb->rcb_reply; 1118 1119 DNPRINTF(MPI_D_CMD, "%s: mpi_scsi_cmd_done xs cmd: 0x%02x len: %d " 1120 "flags 0x%x\n", DEVNAME(sc), xs->cmd->opcode, xs->datalen, 1121 xs->flags); 1122 DNPRINTF(MPI_D_CMD, "%s: target_id: %d bus: %d msg_length: %d " 1123 "function: 0x%02x\n", DEVNAME(sc), sie->target_id, sie->bus, 1124 sie->msg_length, sie->function); 1125 DNPRINTF(MPI_D_CMD, "%s: cdb_length: %d sense_buf_length: %d " 1126 "msg_flags: 0x%02x\n", DEVNAME(sc), sie->cdb_length, 1127 sie->sense_buf_len, sie->msg_flags); 1128 DNPRINTF(MPI_D_CMD, "%s: msg_context: 0x%08x\n", DEVNAME(sc), 1129 letoh32(sie->msg_context)); 1130 DNPRINTF(MPI_D_CMD, "%s: scsi_status: 0x%02x scsi_state: 0x%02x " 1131 "ioc_status: 0x%04x\n", DEVNAME(sc), sie->scsi_status, 1132 sie->scsi_state, letoh16(sie->ioc_status)); 1133 DNPRINTF(MPI_D_CMD, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1134 letoh32(sie->ioc_loginfo)); 1135 DNPRINTF(MPI_D_CMD, "%s: transfer_count: %d\n", DEVNAME(sc), 1136 letoh32(sie->transfer_count)); 1137 DNPRINTF(MPI_D_CMD, "%s: sense_count: %d\n", DEVNAME(sc), 1138 letoh32(sie->sense_count)); 1139 DNPRINTF(MPI_D_CMD, "%s: response_info: 0x%08x\n", DEVNAME(sc), 1140 letoh32(sie->response_info)); 1141 DNPRINTF(MPI_D_CMD, "%s: tag: 0x%04x\n", DEVNAME(sc), 1142 letoh16(sie->tag)); 1143 1144 xs->status = sie->scsi_status; 1145 switch (letoh16(sie->ioc_status)) { 1146 case MPI_IOCSTATUS_SCSI_DATA_UNDERRUN: 1147 xs->resid = xs->datalen - letoh32(sie->transfer_count); 1148 if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_NO_SCSI_STATUS) { 1149 xs->error = XS_DRIVER_STUFFUP; 1150 break; 1151 } 1152 /* FALLTHROUGH */ 1153 case MPI_IOCSTATUS_SUCCESS: 1154 case MPI_IOCSTATUS_SCSI_RECOVERED_ERROR: 1155 switch (xs->status) { 1156 case SCSI_OK: 1157 xs->resid = 0; 1158 break; 1159 1160 case SCSI_CHECK: 1161 xs->error = XS_SENSE; 1162 break; 1163 1164 case SCSI_BUSY: 1165 case SCSI_QUEUE_FULL: 1166 xs->error = XS_BUSY; 1167 break; 1168 1169 default: 1170 xs->error = XS_DRIVER_STUFFUP; 1171 break; 1172 } 1173 break; 1174 1175 case MPI_IOCSTATUS_BUSY: 1176 case MPI_IOCSTATUS_INSUFFICIENT_RESOURCES: 1177 xs->error = XS_BUSY; 1178 break; 1179 1180 case MPI_IOCSTATUS_SCSI_INVALID_BUS: 1181 case MPI_IOCSTATUS_SCSI_INVALID_TARGETID: 1182 case MPI_IOCSTATUS_SCSI_DEVICE_NOT_THERE: 1183 xs->error = XS_SELTIMEOUT; 1184 break; 1185 1186 default: 1187 xs->error = XS_DRIVER_STUFFUP; 1188 break; 1189 } 1190 1191 if (sie->scsi_state & MPI_SCSIIO_ERR_STATE_AUTOSENSE_VALID) 1192 bcopy(&mcb->mcb_sense, &xs->sense, sizeof(xs->sense)); 1193 1194 DNPRINTF(MPI_D_CMD, "%s: xs err: 0x%02x status: %d\n", DEVNAME(sc), 1195 xs->error, xs->status); 1196 1197 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 1198 mpi_put_ccb(sc, ccb); 1199 scsi_done(xs); 1200 } 1201 1202 void 1203 mpi_timeout_xs(void *arg) 1204 { 1205 /* XXX */ 1206 } 1207 1208 int 1209 mpi_load_xs(struct mpi_ccb *ccb) 1210 { 1211 struct mpi_softc *sc = ccb->ccb_sc; 1212 struct scsi_xfer *xs = ccb->ccb_xs; 1213 struct mpi_ccb_bundle *mcb = ccb->ccb_cmd; 1214 struct mpi_msg_scsi_io *io = &mcb->mcb_io; 1215 struct mpi_sge *sge, *nsge = &mcb->mcb_sgl[0]; 1216 struct mpi_sge *ce = NULL, *nce; 1217 u_int64_t ce_dva; 1218 bus_dmamap_t dmap = ccb->ccb_dmamap; 1219 u_int32_t addr, flags; 1220 int i, error; 1221 1222 if (xs->datalen == 0) { 1223 nsge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | 1224 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL); 1225 return (0); 1226 } 1227 1228 error = bus_dmamap_load(sc->sc_dmat, dmap, 1229 xs->data, xs->datalen, NULL, 1230 (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); 1231 if (error) { 1232 printf("%s: error %d loading dmamap\n", DEVNAME(sc), error); 1233 return (1); 1234 } 1235 1236 flags = MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64; 1237 if (xs->flags & SCSI_DATA_OUT) 1238 flags |= MPI_SGE_FL_DIR_OUT; 1239 1240 if (dmap->dm_nsegs > sc->sc_first_sgl_len) { 1241 ce = &mcb->mcb_sgl[sc->sc_first_sgl_len - 1]; 1242 io->chain_offset = ((u_int8_t *)ce - (u_int8_t *)io) / 4; 1243 } 1244 1245 for (i = 0; i < dmap->dm_nsegs; i++) { 1246 1247 if (nsge == ce) { 1248 nsge++; 1249 sge->sg_hdr |= htole32(MPI_SGE_FL_LAST); 1250 1251 DNPRINTF(MPI_D_DMA, "%s: - 0x%08x 0x%08x 0x%08x\n", 1252 DEVNAME(sc), sge->sg_hdr, 1253 sge->sg_hi_addr, sge->sg_lo_addr); 1254 1255 if ((dmap->dm_nsegs - i) > sc->sc_chain_len) { 1256 nce = &nsge[sc->sc_chain_len - 1]; 1257 addr = ((u_int8_t *)nce - (u_int8_t *)nsge) / 4; 1258 addr = addr << 16 | 1259 sizeof(struct mpi_sge) * sc->sc_chain_len; 1260 } else { 1261 nce = NULL; 1262 addr = sizeof(struct mpi_sge) * 1263 (dmap->dm_nsegs - i); 1264 } 1265 1266 ce->sg_hdr = htole32(MPI_SGE_FL_TYPE_CHAIN | 1267 MPI_SGE_FL_SIZE_64 | addr); 1268 1269 ce_dva = ccb->ccb_cmd_dva + 1270 ((u_int8_t *)nsge - (u_int8_t *)mcb); 1271 1272 addr = (u_int32_t)(ce_dva >> 32); 1273 ce->sg_hi_addr = htole32(addr); 1274 addr = (u_int32_t)ce_dva; 1275 ce->sg_lo_addr = htole32(addr); 1276 1277 DNPRINTF(MPI_D_DMA, "%s: ce: 0x%08x 0x%08x 0x%08x\n", 1278 DEVNAME(sc), ce->sg_hdr, ce->sg_hi_addr, 1279 ce->sg_lo_addr); 1280 1281 ce = nce; 1282 } 1283 1284 DNPRINTF(MPI_D_DMA, "%s: %d: %d 0x%016llx\n", DEVNAME(sc), 1285 i, dmap->dm_segs[i].ds_len, 1286 (u_int64_t)dmap->dm_segs[i].ds_addr); 1287 1288 sge = nsge; 1289 1290 sge->sg_hdr = htole32(flags | dmap->dm_segs[i].ds_len); 1291 addr = (u_int32_t)((u_int64_t)dmap->dm_segs[i].ds_addr >> 32); 1292 sge->sg_hi_addr = htole32(addr); 1293 addr = (u_int32_t)dmap->dm_segs[i].ds_addr; 1294 sge->sg_lo_addr = htole32(addr); 1295 1296 DNPRINTF(MPI_D_DMA, "%s: %d: 0x%08x 0x%08x 0x%08x\n", 1297 DEVNAME(sc), i, sge->sg_hdr, sge->sg_hi_addr, 1298 sge->sg_lo_addr); 1299 1300 nsge = sge + 1; 1301 } 1302 1303 /* terminate list */ 1304 sge->sg_hdr |= htole32(MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | 1305 MPI_SGE_FL_EOL); 1306 1307 bus_dmamap_sync(sc->sc_dmat, dmap, 0, dmap->dm_mapsize, 1308 (xs->flags & SCSI_DATA_IN) ? BUS_DMASYNC_PREREAD : 1309 BUS_DMASYNC_PREWRITE); 1310 1311 return (0); 1312 } 1313 1314 void 1315 mpi_minphys(struct buf *bp) 1316 { 1317 /* XXX */ 1318 if (bp->b_bcount > MAXPHYS) 1319 bp->b_bcount = MAXPHYS; 1320 minphys(bp); 1321 } 1322 1323 int 1324 mpi_scsi_ioctl(struct scsi_link *a, u_long b, caddr_t c, int d, struct proc *e) 1325 { 1326 return (0); 1327 } 1328 1329 u_int32_t 1330 mpi_read(struct mpi_softc *sc, bus_size_t r) 1331 { 1332 u_int32_t rv; 1333 1334 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 1335 BUS_SPACE_BARRIER_READ); 1336 rv = bus_space_read_4(sc->sc_iot, sc->sc_ioh, r); 1337 1338 DNPRINTF(MPI_D_RW, "%s: mpi_read %#x %#x\n", DEVNAME(sc), r, rv); 1339 1340 return (rv); 1341 } 1342 1343 void 1344 mpi_write(struct mpi_softc *sc, bus_size_t r, u_int32_t v) 1345 { 1346 DNPRINTF(MPI_D_RW, "%s: mpi_write %#x %#x\n", DEVNAME(sc), r, v); 1347 1348 bus_space_write_4(sc->sc_iot, sc->sc_ioh, r, v); 1349 bus_space_barrier(sc->sc_iot, sc->sc_ioh, r, 4, 1350 BUS_SPACE_BARRIER_WRITE); 1351 } 1352 1353 int 1354 mpi_wait_eq(struct mpi_softc *sc, bus_size_t r, u_int32_t mask, 1355 u_int32_t target) 1356 { 1357 int i; 1358 1359 DNPRINTF(MPI_D_RW, "%s: mpi_wait_eq %#x %#x %#x\n", DEVNAME(sc), r, 1360 mask, target); 1361 1362 for (i = 0; i < 10000; i++) { 1363 if ((mpi_read(sc, r) & mask) == target) 1364 return (0); 1365 delay(1000); 1366 } 1367 1368 return (1); 1369 } 1370 1371 int 1372 mpi_wait_ne(struct mpi_softc *sc, bus_size_t r, u_int32_t mask, 1373 u_int32_t target) 1374 { 1375 int i; 1376 1377 DNPRINTF(MPI_D_RW, "%s: mpi_wait_ne %#x %#x %#x\n", DEVNAME(sc), r, 1378 mask, target); 1379 1380 for (i = 0; i < 10000; i++) { 1381 if ((mpi_read(sc, r) & mask) != target) 1382 return (0); 1383 delay(1000); 1384 } 1385 1386 return (1); 1387 } 1388 1389 int 1390 mpi_init(struct mpi_softc *sc) 1391 { 1392 u_int32_t db; 1393 int i; 1394 1395 /* spin until the IOC leaves the RESET state */ 1396 if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE, 1397 MPI_DOORBELL_STATE_RESET) != 0) { 1398 DNPRINTF(MPI_D_MISC, "%s: mpi_init timeout waiting to leave " 1399 "reset state\n", DEVNAME(sc)); 1400 return (1); 1401 } 1402 1403 /* check current ownership */ 1404 db = mpi_read_db(sc); 1405 if ((db & MPI_DOORBELL_WHOINIT) == MPI_DOORBELL_WHOINIT_PCIPEER) { 1406 DNPRINTF(MPI_D_MISC, "%s: mpi_init initialised by pci peer\n", 1407 DEVNAME(sc)); 1408 return (0); 1409 } 1410 1411 for (i = 0; i < 5; i++) { 1412 switch (db & MPI_DOORBELL_STATE) { 1413 case MPI_DOORBELL_STATE_READY: 1414 DNPRINTF(MPI_D_MISC, "%s: mpi_init ioc is ready\n", 1415 DEVNAME(sc)); 1416 return (0); 1417 1418 case MPI_DOORBELL_STATE_OPER: 1419 case MPI_DOORBELL_STATE_FAULT: 1420 DNPRINTF(MPI_D_MISC, "%s: mpi_init ioc is being " 1421 "reset\n" , DEVNAME(sc)); 1422 if (mpi_reset_soft(sc) != 0) 1423 mpi_reset_hard(sc); 1424 break; 1425 1426 case MPI_DOORBELL_STATE_RESET: 1427 DNPRINTF(MPI_D_MISC, "%s: mpi_init waiting to come " 1428 "out of reset\n", DEVNAME(sc)); 1429 if (mpi_wait_ne(sc, MPI_DOORBELL, MPI_DOORBELL_STATE, 1430 MPI_DOORBELL_STATE_RESET) != 0) 1431 return (1); 1432 break; 1433 } 1434 db = mpi_read_db(sc); 1435 } 1436 1437 return (1); 1438 } 1439 1440 int 1441 mpi_reset_soft(struct mpi_softc *sc) 1442 { 1443 DNPRINTF(MPI_D_MISC, "%s: mpi_reset_soft\n", DEVNAME(sc)); 1444 1445 if (mpi_read_db(sc) & MPI_DOORBELL_INUSE) 1446 return (1); 1447 1448 mpi_write_db(sc, 1449 MPI_DOORBELL_FUNCTION(MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET)); 1450 if (mpi_wait_eq(sc, MPI_INTR_STATUS, 1451 MPI_INTR_STATUS_IOCDOORBELL, 0) != 0) 1452 return (1); 1453 1454 if (mpi_wait_eq(sc, MPI_DOORBELL, MPI_DOORBELL_STATE, 1455 MPI_DOORBELL_STATE_READY) != 0) 1456 return (1); 1457 1458 return (0); 1459 } 1460 1461 int 1462 mpi_reset_hard(struct mpi_softc *sc) 1463 { 1464 DNPRINTF(MPI_D_MISC, "%s: mpi_reset_hard\n", DEVNAME(sc)); 1465 1466 /* enable diagnostic register */ 1467 mpi_write(sc, MPI_WRITESEQ, 0xff); 1468 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_1); 1469 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_2); 1470 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_3); 1471 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_4); 1472 mpi_write(sc, MPI_WRITESEQ, MPI_WRITESEQ_5); 1473 1474 /* reset ioc */ 1475 mpi_write(sc, MPI_HOSTDIAG, MPI_HOSTDIAG_RESET_ADAPTER); 1476 1477 delay(10000); 1478 1479 /* disable diagnostic register */ 1480 mpi_write(sc, MPI_WRITESEQ, 0xff); 1481 1482 /* restore pci bits? */ 1483 1484 /* firmware bits? */ 1485 return (0); 1486 } 1487 1488 int 1489 mpi_handshake_send(struct mpi_softc *sc, void *buf, size_t dwords) 1490 { 1491 u_int32_t *query = buf; 1492 int i; 1493 1494 /* make sure the doorbell is not in use. */ 1495 if (mpi_read_db(sc) & MPI_DOORBELL_INUSE) 1496 return (1); 1497 1498 /* clear pending doorbell interrupts */ 1499 if (mpi_read_intr(sc) & MPI_INTR_STATUS_DOORBELL) 1500 mpi_write_intr(sc, 0); 1501 1502 /* 1503 * first write the doorbell with the handshake function and the 1504 * dword count. 1505 */ 1506 mpi_write_db(sc, MPI_DOORBELL_FUNCTION(MPI_FUNCTION_HANDSHAKE) | 1507 MPI_DOORBELL_DWORDS(dwords)); 1508 1509 /* 1510 * the doorbell used bit will be set because a doorbell function has 1511 * started. Wait for the interrupt and then ack it. 1512 */ 1513 if (mpi_wait_db_int(sc) != 0) 1514 return (1); 1515 mpi_write_intr(sc, 0); 1516 1517 /* poll for the acknowledgement. */ 1518 if (mpi_wait_db_ack(sc) != 0) 1519 return (1); 1520 1521 /* write the query through the doorbell. */ 1522 for (i = 0; i < dwords; i++) { 1523 mpi_write_db(sc, htole32(query[i])); 1524 if (mpi_wait_db_ack(sc) != 0) 1525 return (1); 1526 } 1527 1528 return (0); 1529 } 1530 1531 int 1532 mpi_handshake_recv_dword(struct mpi_softc *sc, u_int32_t *dword) 1533 { 1534 u_int16_t *words = (u_int16_t *)dword; 1535 int i; 1536 1537 for (i = 0; i < 2; i++) { 1538 if (mpi_wait_db_int(sc) != 0) 1539 return (1); 1540 words[i] = letoh16(mpi_read_db(sc) & MPI_DOORBELL_DATA_MASK); 1541 mpi_write_intr(sc, 0); 1542 } 1543 1544 return (0); 1545 } 1546 1547 int 1548 mpi_handshake_recv(struct mpi_softc *sc, void *buf, size_t dwords) 1549 { 1550 struct mpi_msg_reply *reply = buf; 1551 u_int32_t *dbuf = buf, dummy; 1552 int i; 1553 1554 /* get the first dword so we can read the length out of the header. */ 1555 if (mpi_handshake_recv_dword(sc, &dbuf[0]) != 0) 1556 return (1); 1557 1558 DNPRINTF(MPI_D_CMD, "%s: mpi_handshake_recv dwords: %d reply: %d\n", 1559 DEVNAME(sc), dwords, reply->msg_length); 1560 1561 /* 1562 * the total length, in dwords, is in the message length field of the 1563 * reply header. 1564 */ 1565 for (i = 1; i < MIN(dwords, reply->msg_length); i++) { 1566 if (mpi_handshake_recv_dword(sc, &dbuf[i]) != 0) 1567 return (1); 1568 } 1569 1570 /* if there's extra stuff to come off the ioc, discard it */ 1571 while (i++ < reply->msg_length) { 1572 if (mpi_handshake_recv_dword(sc, &dummy) != 0) 1573 return (1); 1574 DNPRINTF(MPI_D_CMD, "%s: mpi_handshake_recv dummy read: " 1575 "0x%08x\n", DEVNAME(sc), dummy); 1576 } 1577 1578 /* wait for the doorbell used bit to be reset and clear the intr */ 1579 if (mpi_wait_db_int(sc) != 0) 1580 return (1); 1581 mpi_write_intr(sc, 0); 1582 1583 return (0); 1584 } 1585 1586 void 1587 mpi_empty_done(struct mpi_ccb *ccb) 1588 { 1589 /* nothing to do */ 1590 } 1591 1592 int 1593 mpi_iocfacts(struct mpi_softc *sc) 1594 { 1595 struct mpi_msg_iocfacts_request ifq; 1596 struct mpi_msg_iocfacts_reply ifp; 1597 1598 DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts\n", DEVNAME(sc)); 1599 1600 bzero(&ifq, sizeof(ifq)); 1601 bzero(&ifp, sizeof(ifp)); 1602 1603 ifq.function = MPI_FUNCTION_IOC_FACTS; 1604 ifq.chain_offset = 0; 1605 ifq.msg_flags = 0; 1606 ifq.msg_context = htole32(0xdeadbeef); 1607 1608 if (mpi_handshake_send(sc, &ifq, dwordsof(ifq)) != 0) { 1609 DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts send failed\n", 1610 DEVNAME(sc)); 1611 return (1); 1612 } 1613 1614 if (mpi_handshake_recv(sc, &ifp, dwordsof(ifp)) != 0) { 1615 DNPRINTF(MPI_D_MISC, "%s: mpi_iocfacts recv failed\n", 1616 DEVNAME(sc)); 1617 return (1); 1618 } 1619 1620 DNPRINTF(MPI_D_MISC, "%s: func: 0x%02x len: %d msgver: %d.%d\n", 1621 DEVNAME(sc), ifp.function, ifp.msg_length, 1622 ifp.msg_version_maj, ifp.msg_version_min); 1623 DNPRINTF(MPI_D_MISC, "%s: msgflags: 0x%02x iocnumber: 0x%02x " 1624 "hdrver: %d.%d\n", DEVNAME(sc), ifp.msg_flags, 1625 ifp.ioc_number, ifp.header_version_maj, 1626 ifp.header_version_min); 1627 DNPRINTF(MPI_D_MISC, "%s: message context: 0x%08x\n", DEVNAME(sc), 1628 letoh32(ifp.msg_context)); 1629 DNPRINTF(MPI_D_MISC, "%s: iocstatus: 0x%04x ioexcept: 0x%04x\n", 1630 DEVNAME(sc), letoh16(ifp.ioc_status), 1631 letoh16(ifp.ioc_exceptions)); 1632 DNPRINTF(MPI_D_MISC, "%s: iocloginfo: 0x%08x\n", DEVNAME(sc), 1633 letoh32(ifp.ioc_loginfo)); 1634 DNPRINTF(MPI_D_MISC, "%s: flags: 0x%02x blocksize: %d whoinit: 0x%02x " 1635 "maxchdepth: %d\n", DEVNAME(sc), ifp.flags, 1636 ifp.block_size, ifp.whoinit, ifp.max_chain_depth); 1637 DNPRINTF(MPI_D_MISC, "%s: reqfrsize: %d replyqdepth: %d\n", 1638 DEVNAME(sc), letoh16(ifp.request_frame_size), 1639 letoh16(ifp.reply_queue_depth)); 1640 DNPRINTF(MPI_D_MISC, "%s: productid: 0x%04x\n", DEVNAME(sc), 1641 letoh16(ifp.product_id)); 1642 DNPRINTF(MPI_D_MISC, "%s: hostmfahiaddr: 0x%08x\n", DEVNAME(sc), 1643 letoh32(ifp.current_host_mfa_hi_addr)); 1644 DNPRINTF(MPI_D_MISC, "%s: event_state: 0x%02x number_of_ports: %d " 1645 "global_credits: %d\n", 1646 DEVNAME(sc), ifp.event_state, ifp.number_of_ports, 1647 letoh16(ifp.global_credits)); 1648 DNPRINTF(MPI_D_MISC, "%s: sensebufhiaddr: 0x%08x\n", DEVNAME(sc), 1649 letoh32(ifp.current_sense_buffer_hi_addr)); 1650 DNPRINTF(MPI_D_MISC, "%s: maxbus: %d maxdev: %d replyfrsize: %d\n", 1651 DEVNAME(sc), ifp.max_buses, ifp.max_devices, 1652 letoh16(ifp.current_reply_frame_size)); 1653 DNPRINTF(MPI_D_MISC, "%s: fw_image_size: %d\n", DEVNAME(sc), 1654 letoh32(ifp.fw_image_size)); 1655 DNPRINTF(MPI_D_MISC, "%s: ioc_capabilities: 0x%08x\n", DEVNAME(sc), 1656 letoh32(ifp.ioc_capabilities)); 1657 DNPRINTF(MPI_D_MISC, "%s: fw_version: %d.%d fw_version_unit: 0x%02x " 1658 "fw_version_dev: 0x%02x\n", DEVNAME(sc), 1659 ifp.fw_version_maj, ifp.fw_version_min, 1660 ifp.fw_version_unit, ifp.fw_version_dev); 1661 DNPRINTF(MPI_D_MISC, "%s: hi_priority_queue_depth: 0x%04x\n", 1662 DEVNAME(sc), letoh16(ifp.hi_priority_queue_depth)); 1663 DNPRINTF(MPI_D_MISC, "%s: host_page_buffer_sge: hdr: 0x%08x " 1664 "addr 0x%08x %08x\n", DEVNAME(sc), 1665 letoh32(ifp.host_page_buffer_sge.sg_hdr), 1666 letoh32(ifp.host_page_buffer_sge.sg_hi_addr), 1667 letoh32(ifp.host_page_buffer_sge.sg_lo_addr)); 1668 1669 sc->sc_maxcmds = letoh16(ifp.global_credits); 1670 sc->sc_maxchdepth = ifp.max_chain_depth; 1671 sc->sc_ioc_number = ifp.ioc_number; 1672 if (sc->sc_flags & MPI_F_VMWARE) 1673 sc->sc_buswidth = 16; 1674 else 1675 sc->sc_buswidth = 1676 (ifp.max_devices == 0) ? 256 : ifp.max_devices; 1677 if (ifp.flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) 1678 sc->sc_fw_len = letoh32(ifp.fw_image_size); 1679 1680 /* 1681 * you can fit sg elements on the end of the io cmd if they fit in the 1682 * request frame size. 1683 */ 1684 sc->sc_first_sgl_len = ((letoh16(ifp.request_frame_size) * 4) - 1685 sizeof(struct mpi_msg_scsi_io)) / sizeof(struct mpi_sge); 1686 DNPRINTF(MPI_D_MISC, "%s: first sgl len: %d\n", DEVNAME(sc), 1687 sc->sc_first_sgl_len); 1688 1689 sc->sc_chain_len = (letoh16(ifp.request_frame_size) * 4) / 1690 sizeof(struct mpi_sge); 1691 DNPRINTF(MPI_D_MISC, "%s: chain len: %d\n", DEVNAME(sc), 1692 sc->sc_chain_len); 1693 1694 /* the sgl tailing the io cmd loses an entry to the chain element. */ 1695 sc->sc_max_sgl_len = MPI_MAX_SGL - 1; 1696 /* the sgl chains lose an entry for each chain element */ 1697 sc->sc_max_sgl_len -= (MPI_MAX_SGL - sc->sc_first_sgl_len) / 1698 sc->sc_chain_len; 1699 DNPRINTF(MPI_D_MISC, "%s: max sgl len: %d\n", DEVNAME(sc), 1700 sc->sc_max_sgl_len); 1701 1702 /* XXX we're ignoring the max chain depth */ 1703 1704 return (0); 1705 } 1706 1707 int 1708 mpi_iocinit(struct mpi_softc *sc) 1709 { 1710 struct mpi_msg_iocinit_request iiq; 1711 struct mpi_msg_iocinit_reply iip; 1712 u_int32_t hi_addr; 1713 1714 DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit\n", DEVNAME(sc)); 1715 1716 bzero(&iiq, sizeof(iiq)); 1717 bzero(&iip, sizeof(iip)); 1718 1719 iiq.function = MPI_FUNCTION_IOC_INIT; 1720 iiq.whoinit = MPI_WHOINIT_HOST_DRIVER; 1721 1722 iiq.max_devices = (sc->sc_buswidth == 256) ? 0 : sc->sc_buswidth; 1723 iiq.max_buses = 1; 1724 1725 iiq.msg_context = htole32(0xd00fd00f); 1726 1727 iiq.reply_frame_size = htole16(MPI_REPLY_SIZE); 1728 1729 hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_requests) >> 32); 1730 iiq.host_mfa_hi_addr = htole32(hi_addr); 1731 iiq.sense_buffer_hi_addr = htole32(hi_addr); 1732 1733 hi_addr = (u_int32_t)((u_int64_t)MPI_DMA_DVA(sc->sc_replies) >> 32); 1734 iiq.reply_fifo_host_signalling_addr = htole32(hi_addr); 1735 1736 iiq.msg_version_maj = 0x01; 1737 iiq.msg_version_min = 0x02; 1738 1739 iiq.hdr_version_unit = 0x0d; 1740 iiq.hdr_version_dev = 0x00; 1741 1742 if (mpi_handshake_send(sc, &iiq, dwordsof(iiq)) != 0) { 1743 DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit send failed\n", 1744 DEVNAME(sc)); 1745 return (1); 1746 } 1747 1748 if (mpi_handshake_recv(sc, &iip, dwordsof(iip)) != 0) { 1749 DNPRINTF(MPI_D_MISC, "%s: mpi_iocinit recv failed\n", 1750 DEVNAME(sc)); 1751 return (1); 1752 } 1753 1754 DNPRINTF(MPI_D_MISC, "%s: function: 0x%02x msg_length: %d " 1755 "whoinit: 0x%02x\n", DEVNAME(sc), iip.function, 1756 iip.msg_length, iip.whoinit); 1757 DNPRINTF(MPI_D_MISC, "%s: msg_flags: 0x%02x max_buses: %d " 1758 "max_devices: %d flags: 0x%02x\n", DEVNAME(sc), iip.msg_flags, 1759 iip.max_buses, iip.max_devices, iip.flags); 1760 DNPRINTF(MPI_D_MISC, "%s: msg_context: 0x%08x\n", DEVNAME(sc), 1761 letoh32(iip.msg_context)); 1762 DNPRINTF(MPI_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1763 letoh16(iip.ioc_status)); 1764 DNPRINTF(MPI_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1765 letoh32(iip.ioc_loginfo)); 1766 1767 return (0); 1768 } 1769 1770 int 1771 mpi_portfacts(struct mpi_softc *sc) 1772 { 1773 struct mpi_ccb *ccb; 1774 struct mpi_msg_portfacts_request *pfq; 1775 volatile struct mpi_msg_portfacts_reply *pfp; 1776 int s, rv = 1; 1777 1778 DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts\n", DEVNAME(sc)); 1779 1780 s = splbio(); 1781 ccb = mpi_get_ccb(sc); 1782 splx(s); 1783 if (ccb == NULL) { 1784 DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts ccb_get\n", 1785 DEVNAME(sc)); 1786 return (rv); 1787 } 1788 1789 ccb->ccb_done = mpi_empty_done; 1790 pfq = ccb->ccb_cmd; 1791 1792 pfq->function = MPI_FUNCTION_PORT_FACTS; 1793 pfq->chain_offset = 0; 1794 pfq->msg_flags = 0; 1795 pfq->port_number = 0; 1796 pfq->msg_context = htole32(ccb->ccb_id); 1797 1798 if (mpi_poll(sc, ccb, 50000) != 0) { 1799 DNPRINTF(MPI_D_MISC, "%s: mpi_portfacts poll\n", DEVNAME(sc)); 1800 goto err; 1801 } 1802 1803 if (ccb->ccb_rcb == NULL) { 1804 DNPRINTF(MPI_D_MISC, "%s: empty portfacts reply\n", 1805 DEVNAME(sc)); 1806 goto err; 1807 } 1808 pfp = ccb->ccb_rcb->rcb_reply; 1809 1810 DNPRINTF(MPI_D_MISC, "%s: function: 0x%02x msg_length: %d\n", 1811 DEVNAME(sc), pfp->function, pfp->msg_length); 1812 DNPRINTF(MPI_D_MISC, "%s: msg_flags: 0x%02x port_number: %d\n", 1813 DEVNAME(sc), pfp->msg_flags, pfp->port_number); 1814 DNPRINTF(MPI_D_MISC, "%s: msg_context: 0x%08x\n", DEVNAME(sc), 1815 letoh32(pfp->msg_context)); 1816 DNPRINTF(MPI_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1817 letoh16(pfp->ioc_status)); 1818 DNPRINTF(MPI_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1819 letoh32(pfp->ioc_loginfo)); 1820 DNPRINTF(MPI_D_MISC, "%s: max_devices: %d port_type: 0x%02x\n", 1821 DEVNAME(sc), letoh16(pfp->max_devices), pfp->port_type); 1822 DNPRINTF(MPI_D_MISC, "%s: protocol_flags: 0x%04x port_scsi_id: %d\n", 1823 DEVNAME(sc), letoh16(pfp->protocol_flags), 1824 letoh16(pfp->port_scsi_id)); 1825 DNPRINTF(MPI_D_MISC, "%s: max_persistent_ids: %d " 1826 "max_posted_cmd_buffers: %d\n", DEVNAME(sc), 1827 letoh16(pfp->max_persistent_ids), 1828 letoh16(pfp->max_posted_cmd_buffers)); 1829 DNPRINTF(MPI_D_MISC, "%s: max_lan_buckets: %d\n", DEVNAME(sc), 1830 letoh16(pfp->max_lan_buckets)); 1831 1832 sc->sc_porttype = pfp->port_type; 1833 sc->sc_target = letoh16(pfp->port_scsi_id); 1834 1835 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 1836 rv = 0; 1837 err: 1838 mpi_put_ccb(sc, ccb); 1839 1840 return (rv); 1841 } 1842 1843 int 1844 mpi_eventnotify(struct mpi_softc *sc) 1845 { 1846 struct mpi_ccb *ccb; 1847 struct mpi_msg_event_request *enq; 1848 int s; 1849 1850 s = splbio(); 1851 ccb = mpi_get_ccb(sc); 1852 splx(s); 1853 if (ccb == NULL) { 1854 DNPRINTF(MPI_D_MISC, "%s: mpi_eventnotify ccb_get\n", 1855 DEVNAME(sc)); 1856 return (1); 1857 } 1858 1859 ccb->ccb_done = mpi_eventnotify_done; 1860 enq = ccb->ccb_cmd; 1861 1862 enq->function = MPI_FUNCTION_EVENT_NOTIFICATION; 1863 enq->chain_offset = 0; 1864 enq->event_switch = MPI_EVENT_SWITCH_ON; 1865 enq->msg_context = htole32(ccb->ccb_id); 1866 1867 mpi_start(sc, ccb); 1868 return (0); 1869 } 1870 1871 void 1872 mpi_eventnotify_done(struct mpi_ccb *ccb) 1873 { 1874 struct mpi_softc *sc = ccb->ccb_sc; 1875 struct mpi_msg_event_reply *enp = ccb->ccb_rcb->rcb_reply; 1876 int deferred = 0; 1877 1878 DNPRINTF(MPI_D_EVT, "%s: mpi_eventnotify_done\n", DEVNAME(sc)); 1879 1880 DNPRINTF(MPI_D_EVT, "%s: function: 0x%02x msg_length: %d " 1881 "data_length: %d\n", DEVNAME(sc), enp->function, enp->msg_length, 1882 letoh16(enp->data_length)); 1883 DNPRINTF(MPI_D_EVT, "%s: ack_required: %d msg_flags 0x%02x\n", 1884 DEVNAME(sc), enp->ack_required, enp->msg_flags); 1885 DNPRINTF(MPI_D_EVT, "%s: msg_context: 0x%08x\n", DEVNAME(sc), 1886 letoh32(enp->msg_context)); 1887 DNPRINTF(MPI_D_EVT, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), 1888 letoh16(enp->ioc_status)); 1889 DNPRINTF(MPI_D_EVT, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 1890 letoh32(enp->ioc_loginfo)); 1891 DNPRINTF(MPI_D_EVT, "%s: event: 0x%08x\n", DEVNAME(sc), 1892 letoh32(enp->event)); 1893 DNPRINTF(MPI_D_EVT, "%s: event_context: 0x%08x\n", DEVNAME(sc), 1894 letoh32(enp->event_context)); 1895 1896 switch (letoh32(enp->event)) { 1897 /* ignore these */ 1898 case MPI_EVENT_EVENT_CHANGE: 1899 case MPI_EVENT_SAS_PHY_LINK_STATUS: 1900 break; 1901 1902 case MPI_EVENT_SAS_DEVICE_STATUS_CHANGE: 1903 if (sc->sc_scsibus == NULL) 1904 break; 1905 1906 if (scsi_task(mpi_evt_sas, sc, ccb->ccb_rcb, 1) != 0) { 1907 printf("%s: unable to run SAS device status change\n", 1908 DEVNAME(sc)); 1909 break; 1910 } 1911 deferred = 1; 1912 break; 1913 1914 default: 1915 printf("%s: unhandled event 0x%02x\n", DEVNAME(sc), 1916 letoh32(enp->event)); 1917 break; 1918 } 1919 1920 if (!deferred) { 1921 if (enp->ack_required) 1922 mpi_eventack(sc, enp); 1923 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 1924 } 1925 1926 if ((enp->msg_flags & MPI_EVENT_FLAGS_REPLY_KEPT) == 0) { 1927 /* XXX this shouldnt happen till shutdown */ 1928 mpi_put_ccb(sc, ccb); 1929 } 1930 } 1931 1932 void 1933 mpi_evt_sas(void *xsc, void *arg) 1934 { 1935 struct mpi_softc *sc = xsc; 1936 struct mpi_rcb *rcb = arg; 1937 struct mpi_msg_event_reply *enp = rcb->rcb_reply; 1938 struct mpi_evt_sas_change *ch; 1939 u_int8_t *data; 1940 int s; 1941 1942 data = rcb->rcb_reply; 1943 data += sizeof(struct mpi_msg_event_reply); 1944 ch = (struct mpi_evt_sas_change *)data; 1945 1946 if (ch->bus != 0) 1947 return; 1948 1949 switch (ch->reason) { 1950 case MPI_EVT_SASCH_REASON_ADDED: 1951 case MPI_EVT_SASCH_REASON_NO_PERSIST_ADDED: 1952 scsi_probe_target(sc->sc_scsibus, ch->target); 1953 break; 1954 1955 case MPI_EVT_SASCH_REASON_NOT_RESPONDING: 1956 scsi_detach_target(sc->sc_scsibus, ch->target, DETACH_FORCE); 1957 break; 1958 1959 case MPI_EVT_SASCH_REASON_SMART_DATA: 1960 case MPI_EVT_SASCH_REASON_UNSUPPORTED: 1961 case MPI_EVT_SASCH_REASON_INTERNAL_RESET: 1962 break; 1963 default: 1964 printf("%s: unknown reason for SAS device status change: " 1965 "0x%02x\n", DEVNAME(sc), ch->reason); 1966 break; 1967 } 1968 1969 s = splbio(); 1970 mpi_push_reply(sc, rcb->rcb_reply_dva); 1971 if (enp->ack_required) 1972 mpi_eventack(sc, enp); 1973 splx(s); 1974 } 1975 1976 void 1977 mpi_eventack(struct mpi_softc *sc, struct mpi_msg_event_reply *enp) 1978 { 1979 struct mpi_ccb *ccb; 1980 struct mpi_msg_eventack_request *eaq; 1981 1982 ccb = mpi_get_ccb(sc); 1983 if (ccb == NULL) { 1984 DNPRINTF(MPI_D_EVT, "%s: mpi_eventack ccb_get\n", DEVNAME(sc)); 1985 return; 1986 } 1987 1988 ccb->ccb_done = mpi_eventack_done; 1989 eaq = ccb->ccb_cmd; 1990 1991 eaq->function = MPI_FUNCTION_EVENT_ACK; 1992 eaq->msg_context = htole32(ccb->ccb_id); 1993 1994 eaq->event = enp->event; 1995 eaq->event_context = enp->event_context; 1996 1997 mpi_start(sc, ccb); 1998 return; 1999 } 2000 2001 void 2002 mpi_eventack_done(struct mpi_ccb *ccb) 2003 { 2004 struct mpi_softc *sc = ccb->ccb_sc; 2005 2006 DNPRINTF(MPI_D_EVT, "%s: event ack done\n", DEVNAME(sc)); 2007 2008 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 2009 mpi_put_ccb(sc, ccb); 2010 } 2011 2012 int 2013 mpi_portenable(struct mpi_softc *sc) 2014 { 2015 struct mpi_ccb *ccb; 2016 struct mpi_msg_portenable_request *peq; 2017 struct mpi_msg_portenable_repy *pep; 2018 int s; 2019 2020 DNPRINTF(MPI_D_MISC, "%s: mpi_portenable\n", DEVNAME(sc)); 2021 2022 s = splbio(); 2023 ccb = mpi_get_ccb(sc); 2024 splx(s); 2025 if (ccb == NULL) { 2026 DNPRINTF(MPI_D_MISC, "%s: mpi_portenable ccb_get\n", 2027 DEVNAME(sc)); 2028 return (1); 2029 } 2030 2031 ccb->ccb_done = mpi_empty_done; 2032 peq = ccb->ccb_cmd; 2033 2034 peq->function = MPI_FUNCTION_PORT_ENABLE; 2035 peq->port_number = 0; 2036 peq->msg_context = htole32(ccb->ccb_id); 2037 2038 if (mpi_poll(sc, ccb, 50000) != 0) { 2039 DNPRINTF(MPI_D_MISC, "%s: mpi_portenable poll\n", DEVNAME(sc)); 2040 return (1); 2041 } 2042 2043 if (ccb->ccb_rcb == NULL) { 2044 DNPRINTF(MPI_D_MISC, "%s: empty portenable reply\n", 2045 DEVNAME(sc)); 2046 return (1); 2047 } 2048 pep = ccb->ccb_rcb->rcb_reply; 2049 2050 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 2051 mpi_put_ccb(sc, ccb); 2052 2053 return (0); 2054 } 2055 2056 int 2057 mpi_fwupload(struct mpi_softc *sc) 2058 { 2059 struct mpi_ccb *ccb; 2060 struct { 2061 struct mpi_msg_fwupload_request req; 2062 struct mpi_sge sge; 2063 } __packed *bundle; 2064 struct mpi_msg_fwupload_reply *upp; 2065 u_int64_t addr; 2066 int s; 2067 int rv = 0; 2068 2069 if (sc->sc_fw_len == 0) 2070 return (0); 2071 2072 DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload\n", DEVNAME(sc)); 2073 2074 sc->sc_fw = mpi_dmamem_alloc(sc, sc->sc_fw_len); 2075 if (sc->sc_fw == NULL) { 2076 DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload unable to allocate %d\n", 2077 DEVNAME(sc), sc->sc_fw_len); 2078 return (1); 2079 } 2080 2081 s = splbio(); 2082 ccb = mpi_get_ccb(sc); 2083 splx(s); 2084 if (ccb == NULL) { 2085 DNPRINTF(MPI_D_MISC, "%s: mpi_fwupload ccb_get\n", 2086 DEVNAME(sc)); 2087 goto err; 2088 } 2089 2090 ccb->ccb_done = mpi_empty_done; 2091 bundle = ccb->ccb_cmd; 2092 2093 bundle->req.function = MPI_FUNCTION_FW_UPLOAD; 2094 bundle->req.msg_context = htole32(ccb->ccb_id); 2095 2096 bundle->req.image_type = MPI_FWUPLOAD_IMAGETYPE_IOC_FW; 2097 2098 bundle->req.tce.details_length = 12; 2099 bundle->req.tce.image_size = htole32(sc->sc_fw_len); 2100 2101 bundle->sge.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | 2102 MPI_SGE_FL_SIZE_64 | MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | 2103 MPI_SGE_FL_EOL | (u_int32_t)sc->sc_fw_len); 2104 addr = MPI_DMA_DVA(sc->sc_fw); 2105 bundle->sge.sg_hi_addr = htole32((u_int32_t)(addr >> 32)); 2106 bundle->sge.sg_lo_addr = htole32((u_int32_t)addr); 2107 2108 if (mpi_poll(sc, ccb, 50000) != 0) { 2109 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc)); 2110 goto err; 2111 } 2112 2113 if (ccb->ccb_rcb == NULL) 2114 panic("%s: unable to do fw upload\n", DEVNAME(sc)); 2115 upp = ccb->ccb_rcb->rcb_reply; 2116 2117 if (letoh16(upp->ioc_status) != MPI_IOCSTATUS_SUCCESS) 2118 rv = 1; 2119 2120 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 2121 mpi_put_ccb(sc, ccb); 2122 2123 return (rv); 2124 2125 err: 2126 mpi_dmamem_free(sc, sc->sc_fw); 2127 return (1); 2128 } 2129 2130 void 2131 mpi_get_raid(struct mpi_softc *sc) 2132 { 2133 struct mpi_cfg_hdr hdr; 2134 struct mpi_cfg_ioc_pg2 *vol_page; 2135 struct mpi_cfg_raid_vol *vol_list, *vol; 2136 size_t pagelen; 2137 u_int32_t capabilities; 2138 struct scsi_link *link; 2139 int i; 2140 2141 DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid\n", DEVNAME(sc)); 2142 2143 if (mpi_cfg_header(sc, MPI_CONFIG_REQ_PAGE_TYPE_IOC, 2, 0, &hdr) != 0) { 2144 DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to fetch header" 2145 "for IOC page 2\n", DEVNAME(sc)); 2146 return; 2147 } 2148 2149 pagelen = hdr.page_length * 4; /* dwords to bytes */ 2150 vol_page = malloc(pagelen, M_TEMP, M_WAITOK); 2151 if (vol_page == NULL) { 2152 DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to allocate " 2153 "space for ioc config page 2\n", DEVNAME(sc)); 2154 return; 2155 } 2156 vol_list = (struct mpi_cfg_raid_vol *)(vol_page + 1); 2157 2158 if (mpi_cfg_page(sc, 0, &hdr, 1, vol_page, pagelen) != 0) { 2159 DNPRINTF(MPI_D_RAID, "%s: mpi_get_raid unable to fetch IOC " 2160 "page 2\n", DEVNAME(sc)); 2161 goto out; 2162 } 2163 2164 capabilities = letoh32(vol_page->capabilities); 2165 2166 DNPRINTF(MPI_D_RAID, "%s: capabilities: 0x08%x\n", DEVNAME(sc), 2167 letoh32(vol_page->capabilities)); 2168 DNPRINTF(MPI_D_RAID, "%s: active_vols: %d max_vols: %d " 2169 "active_physdisks: %d max_physdisks: %d\n", DEVNAME(sc), 2170 vol_page->active_vols, vol_page->max_vols, 2171 vol_page->active_physdisks, vol_page->max_physdisks); 2172 2173 /* don't walk list if there are no RAID capability */ 2174 if (capabilities == 0xdeadbeef) { 2175 printf("%s: deadbeef in raid configuration\n", DEVNAME(sc)); 2176 goto out; 2177 } 2178 2179 if ((capabilities & MPI_CFG_IOC_2_CAPABILITIES_RAID) == 0 || 2180 (vol_page->active_vols == 0)) 2181 goto out; 2182 2183 sc->sc_flags |= MPI_F_RAID; 2184 2185 for (i = 0; i < vol_page->active_vols; i++) { 2186 vol = &vol_list[i]; 2187 2188 DNPRINTF(MPI_D_RAID, "%s: id: %d bus: %d ioc: %d pg: %d\n", 2189 DEVNAME(sc), vol->vol_id, vol->vol_bus, vol->vol_ioc, 2190 vol->vol_page); 2191 DNPRINTF(MPI_D_RAID, "%s: type: 0x%02x flags: 0x%02x\n", 2192 DEVNAME(sc), vol->vol_type, vol->flags); 2193 2194 if (vol->vol_ioc != sc->sc_ioc_number || vol->vol_bus != 0) 2195 continue; 2196 2197 link = sc->sc_scsibus->sc_link[vol->vol_id][0]; 2198 if (link == NULL) 2199 continue; 2200 2201 link->flags |= SDEV_VIRTUAL; 2202 } 2203 2204 out: 2205 free(vol_page, M_TEMP); 2206 } 2207 2208 int 2209 mpi_cfg_header(struct mpi_softc *sc, u_int8_t type, u_int8_t number, 2210 u_int32_t address, struct mpi_cfg_hdr *hdr) 2211 { 2212 struct mpi_ccb *ccb; 2213 struct mpi_msg_config_request *cq; 2214 struct mpi_msg_config_reply *cp; 2215 int rv = 0; 2216 int s; 2217 2218 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header type: %#x number: %x " 2219 "address: %d\n", DEVNAME(sc), type, number, address); 2220 2221 s = splbio(); 2222 ccb = mpi_get_ccb(sc); 2223 splx(s); 2224 if (ccb == NULL) { 2225 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header ccb_get\n", 2226 DEVNAME(sc)); 2227 return (1); 2228 } 2229 2230 ccb->ccb_done = mpi_empty_done; 2231 cq = ccb->ccb_cmd; 2232 2233 cq->function = MPI_FUNCTION_CONFIG; 2234 cq->msg_context = htole32(ccb->ccb_id); 2235 2236 cq->action = MPI_CONFIG_REQ_ACTION_PAGE_HEADER; 2237 2238 cq->config_header.page_number = number; 2239 cq->config_header.page_type = type; 2240 cq->page_address = htole32(address); 2241 cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | 2242 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL); 2243 2244 if (mpi_poll(sc, ccb, 50000) != 0) { 2245 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_header poll\n", DEVNAME(sc)); 2246 return (1); 2247 } 2248 2249 if (ccb->ccb_rcb == NULL) 2250 panic("%s: unable to fetch config header\n", DEVNAME(sc)); 2251 cp = ccb->ccb_rcb->rcb_reply; 2252 2253 DNPRINTF(MPI_D_MISC, "%s: action: 0x%02x msg_length: %d function: " 2254 "0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, cp->function); 2255 DNPRINTF(MPI_D_MISC, "%s: ext_page_length: %d ext_page_type: 0x%02x " 2256 "msg_flags: 0x%02x\n", DEVNAME(sc), 2257 letoh16(cp->ext_page_length), cp->ext_page_type, 2258 cp->msg_flags); 2259 DNPRINTF(MPI_D_MISC, "%s: msg_context: 0x%08x\n", DEVNAME(sc), 2260 letoh32(cp->msg_context)); 2261 DNPRINTF(MPI_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), 2262 letoh16(cp->ioc_status)); 2263 DNPRINTF(MPI_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 2264 letoh32(cp->ioc_loginfo)); 2265 DNPRINTF(MPI_D_MISC, "%s: page_version: 0x%02x page_length: %d " 2266 "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc), 2267 cp->config_header.page_version, 2268 cp->config_header.page_length, 2269 cp->config_header.page_number, 2270 cp->config_header.page_type); 2271 2272 if (letoh16(cp->ioc_status) != MPI_IOCSTATUS_SUCCESS) 2273 rv = 1; 2274 else 2275 *hdr = cp->config_header; 2276 2277 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 2278 mpi_put_ccb(sc, ccb); 2279 2280 return (rv); 2281 } 2282 2283 int 2284 mpi_cfg_page(struct mpi_softc *sc, u_int32_t address, struct mpi_cfg_hdr *hdr, 2285 int read, void *page, size_t len) 2286 { 2287 struct mpi_ccb *ccb; 2288 struct mpi_msg_config_request *cq; 2289 struct mpi_msg_config_reply *cp; 2290 u_int64_t dva; 2291 char *kva; 2292 int rv = 0; 2293 int s; 2294 2295 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page address: %d read: %d type: %x\n", 2296 DEVNAME(sc), address, read, hdr->page_type); 2297 2298 if (len > MPI_REQUEST_SIZE - sizeof(struct mpi_msg_config_request) || 2299 len < hdr->page_length * 4) 2300 return (1); 2301 2302 s = splbio(); 2303 ccb = mpi_get_ccb(sc); 2304 splx(s); 2305 if (ccb == NULL) { 2306 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page ccb_get\n", DEVNAME(sc)); 2307 return (1); 2308 } 2309 2310 ccb->ccb_done = mpi_empty_done; 2311 cq = ccb->ccb_cmd; 2312 2313 cq->function = MPI_FUNCTION_CONFIG; 2314 cq->msg_context = htole32(ccb->ccb_id); 2315 2316 cq->action = (read ? MPI_CONFIG_REQ_ACTION_PAGE_READ_CURRENT : 2317 MPI_CONFIG_REQ_ACTION_PAGE_WRITE_CURRENT); 2318 2319 cq->config_header = *hdr; 2320 cq->config_header.page_type &= MPI_CONFIG_REQ_PAGE_TYPE_MASK; 2321 cq->page_address = htole32(address); 2322 cq->page_buffer.sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | 2323 MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL | 2324 (hdr->page_length * 4) | 2325 (read ? MPI_SGE_FL_DIR_IN : MPI_SGE_FL_DIR_OUT)); 2326 2327 /* bounce the page via the request space to avoid more bus_dma games */ 2328 dva = ccb->ccb_cmd_dva + sizeof(struct mpi_msg_config_request); 2329 2330 cq->page_buffer.sg_hi_addr = htole32((u_int32_t)(dva >> 32)); 2331 cq->page_buffer.sg_lo_addr = htole32((u_int32_t)dva); 2332 2333 kva = ccb->ccb_cmd; 2334 kva += sizeof(struct mpi_msg_config_request); 2335 if (!read) 2336 bcopy(page, kva, len); 2337 2338 if (mpi_poll(sc, ccb, 50000) != 0) { 2339 DNPRINTF(MPI_D_MISC, "%s: mpi_cfg_page poll\n", DEVNAME(sc)); 2340 return (1); 2341 } 2342 2343 if (ccb->ccb_rcb == NULL) { 2344 mpi_put_ccb(sc, ccb); 2345 return (1); 2346 } 2347 cp = ccb->ccb_rcb->rcb_reply; 2348 2349 DNPRINTF(MPI_D_MISC, "%s: action: 0x%02x msg_length: %d function: " 2350 "0x%02x\n", DEVNAME(sc), cp->action, cp->msg_length, cp->function); 2351 DNPRINTF(MPI_D_MISC, "%s: ext_page_length: %d ext_page_type: 0x%02x " 2352 "msg_flags: 0x%02x\n", DEVNAME(sc), 2353 letoh16(cp->ext_page_length), cp->ext_page_type, 2354 cp->msg_flags); 2355 DNPRINTF(MPI_D_MISC, "%s: msg_context: 0x%08x\n", DEVNAME(sc), 2356 letoh32(cp->msg_context)); 2357 DNPRINTF(MPI_D_MISC, "%s: ioc_status: 0x%04x\n", DEVNAME(sc), 2358 letoh16(cp->ioc_status)); 2359 DNPRINTF(MPI_D_MISC, "%s: ioc_loginfo: 0x%08x\n", DEVNAME(sc), 2360 letoh32(cp->ioc_loginfo)); 2361 DNPRINTF(MPI_D_MISC, "%s: page_version: 0x%02x page_length: %d " 2362 "page_number: 0x%02x page_type: 0x%02x\n", DEVNAME(sc), 2363 cp->config_header.page_version, 2364 cp->config_header.page_length, 2365 cp->config_header.page_number, 2366 cp->config_header.page_type); 2367 2368 if (letoh16(cp->ioc_status) != MPI_IOCSTATUS_SUCCESS) 2369 rv = 1; 2370 else if (read) 2371 bcopy(kva, page, len); 2372 2373 mpi_push_reply(sc, ccb->ccb_rcb->rcb_reply_dva); 2374 mpi_put_ccb(sc, ccb); 2375 2376 return (rv); 2377 } 2378