1/* $NetBSD: mpt.c,v 1.14 2010/04/28 22:45:27 chs Exp $ */ 2 3/* 4 * Copyright (c) 2000, 2001 by Greg Ansley 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice immediately at the beginning of the file, without modification, 11 * this list of conditions, and the following disclaimer. 12 * 2. The name of the author may not be used to endorse or promote products 13 * derived from this software without specific prior written permission. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 19 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27/* 28 * Additional Copyright (c) 2002 by Matthew Jacob under same license. 29 */ 30/*- 31 * Copyright (c) 2002, 2006 by Matthew Jacob 32 * All rights reserved. 33 * 34 * Redistribution and use in source and binary forms, with or without 35 * modification, are permitted provided that the following conditions are 36 * met: 37 * 1. Redistributions of source code must retain the above copyright 38 * notice, this list of conditions and the following disclaimer. 39 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 40 * substantially similar to the "NO WARRANTY" disclaimer below 41 * ("Disclaimer") and any redistribution must be conditioned upon including 42 * a substantially similar Disclaimer requirement for further binary 43 * redistribution. 44 * 3. Neither the names of the above listed copyright holders nor the names 45 * of any contributors may be used to endorse or promote products derived 46 * from this software without specific prior written permission. 47 * 48 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 49 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 50 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 51 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 52 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 53 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 54 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 55 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 56 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 57 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 58 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 59 * 60 * Support from Chris Ellsworth in order to make SAS adapters work 61 * is gratefully acknowledged. 62 * 63 * 64 * Support from LSI-Logic has also gone a great deal toward making this a 65 * workable subsystem and is gratefully acknowledged. 66 */ 67/*- 68 * Copyright (c) 2004, Avid Technology, Inc. and its contributors. 69 * Copyright (c) 2005, WHEEL Sp. z o.o. 70 * Copyright (c) 2004, 2005 Justin T. Gibbs 71 * All rights reserved. 72 * 73 * Redistribution and use in source and binary forms, with or without 74 * modification, are permitted provided that the following conditions are 75 * met: 76 * 1. Redistributions of source code must retain the above copyright 77 * notice, this list of conditions and the following disclaimer. 78 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 79 * substantially similar to the "NO WARRANTY" disclaimer below 80 * ("Disclaimer") and any redistribution must be conditioned upon including 81 * a substantially similar Disclaimer requirement for further binary 82 * redistribution. 83 * 3. Neither the names of the above listed copyright holders nor the names 84 * of any contributors may be used to endorse or promote products derived 85 * from this software without specific prior written permission. 86 * 87 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 88 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 89 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 90 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 91 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 92 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 93 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 94 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 95 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 96 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT 97 * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 98 */ 99 100 101/* 102 * mpt.c: 103 * 104 * Generic routines for LSI Fusion adapters. 105 * 106 * Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for 107 * Wasabi Systems, Inc. 108 * 109 * Additional contributions by Garrett D'Amore on behalf of TELES AG. 110 */ 111 112#include <sys/cdefs.h> 113__KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.14 2010/04/28 22:45:27 chs Exp $"); 114 115#include <dev/ic/mpt.h> 116 117#define MPT_MAX_TRYS 3 118#define MPT_MAX_WAIT 300000 119 120static int maxwait_ack = 0; 121static int maxwait_int = 0; 122static int maxwait_state = 0; 123 124static inline u_int32_t 125mpt_rd_db(mpt_softc_t *mpt) 126{ 127 return mpt_read(mpt, MPT_OFFSET_DOORBELL); 128} 129 130static inline u_int32_t 131mpt_rd_intr(mpt_softc_t *mpt) 132{ 133 return mpt_read(mpt, MPT_OFFSET_INTR_STATUS); 134} 135 136/* Busy wait for a door bell to be read by IOC */ 137static int 138mpt_wait_db_ack(mpt_softc_t *mpt) 139{ 140 int i; 141 for (i=0; i < MPT_MAX_WAIT; i++) { 142 if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) { 143 maxwait_ack = i > maxwait_ack ? i : maxwait_ack; 144 return MPT_OK; 145 } 146 147 DELAY(100); 148 } 149 return MPT_FAIL; 150} 151 152/* Busy wait for a door bell interrupt */ 153static int 154mpt_wait_db_int(mpt_softc_t *mpt) 155{ 156 int i; 157 for (i=0; i < MPT_MAX_WAIT; i++) { 158 if (MPT_DB_INTR(mpt_rd_intr(mpt))) { 159 maxwait_int = i > maxwait_int ? i : maxwait_int; 160 return MPT_OK; 161 } 162 DELAY(100); 163 } 164 return MPT_FAIL; 165} 166 167/* Wait for IOC to transition to a give state */ 168void 169mpt_check_doorbell(mpt_softc_t *mpt) 170{ 171 u_int32_t db = mpt_rd_db(mpt); 172 if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) { 173 mpt_prt(mpt, "Device not running"); 174 mpt_print_db(db); 175 } 176} 177 178/* Wait for IOC to transition to a give state */ 179static int 180mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state) 181{ 182 int i; 183 184 for (i = 0; i < MPT_MAX_WAIT; i++) { 185 u_int32_t db = mpt_rd_db(mpt); 186 if (MPT_STATE(db) == state) { 187 maxwait_state = i > maxwait_state ? i : maxwait_state; 188 return (MPT_OK); 189 } 190 DELAY(100); 191 } 192 return (MPT_FAIL); 193} 194 195 196/* Issue the reset COMMAND to the IOC */ 197int 198mpt_soft_reset(mpt_softc_t *mpt) 199{ 200 if (mpt->verbose) { 201 mpt_prt(mpt, "soft reset"); 202 } 203 204 /* Have to use hard reset if we are not in Running state */ 205 if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) { 206 mpt_prt(mpt, "soft reset failed: device not running"); 207 return MPT_FAIL; 208 } 209 210 /* If door bell is in use we don't have a chance of getting 211 * a word in since the IOC probably crashed in message 212 * processing. So don't waste our time. 213 */ 214 if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) { 215 mpt_prt(mpt, "soft reset failed: doorbell wedged"); 216 return MPT_FAIL; 217 } 218 219 /* Send the reset request to the IOC */ 220 mpt_write(mpt, MPT_OFFSET_DOORBELL, 221 MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT); 222 if (mpt_wait_db_ack(mpt) != MPT_OK) { 223 mpt_prt(mpt, "soft reset failed: ack timeout"); 224 return MPT_FAIL; 225 } 226 227 /* Wait for the IOC to reload and come out of reset state */ 228 if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) { 229 mpt_prt(mpt, "soft reset failed: device did not start running"); 230 return MPT_FAIL; 231 } 232 233 return MPT_OK; 234} 235 236/* This is a magic diagnostic reset that resets all the ARM 237 * processors in the chip. 238 */ 239void 240mpt_hard_reset(mpt_softc_t *mpt) 241{ 242 if (mpt->verbose) { 243 mpt_prt(mpt, "hard reset"); 244 } 245 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xff); 246 247 /* Enable diagnostic registers */ 248 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1); 249 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2); 250 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3); 251 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4); 252 mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5); 253 254 /* Diag. port is now active so we can now hit the reset bit */ 255 mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC); 256 257 DELAY(10000); 258 259 /* Disable Diagnostic Register */ 260 mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF); 261} 262 263/* 264 * Reset the IOC when needed. Try software command first then if needed 265 * poke at the magic diagnostic reset. Note that a hard reset resets 266 * *both* IOCs on dual function chips (FC929 && LSI1030) as well as 267 * fouls up the PCI configuration registers. 268 */ 269int 270mpt_reset(mpt_softc_t *mpt) 271{ 272 int ret; 273 274 /* Try a soft reset */ 275 if ((ret = mpt_soft_reset(mpt)) != MPT_OK) { 276 /* Failed; do a hard reset */ 277 mpt_hard_reset(mpt); 278 279 /* Wait for the IOC to reload and come out of reset state */ 280 ret = mpt_wait_state(mpt, MPT_DB_STATE_READY); 281 if (ret != MPT_OK) { 282 mpt_prt(mpt, "failed to reset device"); 283 } 284 } 285 286 return ret; 287} 288 289/* Return a command buffer to the free queue */ 290void 291mpt_free_request(mpt_softc_t *mpt, request_t *req) 292{ 293 if (req == NULL || req != &mpt->request_pool[req->index]) { 294 panic("mpt_free_request bad req ptr\n"); 295 return; 296 } 297 req->sequence = 0; 298 req->xfer = NULL; 299 req->debug = REQ_FREE; 300 SLIST_INSERT_HEAD(&mpt->request_free_list, req, link); 301} 302 303/* Get a command buffer from the free queue */ 304request_t * 305mpt_get_request(mpt_softc_t *mpt) 306{ 307 request_t *req; 308 req = SLIST_FIRST(&mpt->request_free_list); 309 if (req != NULL) { 310 if (req != &mpt->request_pool[req->index]) { 311 panic("mpt_get_request: corrupted request free list\n"); 312 } 313 if (req->xfer != NULL) { 314 panic("mpt_get_request: corrupted request free list (xfer)\n"); 315 } 316 SLIST_REMOVE_HEAD(&mpt->request_free_list, link); 317 req->debug = REQ_IN_PROGRESS; 318 } 319 return req; 320} 321 322/* Pass the command to the IOC */ 323void 324mpt_send_cmd(mpt_softc_t *mpt, request_t *req) 325{ 326 req->sequence = mpt->sequence++; 327 if (mpt->verbose > 1) { 328 u_int32_t *pReq; 329 pReq = req->req_vbuf; 330 mpt_prt(mpt, "Send Request %d (0x%x):", 331 req->index, req->req_pbuf); 332 mpt_prt(mpt, "%08x %08x %08x %08x", 333 pReq[0], pReq[1], pReq[2], pReq[3]); 334 mpt_prt(mpt, "%08x %08x %08x %08x", 335 pReq[4], pReq[5], pReq[6], pReq[7]); 336 mpt_prt(mpt, "%08x %08x %08x %08x", 337 pReq[8], pReq[9], pReq[10], pReq[11]); 338 mpt_prt(mpt, "%08x %08x %08x %08x", 339 pReq[12], pReq[13], pReq[14], pReq[15]); 340 } 341 MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); 342 req->debug = REQ_ON_CHIP; 343 mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf); 344} 345 346/* 347 * Give the reply buffer back to the IOC after we have 348 * finished processing it. 349 */ 350void 351mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr) 352{ 353 mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr); 354} 355 356/* Get a reply from the IOC */ 357u_int32_t 358mpt_pop_reply_queue(mpt_softc_t *mpt) 359{ 360 return mpt_read(mpt, MPT_OFFSET_REPLY_Q); 361} 362 363/* 364 * Send a command to the IOC via the handshake register. 365 * 366 * Only done at initialization time and for certain unusual 367 * commands such as device/bus reset as specified by LSI. 368 */ 369int 370mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd) 371{ 372 int i; 373 u_int32_t data, *data32; 374 375 /* Check condition of the IOC */ 376 data = mpt_rd_db(mpt); 377 if (((MPT_STATE(data) != MPT_DB_STATE_READY) && 378 (MPT_STATE(data) != MPT_DB_STATE_RUNNING) && 379 (MPT_STATE(data) != MPT_DB_STATE_FAULT)) || 380 ( MPT_DB_IS_IN_USE(data) )) { 381 mpt_prt(mpt, "handshake aborted due to invalid doorbell state"); 382 mpt_print_db(data); 383 return(EBUSY); 384 } 385 386 /* We move things in 32 bit chunks */ 387 len = (len + 3) >> 2; 388 data32 = cmd; 389 390 /* Clear any left over pending doorbell interrupts */ 391 if (MPT_DB_INTR(mpt_rd_intr(mpt))) 392 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 393 394 /* 395 * Tell the handshake reg. we are going to send a command 396 * and how long it is going to be. 397 */ 398 data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) | 399 (len << MPI_DOORBELL_ADD_DWORDS_SHIFT); 400 mpt_write(mpt, MPT_OFFSET_DOORBELL, data); 401 402 /* Wait for the chip to notice */ 403 if (mpt_wait_db_int(mpt) != MPT_OK) { 404 mpt_prt(mpt, "mpt_send_handshake_cmd timeout1"); 405 return ETIMEDOUT; 406 } 407 408 /* Clear the interrupt */ 409 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 410 411 if (mpt_wait_db_ack(mpt) != MPT_OK) { 412 mpt_prt(mpt, "mpt_send_handshake_cmd timeout2"); 413 return ETIMEDOUT; 414 } 415 416 /* Send the command */ 417 for (i = 0; i < len; i++) { 418 mpt_write(mpt, MPT_OFFSET_DOORBELL, htole32(*data32++)); 419 if (mpt_wait_db_ack(mpt) != MPT_OK) { 420 mpt_prt(mpt, 421 "mpt_send_handshake_cmd timeout! index = %d", i); 422 return ETIMEDOUT; 423 } 424 } 425 return MPT_OK; 426} 427 428/* Get the response from the handshake register */ 429int 430mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply) 431{ 432 int left, reply_left; 433 u_int16_t *data16; 434 MSG_DEFAULT_REPLY *hdr; 435 436 /* We move things out in 16 bit chunks */ 437 reply_len >>= 1; 438 data16 = (u_int16_t *)reply; 439 440 hdr = (MSG_DEFAULT_REPLY *)reply; 441 442 /* Get first word */ 443 if (mpt_wait_db_int(mpt) != MPT_OK) { 444 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1"); 445 return ETIMEDOUT; 446 } 447 *data16++ = le16toh(mpt_read(mpt, MPT_OFFSET_DOORBELL) & 448 MPT_DB_DATA_MASK); 449 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 450 451 /* Get Second Word */ 452 if (mpt_wait_db_int(mpt) != MPT_OK) { 453 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2"); 454 return ETIMEDOUT; 455 } 456 *data16++ = le16toh(mpt_read(mpt, MPT_OFFSET_DOORBELL) & 457 MPT_DB_DATA_MASK); 458 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 459 460 /* With the second word, we can now look at the length */ 461 if (mpt->verbose > 1 && ((reply_len >> 1) != hdr->MsgLength)) { 462 mpt_prt(mpt, "reply length does not match message length: " 463 "got 0x%02x, expected 0x%02x", 464 hdr->MsgLength << 2, reply_len << 1); 465 } 466 467 /* Get rest of the reply; but don't overflow the provided buffer */ 468 left = (hdr->MsgLength << 1) - 2; 469 reply_left = reply_len - 2; 470 while (left--) { 471 u_int16_t datum; 472 473 if (mpt_wait_db_int(mpt) != MPT_OK) { 474 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3"); 475 return ETIMEDOUT; 476 } 477 datum = mpt_read(mpt, MPT_OFFSET_DOORBELL); 478 479 if (reply_left-- > 0) 480 *data16++ = le16toh(datum & MPT_DB_DATA_MASK); 481 482 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 483 } 484 485 /* One more wait & clear at the end */ 486 if (mpt_wait_db_int(mpt) != MPT_OK) { 487 mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4"); 488 return ETIMEDOUT; 489 } 490 mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); 491 492 if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 493 if (mpt->verbose > 1) 494 mpt_print_reply(hdr); 495 return (MPT_FAIL | hdr->IOCStatus); 496 } 497 498 return (0); 499} 500 501static int 502mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp) 503{ 504 MSG_IOC_FACTS f_req; 505 int error; 506 507 memset(&f_req, 0, sizeof f_req); 508 f_req.Function = MPI_FUNCTION_IOC_FACTS; 509 f_req.MsgContext = htole32(0x12071942); 510 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req); 511 if (error) 512 return(error); 513 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp); 514 return (error); 515} 516 517static int 518mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp) 519{ 520 MSG_PORT_FACTS f_req; 521 int error; 522 523 /* XXX: Only getting PORT FACTS for Port 0 */ 524 memset(&f_req, 0, sizeof f_req); 525 f_req.Function = MPI_FUNCTION_PORT_FACTS; 526 f_req.MsgContext = htole32(0x12071943); 527 error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req); 528 if (error) 529 return(error); 530 error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp); 531 return (error); 532} 533 534/* 535 * Send the initialization request. This is where we specify how many 536 * SCSI busses and how many devices per bus we wish to emulate. 537 * This is also the command that specifies the max size of the reply 538 * frames from the IOC that we will be allocating. 539 */ 540static int 541mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who) 542{ 543 int error = 0; 544 MSG_IOC_INIT init; 545 MSG_IOC_INIT_REPLY reply; 546 547 memset(&init, 0, sizeof init); 548 init.WhoInit = who; 549 init.Function = MPI_FUNCTION_IOC_INIT; 550 init.MaxDevices = mpt->mpt_max_devices; 551 init.MaxBuses = 1; 552 init.ReplyFrameSize = htole16(MPT_REPLY_SIZE); 553 init.MsgContext = htole32(0x12071941); 554 555 if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) { 556 return(error); 557 } 558 559 error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply); 560 return (error); 561} 562 563 564/* 565 * Utiltity routine to read configuration headers and pages 566 */ 567 568static int 569mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *); 570 571static int 572mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber, 573 int PageAddress, fCONFIG_PAGE_HEADER *rslt) 574{ 575 int count; 576 request_t *req; 577 MSG_CONFIG *cfgp; 578 MSG_CONFIG_REPLY *reply; 579 580 req = mpt_get_request(mpt); 581 582 cfgp = req->req_vbuf; 583 memset(cfgp, 0, sizeof *cfgp); 584 585 cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER; 586 cfgp->Function = MPI_FUNCTION_CONFIG; 587 cfgp->Header.PageNumber = (U8) PageNumber; 588 cfgp->Header.PageType = (U8) PageType; 589 cfgp->PageAddress = htole32(PageAddress); 590 MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE), 591 (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 592 MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST)); 593 cfgp->MsgContext = htole32(req->index | 0x80000000); 594 595 mpt_check_doorbell(mpt); 596 mpt_send_cmd(mpt, req); 597 count = 0; 598 do { 599 DELAY(500); 600 mpt_intr(mpt); 601 if (++count == 1000) { 602 mpt_prt(mpt, "read_cfg_header timed out"); 603 return (-1); 604 } 605 } while (req->debug == REQ_ON_CHIP); 606 607 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence); 608 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 609 mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x", 610 reply->IOCStatus); 611 mpt_free_reply(mpt, (req->sequence << 1)); 612 return (-1); 613 } 614 memcpy(rslt, &reply->Header, sizeof (fCONFIG_PAGE_HEADER)); 615 mpt_free_reply(mpt, (req->sequence << 1)); 616 mpt_free_request(mpt, req); 617 return (0); 618} 619 620#define CFG_DATA_OFF 128 621 622int 623mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr) 624{ 625 int count; 626 request_t *req; 627 SGE_SIMPLE32 *se; 628 MSG_CONFIG *cfgp; 629 size_t amt; 630 MSG_CONFIG_REPLY *reply; 631 632 req = mpt_get_request(mpt); 633 634 cfgp = req->req_vbuf; 635 memset(cfgp, 0, MPT_REQUEST_AREA); 636 cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; 637 cfgp->Function = MPI_FUNCTION_CONFIG; 638 cfgp->Header = *hdr; 639 amt = (cfgp->Header.PageLength * sizeof (u_int32_t)); 640 cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK; 641 cfgp->PageAddress = htole32(PageAddress); 642 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE; 643 se->Address = htole32(req->req_pbuf + CFG_DATA_OFF); 644 MPI_pSGE_SET_LENGTH(se, amt); 645 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 646 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 647 MPI_SGE_FLAGS_END_OF_LIST)); 648 se->FlagsLength = htole32(se->FlagsLength); 649 650 cfgp->MsgContext = htole32(req->index | 0x80000000); 651 652 mpt_check_doorbell(mpt); 653 mpt_send_cmd(mpt, req); 654 count = 0; 655 do { 656 DELAY(500); 657 mpt_intr(mpt); 658 if (++count == 1000) { 659 mpt_prt(mpt, "read_cfg_page timed out"); 660 return (-1); 661 } 662 } while (req->debug == REQ_ON_CHIP); 663 664 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence); 665 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 666 mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x", 667 reply->IOCStatus); 668 mpt_free_reply(mpt, (req->sequence << 1)); 669 return (-1); 670 } 671 mpt_free_reply(mpt, (req->sequence << 1)); 672#if 0 /* XXXJRT */ 673 bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap, 674 BUS_DMASYNC_POSTREAD); 675#endif 676 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && 677 cfgp->Header.PageNumber == 0) { 678 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0); 679 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && 680 cfgp->Header.PageNumber == 1) { 681 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1); 682 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && 683 cfgp->Header.PageNumber == 2) { 684 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2); 685 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && 686 cfgp->Header.PageNumber == 0) { 687 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0); 688 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && 689 cfgp->Header.PageNumber == 1) { 690 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1); 691 } 692 memcpy(hdr, (char *)req->req_vbuf + CFG_DATA_OFF, amt); 693 mpt_free_request(mpt, req); 694 return (0); 695} 696 697int 698mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr) 699{ 700 int count, hdr_attr; 701 request_t *req; 702 SGE_SIMPLE32 *se; 703 MSG_CONFIG *cfgp; 704 size_t amt; 705 MSG_CONFIG_REPLY *reply; 706 707 req = mpt_get_request(mpt); 708 709 cfgp = req->req_vbuf; 710 memset(cfgp, 0, sizeof *cfgp); 711 712 hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK; 713 if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE && 714 hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) { 715 mpt_prt(mpt, "page type 0x%x not changeable", 716 hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); 717 return (-1); 718 } 719 hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK; 720 721 cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; 722 cfgp->Function = MPI_FUNCTION_CONFIG; 723 cfgp->Header = *hdr; 724 amt = (cfgp->Header.PageLength * sizeof (u_int32_t)); 725 cfgp->PageAddress = htole32(PageAddress); 726 727 se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE; 728 se->Address = htole32(req->req_pbuf + CFG_DATA_OFF); 729 MPI_pSGE_SET_LENGTH(se, amt); 730 MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | 731 MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | 732 MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC)); 733 se->FlagsLength = htole32(se->FlagsLength); 734 735 cfgp->MsgContext = htole32(req->index | 0x80000000); 736 737 if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && 738 cfgp->Header.PageNumber == 0) { 739 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0); 740 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && 741 cfgp->Header.PageNumber == 1) { 742 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1); 743 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && 744 cfgp->Header.PageNumber == 2) { 745 amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2); 746 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && 747 cfgp->Header.PageNumber == 0) { 748 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0); 749 } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && 750 cfgp->Header.PageNumber == 1) { 751 amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1); 752 } 753 memcpy((char *)req->req_vbuf + CFG_DATA_OFF, hdr, amt); 754 /* Restore stripped out attributes */ 755 hdr->PageType |= hdr_attr; 756 757 mpt_check_doorbell(mpt); 758 mpt_send_cmd(mpt, req); 759 count = 0; 760 do { 761 DELAY(500); 762 mpt_intr(mpt); 763 if (++count == 1000) { 764 hdr->PageType |= hdr_attr; 765 mpt_prt(mpt, "mpt_write_cfg_page timed out"); 766 return (-1); 767 } 768 } while (req->debug == REQ_ON_CHIP); 769 770 reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence); 771 if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { 772 mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x", 773 le16toh(reply->IOCStatus)); 774 mpt_free_reply(mpt, (req->sequence << 1)); 775 return (-1); 776 } 777 mpt_free_reply(mpt, (req->sequence << 1)); 778 779 mpt_free_request(mpt, req); 780 return (0); 781} 782 783/* 784 * Read SCSI configuration information 785 */ 786static int 787mpt_read_config_info_spi(mpt_softc_t *mpt) 788{ 789 int rv, i; 790 791 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, 792 0, &mpt->mpt_port_page0.Header); 793 if (rv) { 794 return (-1); 795 } 796 if (mpt->verbose > 1) { 797 mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x", 798 mpt->mpt_port_page0.Header.PageVersion, 799 mpt->mpt_port_page0.Header.PageLength, 800 mpt->mpt_port_page0.Header.PageNumber, 801 mpt->mpt_port_page0.Header.PageType); 802 } 803 804 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, 805 0, &mpt->mpt_port_page1.Header); 806 if (rv) { 807 return (-1); 808 } 809 if (mpt->verbose > 1) { 810 mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x", 811 mpt->mpt_port_page1.Header.PageVersion, 812 mpt->mpt_port_page1.Header.PageLength, 813 mpt->mpt_port_page1.Header.PageNumber, 814 mpt->mpt_port_page1.Header.PageType); 815 } 816 817 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, 818 0, &mpt->mpt_port_page2.Header); 819 if (rv) { 820 return (-1); 821 } 822 823 if (mpt->verbose > 1) { 824 mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x", 825 mpt->mpt_port_page1.Header.PageVersion, 826 mpt->mpt_port_page1.Header.PageLength, 827 mpt->mpt_port_page1.Header.PageNumber, 828 mpt->mpt_port_page1.Header.PageType); 829 } 830 831 for (i = 0; i < 16; i++) { 832 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 833 0, i, &mpt->mpt_dev_page0[i].Header); 834 if (rv) { 835 return (-1); 836 } 837 if (mpt->verbose > 1) { 838 mpt_prt(mpt, 839 "SPI Target %d Device Page 0 Header: %x %x %x %x", 840 i, mpt->mpt_dev_page0[i].Header.PageVersion, 841 mpt->mpt_dev_page0[i].Header.PageLength, 842 mpt->mpt_dev_page0[i].Header.PageNumber, 843 mpt->mpt_dev_page0[i].Header.PageType); 844 } 845 846 rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, 847 1, i, &mpt->mpt_dev_page1[i].Header); 848 if (rv) { 849 return (-1); 850 } 851 if (mpt->verbose > 1) { 852 mpt_prt(mpt, 853 "SPI Target %d Device Page 1 Header: %x %x %x %x", 854 i, mpt->mpt_dev_page1[i].Header.PageVersion, 855 mpt->mpt_dev_page1[i].Header.PageLength, 856 mpt->mpt_dev_page1[i].Header.PageNumber, 857 mpt->mpt_dev_page1[i].Header.PageType); 858 } 859 } 860 861 /* 862 * At this point, we don't *have* to fail. As long as we have 863 * valid config header information, we can (barely) lurch 864 * along. 865 */ 866 867 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header); 868 mpt2host_config_page_scsi_port_0(&mpt->mpt_port_page0); 869 if (rv) { 870 mpt_prt(mpt, "failed to read SPI Port Page 0"); 871 } else if (mpt->verbose > 1) { 872 mpt_prt(mpt, 873 "SPI Port Page 0: Capabilities %x PhysicalInterface %x", 874 mpt->mpt_port_page0.Capabilities, 875 mpt->mpt_port_page0.PhysicalInterface); 876 } 877 878 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header); 879 mpt2host_config_page_scsi_port_1(&mpt->mpt_port_page1); 880 if (rv) { 881 mpt_prt(mpt, "failed to read SPI Port Page 1"); 882 } else if (mpt->verbose > 1) { 883 mpt_prt(mpt, 884 "SPI Port Page 1: Configuration %x OnBusTimerValue %x", 885 mpt->mpt_port_page1.Configuration, 886 mpt->mpt_port_page1.OnBusTimerValue); 887 } 888 889 rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header); 890 mpt2host_config_page_scsi_port_2(&mpt->mpt_port_page2); 891 if (rv) { 892 mpt_prt(mpt, "failed to read SPI Port Page 2"); 893 } else if (mpt->verbose > 1) { 894 mpt_prt(mpt, 895 "SPI Port Page 2: Flags %x Settings %x", 896 mpt->mpt_port_page2.PortFlags, 897 mpt->mpt_port_page2.PortSettings); 898 for (i = 0; i < 1; i++) { 899 mpt_prt(mpt, 900 "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x", 901 i, mpt->mpt_port_page2.DeviceSettings[i].Timeout, 902 mpt->mpt_port_page2.DeviceSettings[i].SyncFactor, 903 mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags); 904 } 905 } 906 907 for (i = 0; i < 16; i++) { 908 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header); 909 mpt2host_config_page_scsi_device_0(&mpt->mpt_dev_page0[i]); 910 if (rv) { 911 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i); 912 continue; 913 } 914 if (mpt->verbose > 1) { 915 mpt_prt(mpt, 916 "SPI Tgt %d Page 0: NParms %x Information %x", 917 i, mpt->mpt_dev_page0[i].NegotiatedParameters, 918 mpt->mpt_dev_page0[i].Information); 919 } 920 rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header); 921 mpt2host_config_page_scsi_device_1(&mpt->mpt_dev_page1[i]); 922 if (rv) { 923 mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i); 924 continue; 925 } 926 if (mpt->verbose > 1) { 927 mpt_prt(mpt, 928 "SPI Tgt %d Page 1: RParms %x Configuration %x", 929 i, mpt->mpt_dev_page1[i].RequestedParameters, 930 mpt->mpt_dev_page1[i].Configuration); 931 } 932 } 933 return (0); 934} 935 936/* 937 * Validate SPI configuration information. 938 * 939 * In particular, validate SPI Port Page 1. 940 */ 941static int 942mpt_set_initial_config_spi(mpt_softc_t *mpt) 943{ 944 int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id; 945 946 mpt->mpt_disc_enable = 0xff; 947 mpt->mpt_tag_enable = 0; 948 949 if (mpt->mpt_port_page1.Configuration != pp1val) { 950 fCONFIG_PAGE_SCSI_PORT_1 tmp; 951 952 mpt_prt(mpt, 953 "SPI Port Page 1 Config value bad (%x)- should be %x", 954 mpt->mpt_port_page1.Configuration, pp1val); 955 tmp = mpt->mpt_port_page1; 956 tmp.Configuration = pp1val; 957 host2mpt_config_page_scsi_port_1(&tmp); 958 if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) { 959 return (-1); 960 } 961 if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) { 962 return (-1); 963 } 964 mpt2host_config_page_scsi_port_1(&tmp); 965 if (tmp.Configuration != pp1val) { 966 mpt_prt(mpt, 967 "failed to reset SPI Port Page 1 Config value"); 968 return (-1); 969 } 970 mpt->mpt_port_page1 = tmp; 971 } 972 973 i = 0; 974 for (i = 0; i < 16; i++) { 975 fCONFIG_PAGE_SCSI_DEVICE_1 tmp; 976 977 tmp = mpt->mpt_dev_page1[i]; 978 tmp.RequestedParameters = 0; 979 tmp.Configuration = 0; 980 if (mpt->verbose > 1) { 981 mpt_prt(mpt, 982 "Set Tgt %d SPI DevicePage 1 values to %x 0 %x", 983 i, tmp.RequestedParameters, tmp.Configuration); 984 } 985 host2mpt_config_page_scsi_device_1(&tmp); 986 if (mpt_write_cfg_page(mpt, i, &tmp.Header)) { 987 return (-1); 988 } 989 if (mpt_read_cfg_page(mpt, i, &tmp.Header)) { 990 return (-1); 991 } 992 mpt2host_config_page_scsi_device_1(&tmp); 993 mpt->mpt_dev_page1[i] = tmp; 994 if (mpt->verbose > 1) { 995 mpt_prt(mpt, 996 "SPI Tgt %d Page 1: RParm %x Configuration %x", i, 997 mpt->mpt_dev_page1[i].RequestedParameters, 998 mpt->mpt_dev_page1[i].Configuration); 999 } 1000 } 1001 return (0); 1002} 1003 1004/* 1005 * Enable IOC port 1006 */ 1007static int 1008mpt_send_port_enable(mpt_softc_t *mpt, int port) 1009{ 1010 int count; 1011 request_t *req; 1012 MSG_PORT_ENABLE *enable_req; 1013 1014 req = mpt_get_request(mpt); 1015 1016 enable_req = req->req_vbuf; 1017 memset(enable_req, 0, sizeof *enable_req); 1018 1019 enable_req->Function = MPI_FUNCTION_PORT_ENABLE; 1020 enable_req->MsgContext = htole32(req->index | 0x80000000); 1021 enable_req->PortNumber = port; 1022 1023 mpt_check_doorbell(mpt); 1024 if (mpt->verbose > 1) { 1025 mpt_prt(mpt, "enabling port %d", port); 1026 } 1027 mpt_send_cmd(mpt, req); 1028 1029 count = 0; 1030 do { 1031 DELAY(500); 1032 mpt_intr(mpt); 1033 if (++count == 100000) { 1034 mpt_prt(mpt, "port enable timed out"); 1035 return (-1); 1036 } 1037 } while (req->debug == REQ_ON_CHIP); 1038 mpt_free_request(mpt, req); 1039 return (0); 1040} 1041 1042/* 1043 * Enable/Disable asynchronous event reporting. 1044 * 1045 * NB: this is the first command we send via shared memory 1046 * instead of the handshake register. 1047 */ 1048static int 1049mpt_send_event_request(mpt_softc_t *mpt, int onoff) 1050{ 1051 request_t *req; 1052 MSG_EVENT_NOTIFY *enable_req; 1053 1054 req = mpt_get_request(mpt); 1055 1056 enable_req = req->req_vbuf; 1057 memset(enable_req, 0, sizeof *enable_req); 1058 1059 enable_req->Function = MPI_FUNCTION_EVENT_NOTIFICATION; 1060 enable_req->MsgContext = htole32(req->index | 0x80000000); 1061 enable_req->Switch = onoff; 1062 1063 mpt_check_doorbell(mpt); 1064 if (mpt->verbose > 1) { 1065 mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis"); 1066 } 1067 mpt_send_cmd(mpt, req); 1068 1069 return (0); 1070} 1071 1072/* 1073 * Un-mask the interrupts on the chip. 1074 */ 1075void 1076mpt_enable_ints(mpt_softc_t *mpt) 1077{ 1078 /* Unmask every thing except door bell int */ 1079 mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK); 1080} 1081 1082/* 1083 * Mask the interrupts on the chip. 1084 */ 1085void 1086mpt_disable_ints(mpt_softc_t *mpt) 1087{ 1088 /* Mask all interrupts */ 1089 mpt_write(mpt, MPT_OFFSET_INTR_MASK, 1090 MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK); 1091} 1092 1093/* (Re)Initialize the chip for use */ 1094int 1095mpt_hw_init(mpt_softc_t *mpt) 1096{ 1097 u_int32_t db; 1098 int try; 1099 1100 /* 1101 * Start by making sure we're not at FAULT or RESET state 1102 */ 1103 for (try = 0; try < MPT_MAX_TRYS; try++) { 1104 1105 db = mpt_rd_db(mpt); 1106 1107 switch (MPT_STATE(db)) { 1108 case MPT_DB_STATE_READY: 1109 return (0); 1110 1111 default: 1112 /* if peer has already reset us, don't do it again! */ 1113 if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER) 1114 return (0); 1115 /*FALLTHRU*/ 1116 case MPT_DB_STATE_RESET: 1117 case MPT_DB_STATE_FAULT: 1118 if (mpt_reset(mpt) != MPT_OK) { 1119 DELAY(10000); 1120 continue; 1121 } 1122 break; 1123 } 1124 } 1125 return (EIO); 1126} 1127 1128int 1129mpt_init(mpt_softc_t *mpt, u_int32_t who) 1130{ 1131 int try; 1132 MSG_IOC_FACTS_REPLY facts; 1133 MSG_PORT_FACTS_REPLY pfp; 1134 prop_dictionary_t dict; 1135 uint32_t ini_id; 1136 uint32_t pptr; 1137 int val; 1138 1139 /* Put all request buffers (back) on the free list */ 1140 SLIST_INIT(&mpt->request_free_list); 1141 for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) { 1142 mpt_free_request(mpt, &mpt->request_pool[val]); 1143 } 1144 1145 if (mpt->verbose > 1) { 1146 mpt_prt(mpt, "doorbell req = %s", 1147 mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL))); 1148 } 1149 1150 /* 1151 * Start by making sure we're not at FAULT or RESET state 1152 */ 1153 if (mpt_hw_init(mpt) != 0) 1154 return (EIO); 1155 1156 dict = device_properties(&mpt->sc_dev); 1157 1158 for (try = 0; try < MPT_MAX_TRYS; try++) { 1159 /* 1160 * No need to reset if the IOC is already in the READY state. 1161 */ 1162 1163 if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) { 1164 mpt_prt(mpt, "mpt_get_iocfacts failed"); 1165 continue; 1166 } 1167 mpt2host_iocfacts_reply(&facts); 1168 1169 if (mpt->verbose > 1) { 1170 mpt_prt(mpt, 1171 "IOCFACTS: GlobalCredits=%d BlockSize=%u " 1172 "Request Frame Size %u", facts.GlobalCredits, 1173 facts.BlockSize, facts.RequestFrameSize); 1174 } 1175 mpt->mpt_max_devices = facts.MaxDevices; 1176 mpt->mpt_global_credits = facts.GlobalCredits; 1177 mpt->request_frame_size = facts.RequestFrameSize; 1178 1179 if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) { 1180 mpt_prt(mpt, "mpt_get_portfacts failed"); 1181 continue; 1182 } 1183 mpt2host_portfacts_reply(&pfp); 1184 1185 if (mpt->verbose > 1) { 1186 mpt_prt(mpt, 1187 "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d", 1188 pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID, 1189 pfp.MaxDevices); 1190 } 1191 1192 if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) { 1193 mpt_prt(mpt, "initiator role unsupported"); 1194 return (ENXIO); 1195 } 1196 1197 switch (pfp.PortType) { 1198 case MPI_PORTFACTS_PORTTYPE_FC: 1199 mpt->is_fc = 1; 1200 mpt->mpt_max_devices = 255; 1201 break; 1202 case MPI_PORTFACTS_PORTTYPE_SCSI: 1203 mpt->is_scsi = 1; 1204 /* some SPI controllers (VMWare, Sun) lie */ 1205 mpt->mpt_max_devices = 16; 1206 break; 1207 case MPI_PORTFACTS_PORTTYPE_SAS: 1208 mpt->is_sas = 1; 1209 break; 1210 default: 1211 mpt_prt(mpt, "Unsupported Port Type (%x)", 1212 pfp.PortType); 1213 return (ENXIO); 1214 } 1215 1216 if (!mpt->is_sas && !mpt->is_fc && 1217 prop_dictionary_get_uint32(dict, "scsi-initiator-id", &ini_id)) 1218 mpt->mpt_ini_id = ini_id; 1219 else 1220 mpt->mpt_ini_id = pfp.PortSCSIID; 1221 1222 if (mpt_send_ioc_init(mpt, who) != MPT_OK) { 1223 mpt_prt(mpt, "mpt_send_ioc_init failed"); 1224 continue; 1225 } 1226 1227 if (mpt->verbose > 1) { 1228 mpt_prt(mpt, "mpt_send_ioc_init ok"); 1229 } 1230 1231 if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) { 1232 mpt_prt(mpt, "IOC failed to go to run state"); 1233 continue; 1234 } 1235 if (mpt->verbose > 1) { 1236 mpt_prt(mpt, "IOC now at RUNSTATE"); 1237 } 1238 1239 /* 1240 * Give it reply buffers 1241 * 1242 * Do *not* except global credits. 1243 */ 1244 for (val = 0, pptr = mpt->reply_phys; 1245 (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE); 1246 pptr += MPT_REPLY_SIZE) { 1247 mpt_free_reply(mpt, pptr); 1248 if (++val == mpt->mpt_global_credits - 1) 1249 break; 1250 } 1251 1252 /* 1253 * Enable asynchronous event reporting 1254 */ 1255 mpt_send_event_request(mpt, 1); 1256 1257 1258 /* 1259 * Read set up initial configuration information 1260 * (SPI only for now) 1261 */ 1262 1263 if (mpt->is_scsi) { 1264 if (mpt_read_config_info_spi(mpt)) { 1265 return (EIO); 1266 } 1267 if (mpt_set_initial_config_spi(mpt)) { 1268 return (EIO); 1269 } 1270 } 1271 1272 /* 1273 * Now enable the port 1274 */ 1275 if (mpt_send_port_enable(mpt, 0) != MPT_OK) { 1276 mpt_prt(mpt, "failed to enable port 0"); 1277 continue; 1278 } 1279 1280 if (mpt->verbose > 1) { 1281 mpt_prt(mpt, "enabled port 0"); 1282 } 1283 1284 /* Everything worked */ 1285 break; 1286 } 1287 1288 if (try >= MPT_MAX_TRYS) { 1289 mpt_prt(mpt, "failed to initialize IOC"); 1290 return (EIO); 1291 } 1292 1293 if (mpt->verbose > 1) { 1294 mpt_prt(mpt, "enabling interrupts"); 1295 } 1296 1297 mpt_enable_ints(mpt); 1298 return (0); 1299} 1300 1301/* 1302 * Endian Conversion Functions- only used on Big Endian machines 1303 */ 1304#if _BYTE_ORDER == _BIG_ENDIAN 1305void 1306mpt2host_sge_simple_union(SGE_SIMPLE_UNION *sge) 1307{ 1308 1309 MPT_2_HOST32(sge, FlagsLength); 1310 MPT_2_HOST32(sge, _u.Address64.Low); 1311 MPT_2_HOST32(sge, _u.Address64.High); 1312} 1313 1314void 1315mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *rp) 1316{ 1317 1318 MPT_2_HOST16(rp, MsgVersion); 1319#if 0 1320 MPT_2_HOST16(rp, HeaderVersion); 1321#endif 1322 MPT_2_HOST32(rp, MsgContext); 1323 MPT_2_HOST16(rp, IOCExceptions); 1324 MPT_2_HOST16(rp, IOCStatus); 1325 MPT_2_HOST32(rp, IOCLogInfo); 1326 MPT_2_HOST16(rp, ReplyQueueDepth); 1327 MPT_2_HOST16(rp, RequestFrameSize); 1328 MPT_2_HOST16(rp, Reserved_0101_FWVersion); 1329 MPT_2_HOST16(rp, ProductID); 1330 MPT_2_HOST32(rp, CurrentHostMfaHighAddr); 1331 MPT_2_HOST16(rp, GlobalCredits); 1332 MPT_2_HOST32(rp, CurrentSenseBufferHighAddr); 1333 MPT_2_HOST16(rp, CurReplyFrameSize); 1334 MPT_2_HOST32(rp, FWImageSize); 1335#if 0 1336 MPT_2_HOST32(rp, IOCCapabilities); 1337#endif 1338 MPT_2_HOST32(rp, FWVersion.Word); 1339#if 0 1340 MPT_2_HOST16(rp, HighPriorityQueueDepth); 1341 MPT_2_HOST16(rp, Reserved2); 1342 mpt2host_sge_simple_union(&rp->HostPageBufferSGE); 1343 MPT_2_HOST32(rp, ReplyFifoHostSignalingAddr); 1344#endif 1345} 1346 1347void 1348mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *pfp) 1349{ 1350 1351 MPT_2_HOST16(pfp, Reserved); 1352 MPT_2_HOST16(pfp, Reserved1); 1353 MPT_2_HOST32(pfp, MsgContext); 1354 MPT_2_HOST16(pfp, Reserved2); 1355 MPT_2_HOST16(pfp, IOCStatus); 1356 MPT_2_HOST32(pfp, IOCLogInfo); 1357 MPT_2_HOST16(pfp, MaxDevices); 1358 MPT_2_HOST16(pfp, PortSCSIID); 1359 MPT_2_HOST16(pfp, ProtocolFlags); 1360 MPT_2_HOST16(pfp, MaxPostedCmdBuffers); 1361 MPT_2_HOST16(pfp, MaxPersistentIDs); 1362 MPT_2_HOST16(pfp, MaxLanBuckets); 1363 MPT_2_HOST16(pfp, Reserved4); 1364 MPT_2_HOST32(pfp, Reserved5); 1365} 1366 1367void 1368mpt2host_config_page_scsi_port_0(fCONFIG_PAGE_SCSI_PORT_0 *sp0) 1369{ 1370 1371 MPT_2_HOST32(sp0, Capabilities); 1372 MPT_2_HOST32(sp0, PhysicalInterface); 1373} 1374 1375void 1376mpt2host_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1) 1377{ 1378 1379 MPT_2_HOST32(sp1, Configuration); 1380 MPT_2_HOST32(sp1, OnBusTimerValue); 1381#if 0 1382 MPT_2_HOST16(sp1, IDConfig); 1383#endif 1384} 1385 1386void 1387host2mpt_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1) 1388{ 1389 1390 HOST_2_MPT32(sp1, Configuration); 1391 HOST_2_MPT32(sp1, OnBusTimerValue); 1392#if 0 1393 HOST_2_MPT16(sp1, IDConfig); 1394#endif 1395} 1396 1397void 1398mpt2host_config_page_scsi_port_2(fCONFIG_PAGE_SCSI_PORT_2 *sp2) 1399{ 1400 int i; 1401 1402 MPT_2_HOST32(sp2, PortFlags); 1403 MPT_2_HOST32(sp2, PortSettings); 1404 for (i = 0; i < sizeof(sp2->DeviceSettings) / 1405 sizeof(*sp2->DeviceSettings); i++) { 1406 MPT_2_HOST16(sp2, DeviceSettings[i].DeviceFlags); 1407 } 1408} 1409 1410void 1411mpt2host_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0) 1412{ 1413 1414 MPT_2_HOST32(sd0, NegotiatedParameters); 1415 MPT_2_HOST32(sd0, Information); 1416} 1417 1418void 1419host2mpt_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0) 1420{ 1421 1422 HOST_2_MPT32(sd0, NegotiatedParameters); 1423 HOST_2_MPT32(sd0, Information); 1424} 1425 1426void 1427mpt2host_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1) 1428{ 1429 1430 MPT_2_HOST32(sd1, RequestedParameters); 1431 MPT_2_HOST32(sd1, Reserved); 1432 MPT_2_HOST32(sd1, Configuration); 1433} 1434 1435void 1436host2mpt_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1) 1437{ 1438 1439 HOST_2_MPT32(sd1, RequestedParameters); 1440 HOST_2_MPT32(sd1, Reserved); 1441 HOST_2_MPT32(sd1, Configuration); 1442} 1443 1444void 1445mpt2host_config_page_fc_port_0(fCONFIG_PAGE_FC_PORT_0 *fp0) 1446{ 1447 1448 MPT_2_HOST32(fp0, Flags); 1449 MPT_2_HOST32(fp0, PortIdentifier); 1450 MPT_2_HOST32(fp0, WWNN.Low); 1451 MPT_2_HOST32(fp0, WWNN.High); 1452 MPT_2_HOST32(fp0, WWPN.Low); 1453 MPT_2_HOST32(fp0, WWPN.High); 1454 MPT_2_HOST32(fp0, SupportedServiceClass); 1455 MPT_2_HOST32(fp0, SupportedSpeeds); 1456 MPT_2_HOST32(fp0, CurrentSpeed); 1457 MPT_2_HOST32(fp0, MaxFrameSize); 1458 MPT_2_HOST32(fp0, FabricWWNN.Low); 1459 MPT_2_HOST32(fp0, FabricWWNN.High); 1460 MPT_2_HOST32(fp0, FabricWWPN.Low); 1461 MPT_2_HOST32(fp0, FabricWWPN.High); 1462 MPT_2_HOST32(fp0, DiscoveredPortsCount); 1463 MPT_2_HOST32(fp0, MaxInitiators); 1464} 1465 1466void 1467mpt2host_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1) 1468{ 1469 1470 MPT_2_HOST32(fp1, Flags); 1471 MPT_2_HOST32(fp1, NoSEEPROMWWNN.Low); 1472 MPT_2_HOST32(fp1, NoSEEPROMWWNN.High); 1473 MPT_2_HOST32(fp1, NoSEEPROMWWPN.Low); 1474 MPT_2_HOST32(fp1, NoSEEPROMWWPN.High); 1475} 1476 1477void 1478host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1) 1479{ 1480 1481 HOST_2_MPT32(fp1, Flags); 1482 HOST_2_MPT32(fp1, NoSEEPROMWWNN.Low); 1483 HOST_2_MPT32(fp1, NoSEEPROMWWNN.High); 1484 HOST_2_MPT32(fp1, NoSEEPROMWWPN.Low); 1485 HOST_2_MPT32(fp1, NoSEEPROMWWPN.High); 1486} 1487 1488void 1489mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 *volp) 1490{ 1491 int i; 1492 1493 MPT_2_HOST16(volp, VolumeStatus.Reserved); 1494 MPT_2_HOST16(volp, VolumeSettings.Settings); 1495 MPT_2_HOST32(volp, MaxLBA); 1496#if 0 1497 MPT_2_HOST32(volp, MaxLBAHigh); 1498#endif 1499 MPT_2_HOST32(volp, StripeSize); 1500 MPT_2_HOST32(volp, Reserved2); 1501 MPT_2_HOST32(volp, Reserved3); 1502 for (i = 0; i < MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX; i++) { 1503 MPT_2_HOST16(volp, PhysDisk[i].Reserved); 1504 } 1505} 1506 1507void 1508mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *rpd0) 1509{ 1510 1511 MPT_2_HOST32(rpd0, Reserved1); 1512 MPT_2_HOST16(rpd0, PhysDiskStatus.Reserved); 1513 MPT_2_HOST32(rpd0, MaxLBA); 1514 MPT_2_HOST16(rpd0, ErrorData.Reserved); 1515 MPT_2_HOST16(rpd0, ErrorData.ErrorCount); 1516 MPT_2_HOST16(rpd0, ErrorData.SmartCount); 1517} 1518 1519#endif 1520