1 /*- 2 * Generic routines for LSI '909 FC adapters. 3 * FreeBSD Version. 4 * 5 * Copyright (c) 2000, 2001 by Greg Ansley 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice immediately at the beginning of the file, without modification, 12 * this list of conditions, and the following disclaimer. 13 * 2. The name of the author may not be used to endorse or promote products 14 * derived from this software without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 20 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * Additional Copyright (c) 2002 by Matthew Jacob under same license. 29 */ 30 /* 31 * Copyright (c) 2004, Avid Technology, Inc. and its contributors. 32 * Copyright (c) 2005, WHEEL Sp. z o.o. 33 * Copyright (c) 2004, 2005 Justin T. Gibbs 34 * All rights reserved. 35 * 36 * Redistribution and use in source and binary forms, with or without 37 * modification, are permitted provided that the following conditions are 38 * met: 39 * 1. Redistributions of source code must retain the above copyright 40 * notice, this list of conditions and the following disclaimer. 41 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 42 * substantially similar to the "NO WARRANTY" disclaimer below 43 * ("Disclaimer") and any redistribution must be conditioned upon including 44 * a substantially similar Disclaimer requirement for further binary 45 * redistribution. 46 * 3. Neither the names of the above listed copyright holders nor the names 47 * of any contributors may be used to endorse or promote products derived 48 * from this software without specific prior written permission. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 51 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 54 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 60 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 61 */ 62 63 #include <sys/cdefs.h> 64 __FBSDID("$FreeBSD$"); 65 66 #include <dev/mpt/mpt.h> 67 #include <dev/mpt/mpt_cam.h> /* XXX For static handler registration */ 68 #include <dev/mpt/mpt_raid.h> /* XXX For static handler registration */ 69 70 #include <dev/mpt/mpilib/mpi.h> 71 #include <dev/mpt/mpilib/mpi_ioc.h> 72 73 #include <sys/sysctl.h> 74 75 #define MPT_MAX_TRYS 3 76 #define MPT_MAX_WAIT 300000 77 78 static int maxwait_ack = 0; 79 static int maxwait_int = 0; 80 static int maxwait_state = 0; 81 82 TAILQ_HEAD(, mpt_softc) mpt_tailq = TAILQ_HEAD_INITIALIZER(mpt_tailq); 83 mpt_reply_handler_t *mpt_reply_handlers[MPT_NUM_REPLY_HANDLERS]; 84 85 static mpt_reply_handler_t mpt_default_reply_handler; 86 static mpt_reply_handler_t mpt_config_reply_handler; 87 static mpt_reply_handler_t mpt_handshake_reply_handler; 88 static mpt_reply_handler_t mpt_event_reply_handler; 89 static void mpt_send_event_ack(struct mpt_softc *mpt, request_t *ack_req, 90 MSG_EVENT_NOTIFY_REPLY *msg, uint32_t context); 91 static int mpt_soft_reset(struct mpt_softc *mpt); 92 static void mpt_hard_reset(struct mpt_softc *mpt); 93 static int mpt_configure_ioc(struct mpt_softc *mpt); 94 static int mpt_enable_ioc(struct mpt_softc *mpt); 95 96 /************************* Personality Module Support *************************/ 97 /* 98 * We include one extra entry that is guaranteed to be NULL 99 * to simplify our itterator. 100 */ 101 static struct mpt_personality *mpt_personalities[MPT_MAX_PERSONALITIES + 1]; 102 static __inline struct mpt_personality* 103 mpt_pers_find(struct mpt_softc *, u_int); 104 static __inline struct mpt_personality* 105 mpt_pers_find_reverse(struct mpt_softc *, u_int); 106 107 static __inline struct mpt_personality * 108 mpt_pers_find(struct mpt_softc *mpt, u_int start_at) 109 { 110 KASSERT(start_at <= MPT_MAX_PERSONALITIES, 111 ("mpt_pers_find: starting position out of range\n")); 112 113 while (start_at < MPT_MAX_PERSONALITIES 114 && (mpt->mpt_pers_mask & (0x1 << start_at)) == 0) { 115 start_at++; 116 } 117 return (mpt_personalities[start_at]); 118 } 119 120 /* 121 * Used infrequenstly, so no need to optimize like a forward 122 * traversal where we use the MAX+1 is guaranteed to be NULL 123 * trick. 124 */ 125 static __inline struct mpt_personality * 126 mpt_pers_find_reverse(struct mpt_softc *mpt, u_int start_at) 127 { 128 while (start_at < MPT_MAX_PERSONALITIES 129 && (mpt->mpt_pers_mask & (0x1 << start_at)) == 0) { 130 start_at--; 131 } 132 if (start_at < MPT_MAX_PERSONALITIES) 133 return (mpt_personalities[start_at]); 134 return (NULL); 135 } 136 137 #define MPT_PERS_FOREACH(mpt, pers) \ 138 for (pers = mpt_pers_find(mpt, /*start_at*/0); \ 139 pers != NULL; \ 140 pers = mpt_pers_find(mpt, /*start_at*/pers->id+1)) 141 142 #define MPT_PERS_FOREACH_REVERSE(mpt, pers) \ 143 for (pers = mpt_pers_find_reverse(mpt, MPT_MAX_PERSONALITIES-1);\ 144 pers != NULL; \ 145 pers = mpt_pers_find_reverse(mpt, /*start_at*/pers->id-1)) 146 147 static mpt_load_handler_t mpt_stdload; 148 static mpt_probe_handler_t mpt_stdprobe; 149 static mpt_attach_handler_t mpt_stdattach; 150 static mpt_event_handler_t mpt_stdevent; 151 static mpt_reset_handler_t mpt_stdreset; 152 static mpt_shutdown_handler_t mpt_stdshutdown; 153 static mpt_detach_handler_t mpt_stddetach; 154 static mpt_unload_handler_t mpt_stdunload; 155 static struct mpt_personality mpt_default_personality = 156 { 157 .load = mpt_stdload, 158 .probe = mpt_stdprobe, 159 .attach = mpt_stdattach, 160 .event = mpt_stdevent, 161 .reset = mpt_stdreset, 162 .shutdown = mpt_stdshutdown, 163 .detach = mpt_stddetach, 164 .unload = mpt_stdunload 165 }; 166 167 static mpt_load_handler_t mpt_core_load; 168 static mpt_attach_handler_t mpt_core_attach; 169 static mpt_reset_handler_t mpt_core_ioc_reset; 170 static mpt_event_handler_t mpt_core_event; 171 static mpt_shutdown_handler_t mpt_core_shutdown; 172 static mpt_shutdown_handler_t mpt_core_detach; 173 static mpt_unload_handler_t mpt_core_unload; 174 static struct mpt_personality mpt_core_personality = 175 { 176 .name = "mpt_core", 177 .load = mpt_core_load, 178 .attach = mpt_core_attach, 179 .event = mpt_core_event, 180 .reset = mpt_core_ioc_reset, 181 .shutdown = mpt_core_shutdown, 182 .detach = mpt_core_detach, 183 .unload = mpt_core_unload, 184 }; 185 186 /* 187 * Manual declaration so that DECLARE_MPT_PERSONALITY doesn't need 188 * ordering information. We want the core to always register FIRST. 189 * other modules are set to SI_ORDER_SECOND. 190 */ 191 static moduledata_t mpt_core_mod = { 192 "mpt_core", mpt_modevent, &mpt_core_personality 193 }; 194 DECLARE_MODULE(mpt_core, mpt_core_mod, SI_SUB_DRIVERS, SI_ORDER_FIRST); 195 MODULE_VERSION(mpt_core, 1); 196 197 #define MPT_PERS_ATACHED(pers, mpt) \ 198 ((mpt)->pers_mask & (0x1 << pers->id)) 199 200 201 int 202 mpt_modevent(module_t mod, int type, void *data) 203 { 204 struct mpt_personality *pers; 205 int error; 206 207 pers = (struct mpt_personality *)data; 208 209 error = 0; 210 switch (type) { 211 case MOD_LOAD: 212 { 213 mpt_load_handler_t **def_handler; 214 mpt_load_handler_t **pers_handler; 215 int i; 216 217 for (i = 0; i < MPT_MAX_PERSONALITIES; i++) { 218 if (mpt_personalities[i] == NULL) 219 break; 220 } 221 if (i >= MPT_MAX_PERSONALITIES) { 222 error = ENOMEM; 223 break; 224 } 225 pers->id = i; 226 mpt_personalities[i] = pers; 227 228 /* Install standard/noop handlers for any NULL entries. */ 229 def_handler = MPT_PERS_FIRST_HANDLER(&mpt_default_personality); 230 pers_handler = MPT_PERS_FIRST_HANDLER(pers); 231 while (pers_handler <= MPT_PERS_LAST_HANDLER(pers)) { 232 if (*pers_handler == NULL) 233 *pers_handler = *def_handler; 234 pers_handler++; 235 def_handler++; 236 } 237 238 error = (pers->load(pers)); 239 if (error != 0) 240 mpt_personalities[i] = NULL; 241 break; 242 } 243 case MOD_SHUTDOWN: 244 break; 245 case MOD_QUIESCE: 246 break; 247 case MOD_UNLOAD: 248 error = pers->unload(pers); 249 mpt_personalities[pers->id] = NULL; 250 break; 251 default: 252 error = EINVAL; 253 break; 254 } 255 return (error); 256 } 257 258 int 259 mpt_stdload(struct mpt_personality *pers) 260 { 261 /* Load is always successfull. */ 262 return (0); 263 } 264 265 int 266 mpt_stdprobe(struct mpt_softc *mpt) 267 { 268 /* Probe is always successfull. */ 269 return (0); 270 } 271 272 int 273 mpt_stdattach(struct mpt_softc *mpt) 274 { 275 /* Attach is always successfull. */ 276 return (0); 277 } 278 279 int 280 mpt_stdevent(struct mpt_softc *mpt, request_t *req, MSG_EVENT_NOTIFY_REPLY *rep) 281 { 282 /* Event was not for us. */ 283 return (0); 284 } 285 286 void 287 mpt_stdreset(struct mpt_softc *mpt, int type) 288 { 289 } 290 291 void 292 mpt_stdshutdown(struct mpt_softc *mpt) 293 { 294 } 295 296 void 297 mpt_stddetach(struct mpt_softc *mpt) 298 { 299 } 300 301 int 302 mpt_stdunload(struct mpt_personality *pers) 303 { 304 /* Unload is always successfull. */ 305 return (0); 306 } 307 308 /******************************* Bus DMA Support ******************************/ 309 void 310 mpt_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) 311 { 312 struct mpt_map_info *map_info; 313 314 map_info = (struct mpt_map_info *)arg; 315 map_info->error = error; 316 map_info->phys = segs->ds_addr; 317 } 318 319 /**************************** Reply/Event Handling ****************************/ 320 int 321 mpt_register_handler(struct mpt_softc *mpt, mpt_handler_type type, 322 mpt_handler_t handler, uint32_t *phandler_id) 323 { 324 325 switch (type) { 326 case MPT_HANDLER_REPLY: 327 { 328 u_int cbi; 329 u_int free_cbi; 330 331 if (phandler_id == NULL) 332 return (EINVAL); 333 334 free_cbi = MPT_HANDLER_ID_NONE; 335 for (cbi = 0; cbi < MPT_NUM_REPLY_HANDLERS; cbi++) { 336 /* 337 * If the same handler is registered multiple 338 * times, don't error out. Just return the 339 * index of the original registration. 340 */ 341 if (mpt_reply_handlers[cbi] == handler.reply_handler) { 342 *phandler_id = MPT_CBI_TO_HID(cbi); 343 return (0); 344 } 345 346 /* 347 * Fill from the front in the hope that 348 * all registered handlers consume only a 349 * single cache line. 350 * 351 * We don't break on the first empty slot so 352 * that the full table is checked to see if 353 * this handler was previously registered. 354 */ 355 if (free_cbi == MPT_HANDLER_ID_NONE 356 && (mpt_reply_handlers[cbi] 357 == mpt_default_reply_handler)) 358 free_cbi = cbi; 359 } 360 if (free_cbi == MPT_HANDLER_ID_NONE) 361 return (ENOMEM); 362 mpt_reply_handlers[free_cbi] = handler.reply_handler; 363 *phandler_id = MPT_CBI_TO_HID(free_cbi); 364 break; 365 } 366 default: 367 mpt_prt(mpt, "mpt_register_handler unknown type %d\n", type); 368 return (EINVAL); 369 } 370 return (0); 371 } 372 373 int 374 mpt_deregister_handler(struct mpt_softc *mpt, mpt_handler_type type, 375 mpt_handler_t handler, uint32_t handler_id) 376 { 377 378 switch (type) { 379 case MPT_HANDLER_REPLY: 380 { 381 u_int cbi; 382 383 cbi = MPT_CBI(handler_id); 384 if (cbi >= MPT_NUM_REPLY_HANDLERS 385 || mpt_reply_handlers[cbi] != handler.reply_handler) 386 return (ENOENT); 387 mpt_reply_handlers[cbi] = mpt_default_reply_handler; 388 break; 389 } 390 default: 391 mpt_prt(mpt, "mpt_deregister_handler unknown type %d\n", type); 392 return (EINVAL); 393 } 394 return (0); 395 } 396 397 static int 398 mpt_default_reply_handler(struct mpt_softc *mpt, request_t *req, 399 MSG_DEFAULT_REPLY *reply_frame) 400 { 401 mpt_prt(mpt, "XXXX Default Handler Called. Req %p, Frame %p\n", 402 req, reply_frame); 403 404 if (reply_frame != NULL) 405 mpt_dump_reply_frame(mpt, reply_frame); 406 407 mpt_prt(mpt, "XXXX Reply Frame Ignored\n"); 408 409 return (/*free_reply*/TRUE); 410 } 411 412 static int 413 mpt_config_reply_handler(struct mpt_softc *mpt, request_t *req, 414 MSG_DEFAULT_REPLY *reply_frame) 415 { 416 if (req != NULL) { 417 418 if (reply_frame != NULL) { 419 MSG_CONFIG *cfgp; 420 MSG_CONFIG_REPLY *reply; 421 422 cfgp = (MSG_CONFIG *)req->req_vbuf; 423 reply = (MSG_CONFIG_REPLY *)reply_frame; 424 req->IOCStatus = le16toh(reply_frame->IOCStatus); 425 bcopy(&reply->Header, &cfgp->Header, 426 sizeof(cfgp->Header)); 427 } 428 req->state &= ~REQ_STATE_QUEUED; 429 req->state |= REQ_STATE_DONE; 430 TAILQ_REMOVE(&mpt->request_pending_list, req, links); 431 432 if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) 433 wakeup(req); 434 } 435 436 return (/*free_reply*/TRUE); 437 } 438 439 static int 440 mpt_handshake_reply_handler(struct mpt_softc *mpt, request_t *req, 441 MSG_DEFAULT_REPLY *reply_frame) 442 { 443 /* Nothing to be done. */ 444 return (/*free_reply*/TRUE); 445 } 446 447 static int 448 mpt_event_reply_handler(struct mpt_softc *mpt, request_t *req, 449 MSG_DEFAULT_REPLY *reply_frame) 450 { 451 int free_reply; 452 453 if (reply_frame == NULL) { 454 mpt_prt(mpt, "Event Handler: req %p - Unexpected NULL reply\n"); 455 return (/*free_reply*/TRUE); 456 } 457 458 free_reply = TRUE; 459 switch (reply_frame->Function) { 460 case MPI_FUNCTION_EVENT_NOTIFICATION: 461 { 462 MSG_EVENT_NOTIFY_REPLY *msg; 463 struct mpt_personality *pers; 464 u_int handled; 465 466 handled = 0; 467 msg = (MSG_EVENT_NOTIFY_REPLY *)reply_frame; 468 MPT_PERS_FOREACH(mpt, pers) 469 handled += pers->event(mpt, req, msg); 470 471 if (handled == 0) 472 mpt_prt(mpt, 473 "Unhandled Event Notify Frame. Event %#x.\n", 474 msg->Event); 475 476 if (msg->AckRequired) { 477 request_t *ack_req; 478 uint32_t context; 479 480 context = htole32(req->index|MPT_REPLY_HANDLER_EVENTS); 481 ack_req = mpt_get_request(mpt, /*sleep_ok*/FALSE); 482 if (ack_req == NULL) { 483 struct mpt_evtf_record *evtf; 484 485 evtf = (struct mpt_evtf_record *)reply_frame; 486 evtf->context = context; 487 LIST_INSERT_HEAD(&mpt->ack_frames, evtf, links); 488 free_reply = FALSE; 489 break; 490 } 491 mpt_send_event_ack(mpt, ack_req, msg, context); 492 } 493 break; 494 } 495 case MPI_FUNCTION_PORT_ENABLE: 496 mpt_lprt(mpt, MPT_PRT_DEBUG, "enable port reply\n"); 497 break; 498 case MPI_FUNCTION_EVENT_ACK: 499 break; 500 default: 501 mpt_prt(mpt, "Unknown Event Function: %x\n", 502 reply_frame->Function); 503 break; 504 } 505 506 if (req != NULL 507 && (reply_frame->MsgFlags & MPI_MSGFLAGS_CONTINUATION_REPLY) == 0) { 508 509 req->state &= ~REQ_STATE_QUEUED; 510 req->state |= REQ_STATE_DONE; 511 TAILQ_REMOVE(&mpt->request_pending_list, req, links); 512 513 if ((req->state & REQ_STATE_NEED_WAKEUP) != 0) 514 wakeup(req); 515 else 516 mpt_free_request(mpt, req); 517 } 518 return (free_reply); 519 } 520 521 /* 522 * Process an asynchronous event from the IOC. 523 */ 524 static int 525 mpt_core_event(struct mpt_softc *mpt, request_t *req, 526 MSG_EVENT_NOTIFY_REPLY *msg) 527 { 528 switch(msg->Event & 0xFF) { 529 case MPI_EVENT_NONE: 530 break; 531 case MPI_EVENT_LOG_DATA: 532 { 533 int i; 534 535 /* Some error occured that LSI wants logged */ 536 mpt_prt(mpt, "EvtLogData: IOCLogInfo: 0x%08x\n", 537 msg->IOCLogInfo); 538 mpt_prt(mpt, "\tEvtLogData: Event Data:"); 539 for (i = 0; i < msg->EventDataLength; i++) 540 mpt_prtc(mpt, " %08x", msg->Data[i]); 541 mpt_prtc(mpt, "\n"); 542 break; 543 } 544 case MPI_EVENT_EVENT_CHANGE: 545 /* 546 * This is just an acknowledgement 547 * of our mpt_send_event_request. 548 */ 549 break; 550 default: 551 return (/*handled*/0); 552 break; 553 } 554 return (/*handled*/1); 555 } 556 557 static void 558 mpt_send_event_ack(struct mpt_softc *mpt, request_t *ack_req, 559 MSG_EVENT_NOTIFY_REPLY *msg, uint32_t context) 560 { 561 MSG_EVENT_ACK *ackp; 562 563 ackp = (MSG_EVENT_ACK *)ack_req->req_vbuf; 564 bzero(ackp, sizeof *ackp); 565 ackp->Function = MPI_FUNCTION_EVENT_ACK; 566 ackp->Event = msg->Event; 567 ackp->EventContext = msg->EventContext; 568 ackp->MsgContext = context; 569 mpt_check_doorbell(mpt); 570 mpt_send_cmd(mpt, ack_req); 571 } 572 573 /***************************** Interrupt Handling *****************************/ 574 void 575 mpt_intr(void *arg) 576 { 577 struct mpt_softc *mpt; 578 uint32_t reply_desc; 579 580 mpt = (struct mpt_softc *)arg; 581 while ((reply_desc = mpt_pop_reply_queue(mpt)) != MPT_REPLY_EMPTY) { 582 request_t *req; 583 MSG_DEFAULT_REPLY *reply_frame; 584 uint32_t reply_baddr; 585 u_int cb_index; 586 u_int req_index; 587 int free_rf; 588 589 req = NULL; 590 reply_frame = NULL; 591 reply_baddr = 0; 592 if ((reply_desc & MPI_ADDRESS_REPLY_A_BIT) != 0) { 593 u_int offset; 594 595 /* 596 * Insure that the reply frame is coherent. 597 */ 598 reply_baddr = (reply_desc << 1); 599 offset = reply_baddr - (mpt->reply_phys & 0xFFFFFFFF); 600 bus_dmamap_sync_range(mpt->reply_dmat, mpt->reply_dmap, 601 offset, MPT_REPLY_SIZE, 602 BUS_DMASYNC_POSTREAD); 603 reply_frame = MPT_REPLY_OTOV(mpt, offset); 604 reply_desc = le32toh(reply_frame->MsgContext); 605 } 606 cb_index = MPT_CONTEXT_TO_CBI(reply_desc); 607 req_index = MPT_CONTEXT_TO_REQI(reply_desc); 608 if (req_index < MPT_MAX_REQUESTS(mpt)) 609 req = &mpt->request_pool[req_index]; 610 611 free_rf = mpt_reply_handlers[cb_index](mpt, req, reply_frame); 612 613 if (reply_frame != NULL && free_rf) 614 mpt_free_reply(mpt, reply_baddr); 615 } 616 } 617 618 /******************************* Error Recovery *******************************/ 619 void 620 mpt_complete_request_chain(struct mpt_softc *mpt, struct req_queue *chain, 621 u_int iocstatus) 622 { 623 MSG_DEFAULT_REPLY ioc_status_frame; 624 request_t *req; 625 626 bzero(&ioc_status_frame, sizeof(ioc_status_frame)); 627 ioc_status_frame.MsgLength = roundup2(sizeof(ioc_status_frame), 4); 628 ioc_status_frame.IOCStatus = iocstatus; 629 while((req = TAILQ_FIRST(chain)) != NULL) { 630 MSG_REQUEST_HEADER *msg_hdr; 631 u_int cb_index; 632 633 msg_hdr = (MSG_REQUEST_HEADER *)req->req_vbuf; 634 ioc_status_frame.Function = msg_hdr->Function; 635 ioc_status_frame.MsgContext = msg_hdr->MsgContext; 636 cb_index = MPT_CONTEXT_TO_CBI(le32toh(msg_hdr->MsgContext)); 637 mpt_reply_handlers[cb_index](mpt, req, &ioc_status_frame); 638 } 639 } 640 641 /********************************* Diagnostics ********************************/ 642 /* 643 * Perform a diagnostic dump of a reply frame. 644 */ 645 void 646 mpt_dump_reply_frame(struct mpt_softc *mpt, MSG_DEFAULT_REPLY *reply_frame) 647 { 648 649 mpt_prt(mpt, "Address Reply:\n"); 650 mpt_print_reply(reply_frame); 651 } 652 653 /******************************* Doorbell Access ******************************/ 654 static __inline uint32_t mpt_rd_db(struct mpt_softc *mpt); 655 static __inline uint32_t mpt_rd_intr(struct mpt_softc *mpt); 656 657 static __inline uint32_t 658 mpt_rd_db(struct mpt_softc *mpt) 659 { 660 return mpt_read(mpt, MPT_OFFSET_DOORBELL); 661 } 662 663 static __inline uint32_t 664 mpt_rd_intr(struct mpt_softc *mpt) 665 { 666 return mpt_read(mpt, MPT_OFFSET_INTR_STATUS); 667 } 668 669 /* Busy wait for a door bell to be read by IOC */ 670 static int 671 mpt_wait_db_ack(struct mpt_softc *mpt) 672 { 673 int i; 674 for (i=0; i < MPT_MAX_WAIT; i++) { 675 if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) { 676 maxwait_ack = i > maxwait_ack ? i : maxwait_ack; 677 return MPT_OK; 678 } 679 680 DELAY(1000); 681 } 682 return MPT_FAIL; 683 } 684 685 /* Busy wait for a door bell interrupt */ 686 static int 687 mpt_wait_db_int(struct mpt_softc *mpt) 688 { 689 int i; 690 for (i=0; i < MPT_MAX_WAIT; i++) { 691 if (MPT_DB_INTR(mpt_rd_intr(mpt))) { 692 maxwait_int = i > maxwait_int ? i : maxwait_int; 693 return MPT_OK; 694 } 695 DELAY(100); 696 } 697 return MPT_FAIL; 698 } 699 700 /* Wait for IOC to transition to a give state */ 701 void 702 mpt_check_doorbell(struct mpt_softc *mpt) 703 { 704 uint32_t db = mpt_rd_db(mpt); 705 if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) { 706 mpt_prt(mpt, "Device not running\n"); 707 mpt_print_db(db); 708 } 709 } 710 711 /* Wait for IOC to transition to a give state */ 712 static int 713 mpt_wait_state(struct mpt_softc *mpt, enum DB_STATE_BITS state) 714 { 715 int i; 716 717 for (i = 0; i < MPT_MAX_WAIT; i++) { 718 uint32_t db = mpt_rd_db(mpt); 719 if (MPT_STATE(db) == state) { 720 maxwait_state = i > maxwait_state ? i : maxwait_state; 721 return (MPT_OK); 722 } 723 DELAY(100); 724 } 725 return (MPT_FAIL); 726 } 727 728 729 /************************* Intialization/Configuration ************************/ 730 static int mpt_download_fw(struct mpt_softc *mpt); 731 732 /* Issue the reset COMMAND to the IOC */ 733 static int 734 mpt_soft_reset(struct mpt_softc *mpt) 735 { 736 mpt_lprt(mpt, MPT_PRT_DEBUG, "soft reset\n"); 737 738 /* Have to use hard reset if we are not in Running state */ 739 if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) { 740 mpt_prt(mpt, "soft reset failed: device not running\n"); 741 return MPT_FAIL; 742 } 743 744 /* If door bell is in use we don't have a chance of getting 745 * a word in since the IOC probably crashed in message 746 * processing. So don't waste our time. 747 */ 748 if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) { 749 mpt_prt(mpt, "soft reset failed: doorbell wedged\n"); 750 return MPT_FAIL; 751 } 752 753 /* Send the reset request to the IOC */ 754 mpt_write(mpt, MPT_OFFSET_DOORBELL, 755 MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT); 756 if (mpt_wait_db_ack(mpt) != MPT_OK) { 757 mpt_prt(mpt, "soft reset failed: ack timeout\n"); 758 return MPT_FAIL; 759 } 760 761 /* Wait for the IOC to reload and come out of reset state */ 762 if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) { 763 mpt_prt(mpt, "soft reset failed: device did not restart\n"); 764 return MPT_FAIL; 765 } 766 767 return MPT_OK; 768 } 769 770 static int 771 mpt_enable_diag_mode(struct mpt_softc *mpt) 772 { 773 int try; 774 775 try = 20; 776 while (--try) { 777 778 if ((mpt_read(mpt, MPT_OFFSET_DIAGNOSTIC) & MPI_DIAG_DRWE) != 0) 779 break; 780 781 /* Enable diagnostic registers */ 782 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF); 783 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPI_WRSEQ_1ST_KEY_VALUE); 784 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPI_WRSEQ_2ND_KEY_VALUE); 785 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPI_WRSEQ_3RD_KEY_VALUE); 786 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPI_WRSEQ_4TH_KEY_VALUE); 787 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPI_WRSEQ_5TH_KEY_VALUE); 788 789 DELAY(100000); 790 } 791 if (try == 0) 792 return (EIO); 793 return (0); 794 } 795 796 static void 797 mpt_disable_diag_mode(struct mpt_softc *mpt) 798 { 799 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFFFFFFFF); 800 } 801 802 /* This is a magic diagnostic reset that resets all the ARM 803 * processors in the chip. 804 */ 805 static void 806 mpt_hard_reset(struct mpt_softc *mpt) 807 { 808 int error; 809 int wait; 810 uint32_t diagreg; 811 812 mpt_lprt(mpt, MPT_PRT_DEBUG, "hard reset\n"); 813 814 error = mpt_enable_diag_mode(mpt); 815 if (error) { 816 mpt_prt(mpt, "WARNING - Could not enter diagnostic mode !\n"); 817 mpt_prt(mpt, "Trying to reset anyway.\n"); 818 } 819 820 diagreg = mpt_read(mpt, MPT_OFFSET_DIAGNOSTIC); 821 822 /* 823 * This appears to be a workaround required for some 824 * firmware or hardware revs. 825 */ 826 mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, diagreg | MPI_DIAG_DISABLE_ARM); 827 DELAY(1000); 828 829 /* Diag. port is now active so we can now hit the reset bit */ 830 mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, diagreg | MPI_DIAG_RESET_ADAPTER); 831 832 /* 833 * Ensure that the reset has finished. We delay 1ms 834 * prior to reading the register to make sure the chip 835 * has sufficiently completed its reset to handle register 836 * accesses. 837 */ 838 wait = 5000; 839 do { 840 DELAY(1000); 841 diagreg = mpt_read(mpt, MPT_OFFSET_DIAGNOSTIC); 842 } while (--wait && (diagreg & MPI_DIAG_RESET_ADAPTER) == 0); 843 844 if (wait == 0) { 845 mpt_prt(mpt, "WARNING - Failed hard reset! " 846 "Trying to initialize anyway.\n"); 847 } 848 849 /* 850 * If we have firmware to download, it must be loaded before 851 * the controller will become operational. Do so now. 852 */ 853 if (mpt->fw_image != NULL) { 854 855 error = mpt_download_fw(mpt); 856 857 if (error) { 858 mpt_prt(mpt, "WARNING - Firmware Download Failed!\n"); 859 mpt_prt(mpt, "Trying to initialize anyway.\n"); 860 } 861 } 862 863 /* 864 * Reseting the controller should have disabled write 865 * access to the diagnostic registers, but disable 866 * manually to be sure. 867 */ 868 mpt_disable_diag_mode(mpt); 869 } 870 871 static void 872 mpt_core_ioc_reset(struct mpt_softc *mpt, int type) 873 { 874 /* 875 * Complete all pending requests with a status 876 * appropriate for an IOC reset. 877 */ 878 mpt_complete_request_chain(mpt, &mpt->request_pending_list, 879 MPI_IOCSTATUS_INVALID_STATE); 880 } 881 882 883 /* 884 * Reset the IOC when needed. Try software command first then if needed 885 * poke at the magic diagnostic reset. Note that a hard reset resets 886 * *both* IOCs on dual function chips (FC929 && LSI1030) as well as 887 * fouls up the PCI configuration registers. 888 */ 889 int 890 mpt_reset(struct mpt_softc *mpt, int reinit) 891 { 892 struct mpt_personality *pers; 893 int ret; 894 895 /* Try a soft reset */ 896 if ((ret = mpt_soft_reset(mpt)) != MPT_OK) { 897 /* Failed; do a hard reset */ 898 mpt_hard_reset(mpt); 899 900 /* Wait for the IOC to reload and come out of reset state */ 901 ret = mpt_wait_state(mpt, MPT_DB_STATE_READY); 902 if (ret != MPT_OK) 903 mpt_prt(mpt, "failed to reset device\n"); 904 } 905 906 /* 907 * Invoke reset handlers. We bump the reset count so 908 * that mpt_wait_req() understands that regardless of 909 * the specified wait condition, it should stop its wait. 910 */ 911 mpt->reset_cnt++; 912 MPT_PERS_FOREACH(mpt, pers) 913 pers->reset(mpt, ret); 914 915 if (reinit != 0) 916 mpt_enable_ioc(mpt); 917 918 return ret; 919 } 920 921 /* Return a command buffer to the free queue */ 922 void 923 mpt_free_request(struct mpt_softc *mpt, request_t *req) 924 { 925 struct mpt_evtf_record *record; 926 uint32_t reply_baddr; 927 928 if (req == NULL || req != &mpt->request_pool[req->index]) { 929 panic("mpt_free_request bad req ptr\n"); 930 return; 931 } 932 req->ccb = NULL; 933 req->state = REQ_STATE_FREE; 934 if (LIST_EMPTY(&mpt->ack_frames)) { 935 TAILQ_INSERT_HEAD(&mpt->request_free_list, req, links); 936 if (mpt->getreqwaiter != 0) { 937 mpt->getreqwaiter = 0; 938 wakeup(&mpt->request_free_list); 939 } 940 return; 941 } 942 943 /* 944 * Process an ack frame deferred due to resource shortage. 945 */ 946 record = LIST_FIRST(&mpt->ack_frames); 947 LIST_REMOVE(record, links); 948 mpt_send_event_ack(mpt, req, &record->reply, record->context); 949 reply_baddr = (uint32_t)((uint8_t *)record - mpt->reply) 950 + (mpt->reply_phys & 0xFFFFFFFF); 951 mpt_free_reply(mpt, reply_baddr); 952 } 953 954 /* Get a command buffer from the free queue */ 955 request_t * 956 mpt_get_request(struct mpt_softc *mpt, int sleep_ok) 957 { 958 request_t *req; 959 960 retry: 961 req = TAILQ_FIRST(&mpt->request_free_list); 962 if (req != NULL) { 963 KASSERT(req == &mpt->request_pool[req->index], 964 ("mpt_get_request: corrupted request free list\n")); 965 TAILQ_REMOVE(&mpt->request_free_list, req, links); 966 req->state = REQ_STATE_ALLOCATED; 967 } else if (sleep_ok != 0) { 968 mpt->getreqwaiter = 1; 969 mpt_sleep(mpt, &mpt->request_free_list, PUSER, "mptgreq", 0); 970 goto retry; 971 } 972 return req; 973 } 974 975 /* Pass the command to the IOC */ 976 void 977 mpt_send_cmd(struct mpt_softc *mpt, request_t *req) 978 { 979 uint32_t *pReq; 980 981 pReq = req->req_vbuf; 982 mpt_lprt(mpt, MPT_PRT_TRACE, "Send Request %d (0x%x):\n", 983 req->index, req->req_pbuf); 984 mpt_lprt(mpt, MPT_PRT_TRACE, "%08x %08x %08x %08x\n", 985 pReq[0], pReq[1], pReq[2], pReq[3]); 986 mpt_lprt(mpt, MPT_PRT_TRACE, "%08x %08x %08x %08x\n", 987 pReq[4], pReq[5], pReq[6], pReq[7]); 988 mpt_lprt(mpt, MPT_PRT_TRACE, "%08x %08x %08x %08x\n", 989 pReq[8], pReq[9], pReq[10], pReq[11]); 990 mpt_lprt(mpt, MPT_PRT_TRACE, "%08x %08x %08x %08x\n", 991 pReq[12], pReq[13], pReq[14], pReq[15]); 992 993 bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap, 994 BUS_DMASYNC_PREWRITE); 995 req->state |= REQ_STATE_QUEUED; 996 TAILQ_INSERT_HEAD(&mpt->request_pending_list, req, links); 997 mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (uint32_t) req->req_pbuf); 998 } 999 1000 /* 1001 * Wait for a request to complete. 1002 * 1003 * Inputs: 1004 * mpt softc of controller executing request 1005 * req request to wait for 1006 * sleep_ok nonzero implies may sleep in this context 1007 * time_ms timeout in ms. 0 implies no timeout. 1008 * 1009 * Return Values: 1010 * 0 Request completed 1011 * non-0 Timeout fired before request completion. 1012 */ 1013 int 1014 mpt_wait_req(struct mpt_softc *mpt, request_t *req, 1015 mpt_req_state_t state, mpt_req_state_t mask, 1016 int sleep_ok, int time_ms) 1017 { 1018 int error; 1019 int timeout; 1020 u_int saved_cnt; 1021 1022 /* 1023 * timeout is in ms. 0 indicates infinite wait. 1024 * Convert to ticks or 500us units depending on 1025 * our sleep mode. 1026 */ 1027 if (sleep_ok != 0) 1028 timeout = (time_ms * hz) / 1000; 1029 else 1030 timeout = time_ms * 2; 1031 saved_cnt = mpt->reset_cnt; 1032 req->state |= REQ_STATE_NEED_WAKEUP; 1033 mask &= ~REQ_STATE_NEED_WAKEUP; 1034 while ((req->state & mask) != state 1035 && mpt->reset_cnt == saved_cnt) { 1036 1037 if (sleep_ok != 0) { 1038 error = mpt_sleep(mpt, req, PUSER, "mptreq", timeout); 1039 if (error == EWOULDBLOCK) { 1040 timeout = 0; 1041 break; 1042 } 1043 } else { 1044 if (time_ms != 0 && --timeout == 0) { 1045 mpt_prt(mpt, "mpt_wait_req timed out\n"); 1046 break; 1047 } 1048 DELAY(500); 1049 mpt_intr(mpt); 1050 } 1051 } 1052 req->state &= ~REQ_STATE_NEED_WAKEUP; 1053 if (mpt->reset_cnt != saved_cnt) 1054 return (EIO); 1055 if (time_ms && timeout == 0) 1056 return (ETIMEDOUT); 1057 return (0); 1058 } 1059 1060 /* 1061 * Send a command to the IOC via the handshake register. 1062 * 1063 * Only done at initialization time and for certain unusual 1064 * commands such as device/bus reset as specified by LSI. 1065 */ 1066 int 1067 mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd) 1068 { 1069 int i; 1070 uint32_t data, *data32; 1071 1072 /* Check condition of the IOC */ 1073 data = mpt_rd_db(mpt); 1074 if ((MPT_STATE(data) != MPT_DB_STATE_READY 1075 && MPT_STATE(data) != MPT_DB_STATE_RUNNING 1076 && MPT_STATE(data) != MPT_DB_STATE_FAULT) 1077 || MPT_DB_IS_IN_USE(data)) { 1078 mpt_prt(mpt, "handshake aborted - invalid doorbell state\n"); 1079 mpt_print_db(data); 1080 return (EBUSY); 1081 } 1082 1083 /* We move things in 32 bit chunks */ 1084 len = (len + 3) >> 2; 1085 data32 = cmd; 1086 1087 /* Clear any left over pending doorbell interupts */ 1088 if (MPT_DB_INTR(mpt_rd_intr(mpt))) 1089 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 1090 1091 /* 1092 * Tell the handshake reg. we are going to send a command 1093 * and how long it is going to be. 1094 */ 1095 data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) | 1096 (len << MPI_DOORBELL_ADD_DWORDS_SHIFT); 1097 mpt_write(mpt, MPT_OFFSET_DOORBELL, data); 1098 1099 /* Wait for the chip to notice */ 1100 if (mpt_wait_db_int(mpt) != MPT_OK) { 1101 mpt_prt(mpt, "mpt_send_handshake_cmd timeout1\n"); 1102 return (ETIMEDOUT); 1103 } 1104 1105 /* Clear the interrupt */ 1106 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 1107 1108 if (mpt_wait_db_ack(mpt) != MPT_OK) { 1109 mpt_prt(mpt, "mpt_send_handshake_cmd timeout2\n"); 1110 return (ETIMEDOUT); 1111 } 1112 1113 /* Send the command */ 1114 for (i = 0; i < len; i++) { 1115 mpt_write(mpt, MPT_OFFSET_DOORBELL, *data32++); 1116 if (mpt_wait_db_ack(mpt) != MPT_OK) { 1117 mpt_prt(mpt, 1118 "mpt_send_handshake_cmd timeout! index = %d\n", 1119 i); 1120 return (ETIMEDOUT); 1121 } 1122 } 1123 return MPT_OK; 1124 } 1125 1126 /* Get the response from the handshake register */ 1127 int 1128 mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply) 1129 { 1130 int left, reply_left; 1131 u_int16_t *data16; 1132 MSG_DEFAULT_REPLY *hdr; 1133 1134 /* We move things out in 16 bit chunks */ 1135 reply_len >>= 1; 1136 data16 = (u_int16_t *)reply; 1137 1138 hdr = (MSG_DEFAULT_REPLY *)reply; 1139 1140 /* Get first word */ 1141 if (mpt_wait_db_int(mpt) != MPT_OK) { 1142 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1\n"); 1143 return ETIMEDOUT; 1144 } 1145 *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK; 1146 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 1147 1148 /* Get Second Word */ 1149 if (mpt_wait_db_int(mpt) != MPT_OK) { 1150 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2\n"); 1151 return ETIMEDOUT; 1152 } 1153 *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK; 1154 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 1155 1156 /* With the second word, we can now look at the length */ 1157 if (((reply_len >> 1) != hdr->MsgLength)) { 1158 mpt_prt(mpt, "reply length does not match message length: " 1159 "got 0x%02x, expected 0x%02x\n", 1160 hdr->MsgLength << 2, reply_len << 1); 1161 } 1162 1163 /* Get rest of the reply; but don't overflow the provided buffer */ 1164 left = (hdr->MsgLength << 1) - 2; 1165 reply_left = reply_len - 2; 1166 while (left--) { 1167 u_int16_t datum; 1168 1169 if (mpt_wait_db_int(mpt) != MPT_OK) { 1170 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3\n"); 1171 return ETIMEDOUT; 1172 } 1173 datum = mpt_read(mpt, MPT_OFFSET_DOORBELL); 1174 1175 if (reply_left-- > 0) 1176 *data16++ = datum & MPT_DB_DATA_MASK; 1177 1178 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 1179 } 1180 1181 /* One more wait & clear at the end */ 1182 if (mpt_wait_db_int(mpt) != MPT_OK) { 1183 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4\n"); 1184 return ETIMEDOUT; 1185 } 1186 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 1187 1188 if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 1189 if (mpt->verbose >= MPT_PRT_TRACE) 1190 mpt_print_reply(hdr); 1191 return (MPT_FAIL | hdr->IOCStatus); 1192 } 1193 1194 return (0); 1195 } 1196 1197 static int 1198 mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp) 1199 { 1200 MSG_IOC_FACTS f_req; 1201 int error; 1202 1203 bzero(&f_req, sizeof f_req); 1204 f_req.Function = MPI_FUNCTION_IOC_FACTS; 1205 f_req.MsgContext = htole32(MPT_REPLY_HANDLER_HANDSHAKE); 1206 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req); 1207 if (error) 1208 return(error); 1209 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp); 1210 return (error); 1211 } 1212 1213 static int 1214 mpt_get_portfacts(struct mpt_softc *mpt, MSG_PORT_FACTS_REPLY *freplp) 1215 { 1216 MSG_PORT_FACTS f_req; 1217 int error; 1218 1219 /* XXX: Only getting PORT FACTS for Port 0 */ 1220 memset(&f_req, 0, sizeof f_req); 1221 f_req.Function = MPI_FUNCTION_PORT_FACTS; 1222 f_req.MsgContext = htole32(MPT_REPLY_HANDLER_HANDSHAKE); 1223 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req); 1224 if (error) 1225 return(error); 1226 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp); 1227 return (error); 1228 } 1229 1230 /* 1231 * Send the initialization request. This is where we specify how many 1232 * SCSI busses and how many devices per bus we wish to emulate. 1233 * This is also the command that specifies the max size of the reply 1234 * frames from the IOC that we will be allocating. 1235 */ 1236 static int 1237 mpt_send_ioc_init(struct mpt_softc *mpt, uint32_t who) 1238 { 1239 int error = 0; 1240 MSG_IOC_INIT init; 1241 MSG_IOC_INIT_REPLY reply; 1242 1243 bzero(&init, sizeof init); 1244 init.WhoInit = who; 1245 init.Function = MPI_FUNCTION_IOC_INIT; 1246 if (mpt->is_fc) { 1247 init.MaxDevices = 255; 1248 } else { 1249 init.MaxDevices = 16; 1250 } 1251 init.MaxBuses = 1; 1252 init.ReplyFrameSize = MPT_REPLY_SIZE; 1253 init.MsgContext = htole32(MPT_REPLY_HANDLER_HANDSHAKE); 1254 1255 if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) { 1256 return(error); 1257 } 1258 1259 error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply); 1260 return (error); 1261 } 1262 1263 1264 /* 1265 * Utiltity routine to read configuration headers and pages 1266 */ 1267 int 1268 mpt_issue_cfg_req(struct mpt_softc *mpt, request_t *req, u_int Action, 1269 u_int PageVersion, u_int PageLength, u_int PageNumber, 1270 u_int PageType, uint32_t PageAddress, bus_addr_t addr, 1271 bus_size_t len, int sleep_ok, int timeout_ms) 1272 { 1273 MSG_CONFIG *cfgp; 1274 SGE_SIMPLE32 *se; 1275 1276 cfgp = req->req_vbuf; 1277 memset(cfgp, 0, sizeof *cfgp); 1278 cfgp->Action = Action; 1279 cfgp->Function = MPI_FUNCTION_CONFIG; 1280 cfgp->Header.PageVersion = PageVersion; 1281 cfgp->Header.PageLength = PageLength; 1282 cfgp->Header.PageNumber = PageNumber; 1283 cfgp->Header.PageType = PageType; 1284 cfgp->PageAddress = PageAddress; 1285 se = (SGE_SIMPLE32 *)&cfgp->PageBufferSGE; 1286 se->Address = addr; 1287 MPI_pSGE_SET_LENGTH(se, len); 1288 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 1289 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 1290 MPI_SGE_FLAGS_END_OF_LIST | 1291 ((Action == MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT 1292 || Action == MPI_CONFIG_ACTION_PAGE_WRITE_NVRAM) 1293 ? MPI_SGE_FLAGS_HOST_TO_IOC : MPI_SGE_FLAGS_IOC_TO_HOST))); 1294 cfgp->MsgContext = htole32(req->index | MPT_REPLY_HANDLER_CONFIG); 1295 1296 mpt_check_doorbell(mpt); 1297 mpt_send_cmd(mpt, req); 1298 return (mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, 1299 sleep_ok, timeout_ms)); 1300 } 1301 1302 1303 int 1304 mpt_read_cfg_header(struct mpt_softc *mpt, int PageType, int PageNumber, 1305 uint32_t PageAddress, CONFIG_PAGE_HEADER *rslt, 1306 int sleep_ok, int timeout_ms) 1307 { 1308 request_t *req; 1309 int error; 1310 1311 req = mpt_get_request(mpt, sleep_ok); 1312 if (req == NULL) { 1313 mpt_prt(mpt, "mpt_read_cfg_header: Get request failed!\n"); 1314 return (-1); 1315 } 1316 1317 error = mpt_issue_cfg_req(mpt, req, MPI_CONFIG_ACTION_PAGE_HEADER, 1318 /*PageVersion*/0, /*PageLength*/0, PageNumber, 1319 PageType, PageAddress, /*addr*/0, /*len*/0, 1320 sleep_ok, timeout_ms); 1321 if (error != 0) { 1322 mpt_prt(mpt, "read_cfg_header timed out\n"); 1323 return (-1); 1324 } 1325 1326 if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 1327 mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x\n", 1328 req->IOCStatus); 1329 error = -1; 1330 } else { 1331 MSG_CONFIG *cfgp; 1332 1333 cfgp = req->req_vbuf; 1334 bcopy(&cfgp->Header, rslt, sizeof(*rslt)); 1335 error = 0; 1336 } 1337 mpt_free_request(mpt, req); 1338 return (error); 1339 } 1340 1341 #define CFG_DATA_OFF 128 1342 1343 int 1344 mpt_read_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress, 1345 CONFIG_PAGE_HEADER *hdr, size_t len, int sleep_ok, 1346 int timeout_ms) 1347 { 1348 request_t *req; 1349 int error; 1350 1351 req = mpt_get_request(mpt, sleep_ok); 1352 if (req == NULL) { 1353 mpt_prt(mpt, "mpt_read_cfg_page: Get request failed!\n"); 1354 return (-1); 1355 } 1356 1357 error = mpt_issue_cfg_req(mpt, req, Action, hdr->PageVersion, 1358 hdr->PageLength, hdr->PageNumber, 1359 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK, 1360 PageAddress, req->req_pbuf + CFG_DATA_OFF, 1361 len, sleep_ok, timeout_ms); 1362 if (error != 0) { 1363 mpt_prt(mpt, "read_cfg_page(%d) timed out\n", Action); 1364 return (-1); 1365 } 1366 1367 if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 1368 mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x\n", 1369 req->IOCStatus); 1370 mpt_free_request(mpt, req); 1371 return (-1); 1372 } 1373 bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap, 1374 BUS_DMASYNC_POSTREAD); 1375 memcpy(hdr, ((uint8_t *)req->req_vbuf)+CFG_DATA_OFF, len); 1376 mpt_free_request(mpt, req); 1377 return (0); 1378 } 1379 1380 int 1381 mpt_write_cfg_page(struct mpt_softc *mpt, int Action, uint32_t PageAddress, 1382 CONFIG_PAGE_HEADER *hdr, size_t len, int sleep_ok, 1383 int timeout_ms) 1384 { 1385 request_t *req; 1386 u_int hdr_attr; 1387 int error; 1388 1389 hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK; 1390 if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE && 1391 hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) { 1392 mpt_prt(mpt, "page type 0x%x not changeable\n", 1393 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); 1394 return (-1); 1395 } 1396 hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK, 1397 1398 req = mpt_get_request(mpt, sleep_ok); 1399 if (req == NULL) 1400 return (-1); 1401 1402 memcpy(((caddr_t)req->req_vbuf)+CFG_DATA_OFF, hdr, len); 1403 /* Restore stripped out attributes */ 1404 hdr->PageType |= hdr_attr; 1405 1406 error = mpt_issue_cfg_req(mpt, req, Action, hdr->PageVersion, 1407 hdr->PageLength, hdr->PageNumber, 1408 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK, 1409 PageAddress, req->req_pbuf + CFG_DATA_OFF, 1410 len, sleep_ok, timeout_ms); 1411 if (error != 0) { 1412 mpt_prt(mpt, "mpt_write_cfg_page timed out\n"); 1413 return (-1); 1414 } 1415 1416 if ((req->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 1417 mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x\n", 1418 req->IOCStatus); 1419 mpt_free_request(mpt, req); 1420 return (-1); 1421 } 1422 mpt_free_request(mpt, req); 1423 return (0); 1424 } 1425 1426 /* 1427 * Read IOC configuration information 1428 */ 1429 static int 1430 mpt_read_config_info_ioc(struct mpt_softc *mpt) 1431 { 1432 CONFIG_PAGE_HEADER hdr; 1433 struct mpt_raid_volume *mpt_raid; 1434 int rv; 1435 int i; 1436 size_t len; 1437 1438 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_IOC, 1439 /*PageNumber*/2, /*PageAddress*/0, &hdr, 1440 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1441 if (rv) 1442 return (EIO); 1443 1444 mpt_lprt(mpt, MPT_PRT_DEBUG, "IOC Page 2 Header: ver %x, len %x, " 1445 "num %x, type %x\n", hdr.PageVersion, 1446 hdr.PageLength * sizeof(uint32_t), 1447 hdr.PageNumber, hdr.PageType); 1448 1449 len = hdr.PageLength * sizeof(uint32_t); 1450 mpt->ioc_page2 = malloc(len, M_DEVBUF, M_NOWAIT); 1451 if (mpt->ioc_page2 == NULL) 1452 return (ENOMEM); 1453 memset(mpt->ioc_page2, 0, sizeof(*mpt->ioc_page2)); 1454 memcpy(&mpt->ioc_page2->Header, &hdr, sizeof(hdr)); 1455 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1456 &mpt->ioc_page2->Header, len, 1457 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1458 if (rv) { 1459 mpt_prt(mpt, "failed to read IOC Page 2\n"); 1460 } else if (mpt->ioc_page2->CapabilitiesFlags != 0) { 1461 uint32_t mask; 1462 1463 mpt_prt(mpt, "Capabilities: ("); 1464 for (mask = 1; mask != 0; mask <<= 1) { 1465 if ((mpt->ioc_page2->CapabilitiesFlags & mask) == 0) 1466 continue; 1467 1468 switch (mask) { 1469 case MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT: 1470 mpt_prtc(mpt, " RAID-0"); 1471 break; 1472 case MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT: 1473 mpt_prtc(mpt, " RAID-1E"); 1474 break; 1475 case MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT: 1476 mpt_prtc(mpt, " RAID-1"); 1477 break; 1478 case MPI_IOCPAGE2_CAP_FLAGS_SES_SUPPORT: 1479 mpt_prtc(mpt, " SES"); 1480 break; 1481 case MPI_IOCPAGE2_CAP_FLAGS_SAFTE_SUPPORT: 1482 mpt_prtc(mpt, " SAFTE"); 1483 break; 1484 case MPI_IOCPAGE2_CAP_FLAGS_CROSS_CHANNEL_SUPPORT: 1485 mpt_prtc(mpt, " Multi-Channel-Arrays"); 1486 default: 1487 break; 1488 } 1489 } 1490 mpt_prtc(mpt, " )\n"); 1491 if ((mpt->ioc_page2->CapabilitiesFlags 1492 & (MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT 1493 | MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT 1494 | MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT)) != 0) { 1495 mpt_prt(mpt, "%d Active Volume%s(%d Max)\n", 1496 mpt->ioc_page2->NumActiveVolumes, 1497 mpt->ioc_page2->NumActiveVolumes != 1 1498 ? "s " : " ", 1499 mpt->ioc_page2->MaxVolumes); 1500 mpt_prt(mpt, "%d Hidden Drive Member%s(%d Max)\n", 1501 mpt->ioc_page2->NumActivePhysDisks, 1502 mpt->ioc_page2->NumActivePhysDisks != 1 1503 ? "s " : " ", 1504 mpt->ioc_page2->MaxPhysDisks); 1505 } 1506 } 1507 1508 len = mpt->ioc_page2->MaxVolumes * sizeof(struct mpt_raid_volume); 1509 mpt->raid_volumes = malloc(len, M_DEVBUF, M_NOWAIT); 1510 if (mpt->raid_volumes == NULL) { 1511 mpt_prt(mpt, "Could not allocate RAID volume data\n"); 1512 } else { 1513 memset(mpt->raid_volumes, 0, len); 1514 } 1515 1516 /* 1517 * Copy critical data out of ioc_page2 so that we can 1518 * safely refresh the page without windows of unreliable 1519 * data. 1520 */ 1521 mpt->raid_max_volumes = mpt->ioc_page2->MaxVolumes; 1522 1523 len = sizeof(*mpt->raid_volumes->config_page) 1524 + (sizeof(RAID_VOL0_PHYS_DISK)*(mpt->ioc_page2->MaxPhysDisks - 1)); 1525 for (i = 0; i < mpt->ioc_page2->MaxVolumes; i++) { 1526 mpt_raid = &mpt->raid_volumes[i]; 1527 mpt_raid->config_page = malloc(len, M_DEVBUF, M_NOWAIT); 1528 if (mpt_raid->config_page == NULL) { 1529 mpt_prt(mpt, "Could not allocate RAID page data\n"); 1530 break; 1531 } 1532 memset(mpt_raid->config_page, 0, len); 1533 } 1534 mpt->raid_page0_len = len; 1535 1536 len = mpt->ioc_page2->MaxPhysDisks * sizeof(struct mpt_raid_disk); 1537 mpt->raid_disks = malloc(len, M_DEVBUF, M_NOWAIT); 1538 if (mpt->raid_disks == NULL) { 1539 mpt_prt(mpt, "Could not allocate RAID disk data\n"); 1540 } else { 1541 memset(mpt->raid_disks, 0, len); 1542 } 1543 1544 mpt->raid_max_disks = mpt->ioc_page2->MaxPhysDisks; 1545 1546 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_IOC, 1547 /*PageNumber*/3, /*PageAddress*/0, &hdr, 1548 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1549 if (rv) 1550 return (EIO); 1551 1552 mpt_lprt(mpt, MPT_PRT_DEBUG, "IOC Page 3 Header: %x %x %x %x\n", 1553 hdr.PageVersion, hdr.PageLength, hdr.PageNumber, hdr.PageType); 1554 1555 if (mpt->ioc_page3 != NULL) 1556 free(mpt->ioc_page3, M_DEVBUF); 1557 len = hdr.PageLength * sizeof(uint32_t); 1558 mpt->ioc_page3 = malloc(len, M_DEVBUF, M_NOWAIT); 1559 if (mpt->ioc_page3 == NULL) 1560 return (-1); 1561 memset(mpt->ioc_page3, 0, sizeof(*mpt->ioc_page3)); 1562 memcpy(&mpt->ioc_page3->Header, &hdr, sizeof(hdr)); 1563 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1564 &mpt->ioc_page3->Header, len, 1565 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1566 if (rv) { 1567 mpt_prt(mpt, "failed to read IOC Page 3\n"); 1568 } 1569 1570 mpt_raid_wakeup(mpt); 1571 1572 return (0); 1573 } 1574 1575 /* 1576 * Read SCSI configuration information 1577 */ 1578 static int 1579 mpt_read_config_info_spi(struct mpt_softc *mpt) 1580 { 1581 int rv, i; 1582 1583 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, 1584 0, &mpt->mpt_port_page0.Header, 1585 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1586 if (rv) 1587 return (-1); 1588 mpt_lprt(mpt, MPT_PRT_DEBUG, 1589 "SPI Port Page 0 Header: %x %x %x %x\n", 1590 mpt->mpt_port_page0.Header.PageVersion, 1591 mpt->mpt_port_page0.Header.PageLength, 1592 mpt->mpt_port_page0.Header.PageNumber, 1593 mpt->mpt_port_page0.Header.PageType); 1594 1595 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 1596 0, &mpt->mpt_port_page1.Header, 1597 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1598 if (rv) 1599 return (-1); 1600 1601 mpt_lprt(mpt, MPT_PRT_DEBUG, "SPI Port Page 1 Header: %x %x %x %x\n", 1602 mpt->mpt_port_page1.Header.PageVersion, 1603 mpt->mpt_port_page1.Header.PageLength, 1604 mpt->mpt_port_page1.Header.PageNumber, 1605 mpt->mpt_port_page1.Header.PageType); 1606 1607 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 1608 /*PageAddress*/0, &mpt->mpt_port_page2.Header, 1609 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1610 if (rv) 1611 return (-1); 1612 1613 mpt_lprt(mpt, MPT_PRT_DEBUG, 1614 "SPI Port Page 2 Header: %x %x %x %x\n", 1615 mpt->mpt_port_page1.Header.PageVersion, 1616 mpt->mpt_port_page1.Header.PageLength, 1617 mpt->mpt_port_page1.Header.PageNumber, 1618 mpt->mpt_port_page1.Header.PageType); 1619 1620 for (i = 0; i < 16; i++) { 1621 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 1622 0, i, &mpt->mpt_dev_page0[i].Header, 1623 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1624 if (rv) 1625 return (-1); 1626 1627 mpt_lprt(mpt, MPT_PRT_DEBUG, 1628 "SPI Target %d Device Page 0 Header: %x %x %x %x\n", 1629 i, mpt->mpt_dev_page0[i].Header.PageVersion, 1630 mpt->mpt_dev_page0[i].Header.PageLength, 1631 mpt->mpt_dev_page0[i].Header.PageNumber, 1632 mpt->mpt_dev_page0[i].Header.PageType); 1633 1634 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 1635 1, i, &mpt->mpt_dev_page1[i].Header, 1636 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1637 if (rv) 1638 return (-1); 1639 1640 mpt_lprt(mpt, MPT_PRT_DEBUG, 1641 "SPI Target %d Device Page 1 Header: %x %x %x %x\n", 1642 i, mpt->mpt_dev_page1[i].Header.PageVersion, 1643 mpt->mpt_dev_page1[i].Header.PageLength, 1644 mpt->mpt_dev_page1[i].Header.PageNumber, 1645 mpt->mpt_dev_page1[i].Header.PageType); 1646 } 1647 1648 /* 1649 * At this point, we don't *have* to fail. As long as we have 1650 * valid config header information, we can (barely) lurch 1651 * along. 1652 */ 1653 1654 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1655 &mpt->mpt_port_page0.Header, 1656 sizeof(mpt->mpt_port_page0), 1657 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1658 if (rv) { 1659 mpt_prt(mpt, "failed to read SPI Port Page 0\n"); 1660 } else { 1661 mpt_lprt(mpt, MPT_PRT_DEBUG, 1662 "SPI Port Page 0: Capabilities %x PhysicalInterface %x\n", 1663 mpt->mpt_port_page0.Capabilities, 1664 mpt->mpt_port_page0.PhysicalInterface); 1665 } 1666 1667 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1668 &mpt->mpt_port_page1.Header, 1669 sizeof(mpt->mpt_port_page1), 1670 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1671 if (rv) { 1672 mpt_prt(mpt, "failed to read SPI Port Page 1\n"); 1673 } else { 1674 mpt_lprt(mpt, MPT_PRT_DEBUG, 1675 "SPI Port Page 1: Configuration %x OnBusTimerValue %x\n", 1676 mpt->mpt_port_page1.Configuration, 1677 mpt->mpt_port_page1.OnBusTimerValue); 1678 } 1679 1680 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1681 &mpt->mpt_port_page2.Header, 1682 sizeof(mpt->mpt_port_page2), 1683 /*sleep_ok*/FALSE, /*timeout_ms*/5000); 1684 if (rv) { 1685 mpt_prt(mpt, "failed to read SPI Port Page 2\n"); 1686 } else { 1687 mpt_lprt(mpt, MPT_PRT_DEBUG, 1688 "SPI Port Page 2: Flags %x Settings %x\n", 1689 mpt->mpt_port_page2.PortFlags, 1690 mpt->mpt_port_page2.PortSettings); 1691 for (i = 0; i < 16; i++) { 1692 mpt_lprt(mpt, MPT_PRT_DEBUG, 1693 "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x\n", 1694 i, mpt->mpt_port_page2.DeviceSettings[i].Timeout, 1695 mpt->mpt_port_page2.DeviceSettings[i].SyncFactor, 1696 mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags); 1697 } 1698 } 1699 1700 for (i = 0; i < 16; i++) { 1701 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/i, 1702 &mpt->mpt_dev_page0[i].Header, 1703 sizeof(*mpt->mpt_dev_page0), 1704 /*sleep_ok*/FALSE, 1705 /*timeout_ms*/5000); 1706 if (rv) { 1707 mpt_prt(mpt, 1708 "cannot read SPI Tgt %d Device Page 0\n", i); 1709 continue; 1710 } 1711 mpt_lprt(mpt, MPT_PRT_DEBUG, 1712 "SPI Tgt %d Page 0: NParms %x Information %x", 1713 i, mpt->mpt_dev_page0[i].NegotiatedParameters, 1714 mpt->mpt_dev_page0[i].Information); 1715 1716 rv = mpt_read_cur_cfg_page(mpt, /*PageAddress*/i, 1717 &mpt->mpt_dev_page1[i].Header, 1718 sizeof(*mpt->mpt_dev_page1), 1719 /*sleep_ok*/FALSE, 1720 /*timeout_ms*/5000); 1721 if (rv) { 1722 mpt_prt(mpt, 1723 "cannot read SPI Tgt %d Device Page 1\n", i); 1724 continue; 1725 } 1726 mpt_lprt(mpt, MPT_PRT_DEBUG, 1727 "SPI Tgt %d Page 1: RParms %x Configuration %x\n", 1728 i, mpt->mpt_dev_page1[i].RequestedParameters, 1729 mpt->mpt_dev_page1[i].Configuration); 1730 } 1731 return (0); 1732 } 1733 1734 /* 1735 * Validate SPI configuration information. 1736 * 1737 * In particular, validate SPI Port Page 1. 1738 */ 1739 static int 1740 mpt_set_initial_config_spi(struct mpt_softc *mpt) 1741 { 1742 int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id; 1743 int error; 1744 1745 mpt->mpt_disc_enable = 0xff; 1746 mpt->mpt_tag_enable = 0; 1747 1748 if (mpt->mpt_port_page1.Configuration != pp1val) { 1749 CONFIG_PAGE_SCSI_PORT_1 tmp; 1750 1751 mpt_prt(mpt, 1752 "SPI Port Page 1 Config value bad (%x)- should be %x\n", 1753 mpt->mpt_port_page1.Configuration, pp1val); 1754 tmp = mpt->mpt_port_page1; 1755 tmp.Configuration = pp1val; 1756 error = mpt_write_cur_cfg_page(mpt, /*PageAddress*/0, 1757 &tmp.Header, sizeof(tmp), 1758 /*sleep_ok*/FALSE, 1759 /*timeout_ms*/5000); 1760 if (error) 1761 return (-1); 1762 error = mpt_read_cur_cfg_page(mpt, /*PageAddress*/0, 1763 &tmp.Header, sizeof(tmp), 1764 /*sleep_ok*/FALSE, 1765 /*timeout_ms*/5000); 1766 if (error) 1767 return (-1); 1768 if (tmp.Configuration != pp1val) { 1769 mpt_prt(mpt, 1770 "failed to reset SPI Port Page 1 Config value\n"); 1771 return (-1); 1772 } 1773 mpt->mpt_port_page1 = tmp; 1774 } 1775 1776 for (i = 0; i < 16; i++) { 1777 CONFIG_PAGE_SCSI_DEVICE_1 tmp; 1778 tmp = mpt->mpt_dev_page1[i]; 1779 tmp.RequestedParameters = 0; 1780 tmp.Configuration = 0; 1781 mpt_lprt(mpt, MPT_PRT_DEBUG, 1782 "Set Tgt %d SPI DevicePage 1 values to %x 0 %x\n", 1783 i, tmp.RequestedParameters, tmp.Configuration); 1784 error = mpt_write_cur_cfg_page(mpt, /*PageAddress*/i, 1785 &tmp.Header, sizeof(tmp), 1786 /*sleep_ok*/FALSE, 1787 /*timeout_ms*/5000); 1788 if (error) 1789 return (-1); 1790 error = mpt_read_cur_cfg_page(mpt, /*PageAddress*/i, 1791 &tmp.Header, sizeof(tmp), 1792 /*sleep_ok*/FALSE, 1793 /*timeout_ms*/5000); 1794 if (error) 1795 return (-1); 1796 mpt->mpt_dev_page1[i] = tmp; 1797 mpt_lprt(mpt, MPT_PRT_DEBUG, 1798 "SPI Tgt %d Page 1: RParm %x Configuration %x\n", i, 1799 mpt->mpt_dev_page1[i].RequestedParameters, 1800 mpt->mpt_dev_page1[i].Configuration); 1801 } 1802 return (0); 1803 } 1804 1805 /* 1806 * Enable IOC port 1807 */ 1808 static int 1809 mpt_send_port_enable(struct mpt_softc *mpt, int port) 1810 { 1811 request_t *req; 1812 MSG_PORT_ENABLE *enable_req; 1813 int error; 1814 1815 req = mpt_get_request(mpt, /*sleep_ok*/FALSE); 1816 if (req == NULL) 1817 return (-1); 1818 1819 enable_req = req->req_vbuf; 1820 bzero(enable_req, sizeof *enable_req); 1821 1822 enable_req->Function = MPI_FUNCTION_PORT_ENABLE; 1823 enable_req->MsgContext = htole32(req->index | MPT_REPLY_HANDLER_CONFIG); 1824 enable_req->PortNumber = port; 1825 1826 mpt_check_doorbell(mpt); 1827 mpt_lprt(mpt, MPT_PRT_DEBUG, "enabling port %d\n", port); 1828 1829 mpt_send_cmd(mpt, req); 1830 error = mpt_wait_req(mpt, req, REQ_STATE_DONE, REQ_STATE_DONE, 1831 /*sleep_ok*/FALSE, /*time_ms*/500); 1832 if (error != 0) { 1833 mpt_prt(mpt, "port enable timed out"); 1834 return (-1); 1835 } 1836 mpt_free_request(mpt, req); 1837 return (0); 1838 } 1839 1840 /* 1841 * Enable/Disable asynchronous event reporting. 1842 * 1843 * NB: this is the first command we send via shared memory 1844 * instead of the handshake register. 1845 */ 1846 static int 1847 mpt_send_event_request(struct mpt_softc *mpt, int onoff) 1848 { 1849 request_t *req; 1850 MSG_EVENT_NOTIFY *enable_req; 1851 1852 req = mpt_get_request(mpt, /*sleep_ok*/FALSE); 1853 1854 enable_req = req->req_vbuf; 1855 bzero(enable_req, sizeof *enable_req); 1856 1857 enable_req->Function = MPI_FUNCTION_EVENT_NOTIFICATION; 1858 enable_req->MsgContext = htole32(req->index | MPT_REPLY_HANDLER_EVENTS); 1859 enable_req->Switch = onoff; 1860 1861 mpt_check_doorbell(mpt); 1862 mpt_lprt(mpt, MPT_PRT_DEBUG, 1863 "%sabling async events\n", onoff ? "en" : "dis"); 1864 mpt_send_cmd(mpt, req); 1865 1866 return (0); 1867 } 1868 1869 /* 1870 * Un-mask the interupts on the chip. 1871 */ 1872 void 1873 mpt_enable_ints(struct mpt_softc *mpt) 1874 { 1875 /* Unmask every thing except door bell int */ 1876 mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK); 1877 } 1878 1879 /* 1880 * Mask the interupts on the chip. 1881 */ 1882 void 1883 mpt_disable_ints(struct mpt_softc *mpt) 1884 { 1885 /* Mask all interrupts */ 1886 mpt_write(mpt, MPT_OFFSET_INTR_MASK, 1887 MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK); 1888 } 1889 1890 static void 1891 mpt_sysctl_attach(struct mpt_softc *mpt) 1892 { 1893 struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(mpt->dev); 1894 struct sysctl_oid *tree = device_get_sysctl_tree(mpt->dev); 1895 1896 SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, 1897 "debug", CTLFLAG_RW, &mpt->verbose, 0, 1898 "Debugging/Verbose level"); 1899 } 1900 1901 int 1902 mpt_attach(struct mpt_softc *mpt) 1903 { 1904 int i; 1905 1906 for (i = 0; i < MPT_MAX_PERSONALITIES; i++) { 1907 struct mpt_personality *pers; 1908 int error; 1909 1910 pers = mpt_personalities[i]; 1911 if (pers == NULL) 1912 continue; 1913 1914 if (pers->probe(mpt) == 0) { 1915 error = pers->attach(mpt); 1916 if (error != 0) { 1917 mpt_detach(mpt); 1918 return (error); 1919 } 1920 mpt->mpt_pers_mask |= (0x1 << pers->id); 1921 pers->use_count++; 1922 } 1923 } 1924 return (0); 1925 } 1926 1927 int 1928 mpt_shutdown(struct mpt_softc *mpt) 1929 { 1930 struct mpt_personality *pers; 1931 1932 MPT_PERS_FOREACH_REVERSE(mpt, pers) 1933 pers->shutdown(mpt); 1934 1935 mpt_reset(mpt, /*reinit*/FALSE); 1936 return (0); 1937 } 1938 1939 int 1940 mpt_detach(struct mpt_softc *mpt) 1941 { 1942 struct mpt_personality *pers; 1943 1944 MPT_PERS_FOREACH_REVERSE(mpt, pers) { 1945 pers->detach(mpt); 1946 mpt->mpt_pers_mask &= ~(0x1 << pers->id); 1947 pers->use_count--; 1948 } 1949 1950 return (0); 1951 } 1952 1953 int 1954 mpt_core_load(struct mpt_personality *pers) 1955 { 1956 int i; 1957 1958 /* 1959 * Setup core handlers and insert the default handler 1960 * into all "empty slots". 1961 */ 1962 for (i = 0; i < MPT_NUM_REPLY_HANDLERS; i++) 1963 mpt_reply_handlers[i] = mpt_default_reply_handler; 1964 1965 mpt_reply_handlers[MPT_CBI(MPT_REPLY_HANDLER_EVENTS)] = 1966 mpt_event_reply_handler; 1967 mpt_reply_handlers[MPT_CBI(MPT_REPLY_HANDLER_CONFIG)] = 1968 mpt_config_reply_handler; 1969 mpt_reply_handlers[MPT_CBI(MPT_REPLY_HANDLER_HANDSHAKE)] = 1970 mpt_handshake_reply_handler; 1971 1972 return (0); 1973 } 1974 1975 /* 1976 * Initialize per-instance driver data and perform 1977 * initial controller configuration. 1978 */ 1979 int 1980 mpt_core_attach(struct mpt_softc *mpt) 1981 { 1982 int val; 1983 int error; 1984 1985 LIST_INIT(&mpt->ack_frames); 1986 1987 /* Put all request buffers on the free list */ 1988 TAILQ_INIT(&mpt->request_pending_list); 1989 TAILQ_INIT(&mpt->request_free_list); 1990 for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) 1991 mpt_free_request(mpt, &mpt->request_pool[val]); 1992 1993 mpt_sysctl_attach(mpt); 1994 1995 mpt_lprt(mpt, MPT_PRT_DEBUG, "doorbell req = %s\n", 1996 mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL))); 1997 1998 error = mpt_configure_ioc(mpt); 1999 2000 return (error); 2001 } 2002 2003 void 2004 mpt_core_shutdown(struct mpt_softc *mpt) 2005 { 2006 } 2007 2008 void 2009 mpt_core_detach(struct mpt_softc *mpt) 2010 { 2011 } 2012 2013 int 2014 mpt_core_unload(struct mpt_personality *pers) 2015 { 2016 /* Unload is always successfull. */ 2017 return (0); 2018 } 2019 2020 #define FW_UPLOAD_REQ_SIZE \ 2021 (sizeof(MSG_FW_UPLOAD) - sizeof(SGE_MPI_UNION) \ 2022 + sizeof(FW_UPLOAD_TCSGE) + sizeof(SGE_SIMPLE32)) 2023 2024 static int 2025 mpt_upload_fw(struct mpt_softc *mpt) 2026 { 2027 uint8_t fw_req_buf[FW_UPLOAD_REQ_SIZE]; 2028 MSG_FW_UPLOAD_REPLY fw_reply; 2029 MSG_FW_UPLOAD *fw_req; 2030 FW_UPLOAD_TCSGE *tsge; 2031 SGE_SIMPLE32 *sge; 2032 uint32_t flags; 2033 int error; 2034 2035 memset(&fw_req_buf, 0, sizeof(fw_req_buf)); 2036 fw_req = (MSG_FW_UPLOAD *)fw_req_buf; 2037 fw_req->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM; 2038 fw_req->Function = MPI_FUNCTION_FW_UPLOAD; 2039 fw_req->MsgContext = htole32(MPT_REPLY_HANDLER_HANDSHAKE); 2040 tsge = (FW_UPLOAD_TCSGE *)&fw_req->SGL; 2041 tsge->DetailsLength = 12; 2042 tsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT; 2043 tsge->ImageSize = htole32(mpt->fw_image_size); 2044 sge = (SGE_SIMPLE32 *)(tsge + 1); 2045 flags = (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER 2046 | MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_SIMPLE_ELEMENT 2047 | MPI_SGE_FLAGS_32_BIT_ADDRESSING | MPI_SGE_FLAGS_IOC_TO_HOST); 2048 flags <<= MPI_SGE_FLAGS_SHIFT; 2049 sge->FlagsLength = htole32(flags | mpt->fw_image_size); 2050 sge->Address = htole32(mpt->fw_phys); 2051 error = mpt_send_handshake_cmd(mpt, sizeof(fw_req_buf), &fw_req_buf); 2052 if (error) 2053 return(error); 2054 error = mpt_recv_handshake_reply(mpt, sizeof(fw_reply), &fw_reply); 2055 return (error); 2056 } 2057 2058 static void 2059 mpt_diag_outsl(struct mpt_softc *mpt, uint32_t addr, 2060 uint32_t *data, bus_size_t len) 2061 { 2062 uint32_t *data_end; 2063 2064 data_end = data + (roundup2(len, sizeof(uint32_t)) / 4); 2065 mpt_pio_write(mpt, MPT_OFFSET_DIAG_ADDR, addr); 2066 while (data != data_end) { 2067 mpt_pio_write(mpt, MPT_OFFSET_DIAG_DATA, *data); 2068 data++; 2069 } 2070 } 2071 2072 static int 2073 mpt_download_fw(struct mpt_softc *mpt) 2074 { 2075 MpiFwHeader_t *fw_hdr; 2076 int error; 2077 uint32_t ext_offset; 2078 uint32_t data; 2079 2080 mpt_prt(mpt, "Downloading Firmware - Image Size %d\n", 2081 mpt->fw_image_size); 2082 2083 error = mpt_enable_diag_mode(mpt); 2084 if (error != 0) { 2085 mpt_prt(mpt, "Could not enter diagnostic mode!\n"); 2086 return (EIO); 2087 } 2088 2089 mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, 2090 MPI_DIAG_RW_ENABLE|MPI_DIAG_DISABLE_ARM); 2091 2092 fw_hdr = (MpiFwHeader_t *)mpt->fw_image; 2093 mpt_diag_outsl(mpt, fw_hdr->LoadStartAddress, (uint32_t*)fw_hdr, 2094 fw_hdr->ImageSize); 2095 2096 ext_offset = fw_hdr->NextImageHeaderOffset; 2097 while (ext_offset != 0) { 2098 MpiExtImageHeader_t *ext; 2099 2100 ext = (MpiExtImageHeader_t *)((uintptr_t)fw_hdr + ext_offset); 2101 ext_offset = ext->NextImageHeaderOffset; 2102 2103 mpt_diag_outsl(mpt, ext->LoadStartAddress, (uint32_t*)ext, 2104 ext->ImageSize); 2105 } 2106 2107 /* Setup the address to jump to on reset. */ 2108 mpt_pio_write(mpt, MPT_OFFSET_DIAG_ADDR, fw_hdr->IopResetRegAddr); 2109 mpt_pio_write(mpt, MPT_OFFSET_DIAG_DATA, fw_hdr->IopResetVectorValue); 2110 2111 /* 2112 * The controller sets the "flash bad" status after attempting 2113 * to auto-boot from flash. Clear the status so that the controller 2114 * will continue the boot process with our newly installed firmware. 2115 */ 2116 mpt_pio_write(mpt, MPT_OFFSET_DIAG_ADDR, MPT_DIAG_MEM_CFG_BASE); 2117 data = mpt_pio_read(mpt, MPT_OFFSET_DIAG_DATA) | MPT_DIAG_MEM_CFG_BADFL; 2118 mpt_pio_write(mpt, MPT_OFFSET_DIAG_ADDR, MPT_DIAG_MEM_CFG_BASE); 2119 mpt_pio_write(mpt, MPT_OFFSET_DIAG_DATA, data); 2120 2121 /* 2122 * Re-enable the processor and clear the boot halt flag. 2123 */ 2124 data = mpt_read(mpt, MPT_OFFSET_DIAGNOSTIC); 2125 data &= ~(MPI_DIAG_PREVENT_IOC_BOOT|MPI_DIAG_DISABLE_ARM); 2126 mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, data); 2127 2128 mpt_disable_diag_mode(mpt); 2129 return (0); 2130 } 2131 2132 /* 2133 * Allocate/Initialize data structures for the controller. Called 2134 * once at instance startup. 2135 */ 2136 static int 2137 mpt_configure_ioc(struct mpt_softc *mpt) 2138 { 2139 MSG_PORT_FACTS_REPLY pfp; 2140 MSG_IOC_FACTS_REPLY facts; 2141 int try; 2142 int needreset; 2143 2144 needreset = 0; 2145 for (try = 0; try < MPT_MAX_TRYS; try++) { 2146 2147 /* 2148 * No need to reset if the IOC is already in the READY state. 2149 * 2150 * Force reset if initialization failed previously. 2151 * Note that a hard_reset of the second channel of a '929 2152 * will stop operation of the first channel. Hopefully, if the 2153 * first channel is ok, the second will not require a hard 2154 * reset. 2155 */ 2156 if (needreset || (mpt_rd_db(mpt) & MPT_DB_STATE_MASK) != 2157 MPT_DB_STATE_READY) { 2158 if (mpt_reset(mpt, /*reinit*/FALSE) != MPT_OK) 2159 continue; 2160 } 2161 needreset = 0; 2162 2163 if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) { 2164 mpt_prt(mpt, "mpt_get_iocfacts failed\n"); 2165 needreset = 1; 2166 continue; 2167 } 2168 2169 mpt->mpt_global_credits = le16toh(facts.GlobalCredits); 2170 mpt->request_frame_size = le16toh(facts.RequestFrameSize); 2171 mpt_prt(mpt, "MPI Version=%d.%d.%d.%d\n", 2172 le16toh(facts.MsgVersion) >> 8, 2173 le16toh(facts.MsgVersion) & 0xFF, 2174 le16toh(facts.HeaderVersion) >> 8, 2175 le16toh(facts.HeaderVersion) & 0xFF); 2176 mpt_lprt(mpt, MPT_PRT_DEBUG, 2177 "MsgLength=%u IOCNumber = %d\n", 2178 facts.MsgLength, facts.IOCNumber); 2179 mpt_lprt(mpt, MPT_PRT_DEBUG, 2180 "IOCFACTS: GlobalCredits=%d BlockSize=%u " 2181 "Request Frame Size %u\n", mpt->mpt_global_credits, 2182 facts.BlockSize * 8, mpt->request_frame_size * 8); 2183 mpt_lprt(mpt, MPT_PRT_DEBUG, 2184 "IOCFACTS: Num Ports %d, FWImageSize %d, " 2185 "Flags=%#x\n", facts.NumberOfPorts, 2186 le32toh(facts.FWImageSize), facts.Flags); 2187 2188 if ((facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) != 0) { 2189 struct mpt_map_info mi; 2190 int error; 2191 2192 /* 2193 * In some configurations, the IOC's firmware is 2194 * stored in a shared piece of system NVRAM that 2195 * is only accessable via the BIOS. In this 2196 * case, the firmware keeps a copy of firmware in 2197 * RAM until the OS driver retrieves it. Once 2198 * retrieved, we are responsible for re-downloading 2199 * the firmware after any hard-reset. 2200 */ 2201 mpt->fw_image_size = le32toh(facts.FWImageSize); 2202 error = mpt_dma_tag_create(mpt, mpt->parent_dmat, 2203 /*alignment*/1, /*boundary*/0, 2204 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 2205 /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL, 2206 /*filterarg*/NULL, mpt->fw_image_size, 2207 /*nsegments*/1, /*maxsegsz*/mpt->fw_image_size, 2208 /*flags*/0, &mpt->fw_dmat); 2209 if (error != 0) { 2210 mpt_prt(mpt, "cannot create fw dma tag\n"); 2211 return (ENOMEM); 2212 } 2213 error = bus_dmamem_alloc(mpt->fw_dmat, 2214 (void **)&mpt->fw_image, BUS_DMA_NOWAIT, 2215 &mpt->fw_dmap); 2216 if (error != 0) { 2217 mpt_prt(mpt, "cannot allocate fw mem.\n"); 2218 bus_dma_tag_destroy(mpt->fw_dmat); 2219 return (ENOMEM); 2220 } 2221 mi.mpt = mpt; 2222 mi.error = 0; 2223 bus_dmamap_load(mpt->fw_dmat, mpt->fw_dmap, 2224 mpt->fw_image, mpt->fw_image_size, mpt_map_rquest, 2225 &mi, 0); 2226 mpt->fw_phys = mi.phys; 2227 2228 error = mpt_upload_fw(mpt); 2229 if (error != 0) { 2230 mpt_prt(mpt, "fw upload failed.\n"); 2231 bus_dmamap_unload(mpt->fw_dmat, mpt->fw_dmap); 2232 bus_dmamem_free(mpt->fw_dmat, mpt->fw_image, 2233 mpt->fw_dmap); 2234 bus_dma_tag_destroy(mpt->fw_dmat); 2235 mpt->fw_image = NULL; 2236 return (EIO); 2237 } 2238 } 2239 2240 if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) { 2241 mpt_prt(mpt, "mpt_get_portfacts failed\n"); 2242 needreset = 1; 2243 continue; 2244 } 2245 2246 mpt_lprt(mpt, MPT_PRT_DEBUG, 2247 "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d\n", 2248 pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID, 2249 pfp.MaxDevices); 2250 2251 mpt->mpt_port_type = pfp.PortType; 2252 mpt->mpt_proto_flags = pfp.ProtocolFlags; 2253 if (pfp.PortType != MPI_PORTFACTS_PORTTYPE_SCSI && 2254 pfp.PortType != MPI_PORTFACTS_PORTTYPE_FC) { 2255 mpt_prt(mpt, "Unsupported Port Type (%x)\n", 2256 pfp.PortType); 2257 return (ENXIO); 2258 } 2259 if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) { 2260 mpt_prt(mpt, "initiator role unsupported\n"); 2261 return (ENXIO); 2262 } 2263 if (pfp.PortType == MPI_PORTFACTS_PORTTYPE_FC) { 2264 mpt->is_fc = 1; 2265 } else { 2266 mpt->is_fc = 0; 2267 } 2268 mpt->mpt_ini_id = pfp.PortSCSIID; 2269 2270 if (mpt_enable_ioc(mpt) != 0) { 2271 mpt_prt(mpt, "Unable to initialize IOC\n"); 2272 return (ENXIO); 2273 } 2274 2275 /* 2276 * Read and set up initial configuration information 2277 * (IOC and SPI only for now) 2278 * 2279 * XXX Should figure out what "personalities" are 2280 * available and defer all initialization junk to 2281 * them. 2282 */ 2283 mpt_read_config_info_ioc(mpt); 2284 2285 if (mpt->is_fc == 0) { 2286 if (mpt_read_config_info_spi(mpt)) { 2287 return (EIO); 2288 } 2289 if (mpt_set_initial_config_spi(mpt)) { 2290 return (EIO); 2291 } 2292 } 2293 2294 /* Everything worked */ 2295 break; 2296 } 2297 2298 if (try >= MPT_MAX_TRYS) { 2299 mpt_prt(mpt, "failed to initialize IOC"); 2300 return (EIO); 2301 } 2302 2303 mpt_lprt(mpt, MPT_PRT_DEBUG, "enabling interrupts\n"); 2304 2305 mpt_enable_ints(mpt); 2306 return (0); 2307 } 2308 2309 static int 2310 mpt_enable_ioc(struct mpt_softc *mpt) 2311 { 2312 uint32_t pptr; 2313 int val; 2314 2315 if (mpt_send_ioc_init(mpt, MPT_DB_INIT_HOST) != MPT_OK) { 2316 mpt_prt(mpt, "mpt_send_ioc_init failed\n"); 2317 return (EIO); 2318 } 2319 2320 mpt_lprt(mpt, MPT_PRT_DEBUG, "mpt_send_ioc_init ok\n"); 2321 2322 if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) { 2323 mpt_prt(mpt, "IOC failed to go to run state\n"); 2324 return (ENXIO); 2325 } 2326 mpt_lprt(mpt, MPT_PRT_DEBUG, "IOC now at RUNSTATE"); 2327 2328 /* 2329 * Give it reply buffers 2330 * 2331 * Do *not* exceed global credits. 2332 */ 2333 for (val = 0, pptr = mpt->reply_phys; 2334 (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE); 2335 pptr += MPT_REPLY_SIZE) { 2336 mpt_free_reply(mpt, pptr); 2337 if (++val == mpt->mpt_global_credits - 1) 2338 break; 2339 } 2340 2341 /* 2342 * Enable asynchronous event reporting 2343 */ 2344 mpt_send_event_request(mpt, 1); 2345 2346 /* 2347 * Now enable the port 2348 */ 2349 if (mpt_send_port_enable(mpt, 0) != MPT_OK) { 2350 mpt_prt(mpt, "failed to enable port 0\n"); 2351 return (ENXIO); 2352 } 2353 2354 mpt_lprt(mpt, MPT_PRT_DEBUG, "enabled port 0\n"); 2355 2356 return (0); 2357 } 2358