Home | History | Annotate | Line # | Download | only in ic
mpt.c revision 1.11
      1 /*	$NetBSD: mpt.c,v 1.11 2009/03/18 16:00:18 cegger 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 
     32 /*
     33  * mpt.c:
     34  *
     35  * Generic routines for LSI Fusion adapters.
     36  *
     37  * Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
     38  * Wasabi Systems, Inc.
     39  *
     40  * Additional contributions by Garrett D'Amore on behalf of TELES AG.
     41  */
     42 
     43 #include <sys/cdefs.h>
     44 __KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.11 2009/03/18 16:00:18 cegger Exp $");
     45 
     46 #include <dev/ic/mpt.h>
     47 
     48 #define MPT_MAX_TRYS 3
     49 #define MPT_MAX_WAIT 300000
     50 
     51 static int maxwait_ack = 0;
     52 static int maxwait_int = 0;
     53 static int maxwait_state = 0;
     54 
     55 static inline u_int32_t
     56 mpt_rd_db(mpt_softc_t *mpt)
     57 {
     58 	return mpt_read(mpt, MPT_OFFSET_DOORBELL);
     59 }
     60 
     61 static inline u_int32_t
     62 mpt_rd_intr(mpt_softc_t *mpt)
     63 {
     64 	return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
     65 }
     66 
     67 /* Busy wait for a door bell to be read by IOC */
     68 static int
     69 mpt_wait_db_ack(mpt_softc_t *mpt)
     70 {
     71 	int i;
     72 	for (i=0; i < MPT_MAX_WAIT; i++) {
     73 		if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) {
     74 			maxwait_ack = i > maxwait_ack ? i : maxwait_ack;
     75 			return MPT_OK;
     76 		}
     77 
     78 		DELAY(100);
     79 	}
     80 	return MPT_FAIL;
     81 }
     82 
     83 /* Busy wait for a door bell interrupt */
     84 static int
     85 mpt_wait_db_int(mpt_softc_t *mpt)
     86 {
     87 	int i;
     88 	for (i=0; i < MPT_MAX_WAIT; i++) {
     89 		if (MPT_DB_INTR(mpt_rd_intr(mpt))) {
     90 			maxwait_int = i > maxwait_int ? i : maxwait_int;
     91 			return MPT_OK;
     92 		}
     93 		DELAY(100);
     94 	}
     95 	return MPT_FAIL;
     96 }
     97 
     98 /* Wait for IOC to transition to a give state */
     99 void
    100 mpt_check_doorbell(mpt_softc_t *mpt)
    101 {
    102 	u_int32_t db = mpt_rd_db(mpt);
    103 	if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
    104 		mpt_prt(mpt, "Device not running");
    105 		mpt_print_db(db);
    106 	}
    107 }
    108 
    109 /* Wait for IOC to transition to a give state */
    110 static int
    111 mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state)
    112 {
    113 	int i;
    114 
    115 	for (i = 0; i < MPT_MAX_WAIT; i++) {
    116 		u_int32_t db = mpt_rd_db(mpt);
    117 		if (MPT_STATE(db) == state) {
    118 			maxwait_state = i > maxwait_state ? i : maxwait_state;
    119 			return (MPT_OK);
    120 		}
    121 		DELAY(100);
    122 	}
    123 	return (MPT_FAIL);
    124 }
    125 
    126 
    127 /* Issue the reset COMMAND to the IOC */
    128 int
    129 mpt_soft_reset(mpt_softc_t *mpt)
    130 {
    131 	if (mpt->verbose) {
    132 		mpt_prt(mpt, "soft reset");
    133 	}
    134 
    135 	/* Have to use hard reset if we are not in Running state */
    136 	if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) {
    137 		mpt_prt(mpt, "soft reset failed: device not running");
    138 		return MPT_FAIL;
    139 	}
    140 
    141 	/* If door bell is in use we don't have a chance of getting
    142 	 * a word in since the IOC probably crashed in message
    143 	 * processing. So don't waste our time.
    144 	 */
    145 	if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) {
    146 		mpt_prt(mpt, "soft reset failed: doorbell wedged");
    147 		return MPT_FAIL;
    148 	}
    149 
    150 	/* Send the reset request to the IOC */
    151 	mpt_write(mpt, MPT_OFFSET_DOORBELL,
    152 	    MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT);
    153 	if (mpt_wait_db_ack(mpt) != MPT_OK) {
    154 		mpt_prt(mpt, "soft reset failed: ack timeout");
    155 		return MPT_FAIL;
    156 	}
    157 
    158 	/* Wait for the IOC to reload and come out of reset state */
    159 	if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) {
    160 		mpt_prt(mpt, "soft reset failed: device did not start running");
    161 		return MPT_FAIL;
    162 	}
    163 
    164 	return MPT_OK;
    165 }
    166 
    167 /* This is a magic diagnostic reset that resets all the ARM
    168  * processors in the chip.
    169  */
    170 void
    171 mpt_hard_reset(mpt_softc_t *mpt)
    172 {
    173 	if (mpt->verbose) {
    174 		mpt_prt(mpt, "hard reset");
    175 	}
    176 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xff);
    177 
    178 	/* Enable diagnostic registers */
    179 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1);
    180 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2);
    181 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3);
    182 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4);
    183 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5);
    184 
    185 	/* Diag. port is now active so we can now hit the reset bit */
    186 	mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC);
    187 
    188 	DELAY(10000);
    189 
    190 	/* Disable Diagnostic Register */
    191 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF);
    192 }
    193 
    194 /*
    195  * Reset the IOC when needed. Try software command first then if needed
    196  * poke at the magic diagnostic reset. Note that a hard reset resets
    197  * *both* IOCs on dual function chips (FC929 && LSI1030) as well as
    198  * fouls up the PCI configuration registers.
    199  */
    200 int
    201 mpt_reset(mpt_softc_t *mpt)
    202 {
    203 	int ret;
    204 
    205 	/* Try a soft reset */
    206 	if ((ret = mpt_soft_reset(mpt)) != MPT_OK) {
    207 		/* Failed; do a hard reset */
    208 		mpt_hard_reset(mpt);
    209 
    210 		/* Wait for the IOC to reload and come out of reset state */
    211 		ret = mpt_wait_state(mpt, MPT_DB_STATE_READY);
    212 		if (ret != MPT_OK) {
    213 			mpt_prt(mpt, "failed to reset device");
    214 		}
    215 	}
    216 
    217 	return ret;
    218 }
    219 
    220 /* Return a command buffer to the free queue */
    221 void
    222 mpt_free_request(mpt_softc_t *mpt, request_t *req)
    223 {
    224 	if (req == NULL || req != &mpt->request_pool[req->index]) {
    225 		panic("mpt_free_request bad req ptr\n");
    226 		return;
    227 	}
    228 	req->sequence = 0;
    229 	req->xfer = NULL;
    230 	req->debug = REQ_FREE;
    231 	SLIST_INSERT_HEAD(&mpt->request_free_list, req, link);
    232 }
    233 
    234 /* Get a command buffer from the free queue */
    235 request_t *
    236 mpt_get_request(mpt_softc_t *mpt)
    237 {
    238 	request_t *req;
    239 	req = SLIST_FIRST(&mpt->request_free_list);
    240 	if (req != NULL) {
    241 		if (req != &mpt->request_pool[req->index]) {
    242 			panic("mpt_get_request: corrupted request free list\n");
    243 		}
    244 		if (req->xfer != NULL) {
    245 			panic("mpt_get_request: corrupted request free list (xfer)\n");
    246 		}
    247 		SLIST_REMOVE_HEAD(&mpt->request_free_list, link);
    248 		req->debug = REQ_IN_PROGRESS;
    249 	}
    250 	return req;
    251 }
    252 
    253 /* Pass the command to the IOC */
    254 void
    255 mpt_send_cmd(mpt_softc_t *mpt, request_t *req)
    256 {
    257 	req->sequence = mpt->sequence++;
    258 	if (mpt->verbose > 1) {
    259 		u_int32_t *pReq;
    260 		pReq = req->req_vbuf;
    261 		mpt_prt(mpt, "Send Request %d (0x%x):",
    262 		    req->index, req->req_pbuf);
    263 		mpt_prt(mpt, "%08x %08x %08x %08x",
    264 		    pReq[0], pReq[1], pReq[2], pReq[3]);
    265 		mpt_prt(mpt, "%08x %08x %08x %08x",
    266 		    pReq[4], pReq[5], pReq[6], pReq[7]);
    267 		mpt_prt(mpt, "%08x %08x %08x %08x",
    268 		    pReq[8], pReq[9], pReq[10], pReq[11]);
    269 		mpt_prt(mpt, "%08x %08x %08x %08x",
    270 		    pReq[12], pReq[13], pReq[14], pReq[15]);
    271 	}
    272 	MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    273 	req->debug = REQ_ON_CHIP;
    274 	mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf);
    275 }
    276 
    277 /*
    278  * Give the reply buffer back to the IOC after we have
    279  * finished processing it.
    280  */
    281 void
    282 mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr)
    283 {
    284      mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
    285 }
    286 
    287 /* Get a reply from the IOC */
    288 u_int32_t
    289 mpt_pop_reply_queue(mpt_softc_t *mpt)
    290 {
    291      return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
    292 }
    293 
    294 /*
    295  * Send a command to the IOC via the handshake register.
    296  *
    297  * Only done at initialization time and for certain unusual
    298  * commands such as device/bus reset as specified by LSI.
    299  */
    300 int
    301 mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd)
    302 {
    303 	int i;
    304 	u_int32_t data, *data32;
    305 
    306 	/* Check condition of the IOC */
    307 	data = mpt_rd_db(mpt);
    308 	if (((MPT_STATE(data) != MPT_DB_STATE_READY)	&&
    309 	     (MPT_STATE(data) != MPT_DB_STATE_RUNNING)	&&
    310 	     (MPT_STATE(data) != MPT_DB_STATE_FAULT))	||
    311 	    (  MPT_DB_IS_IN_USE(data) )) {
    312 		mpt_prt(mpt, "handshake aborted due to invalid doorbell state");
    313 		mpt_print_db(data);
    314 		return(EBUSY);
    315 	}
    316 
    317 	/* We move things in 32 bit chunks */
    318 	len = (len + 3) >> 2;
    319 	data32 = cmd;
    320 
    321 	/* Clear any left over pending doorbell interrupts */
    322 	if (MPT_DB_INTR(mpt_rd_intr(mpt)))
    323 		mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    324 
    325 	/*
    326 	 * Tell the handshake reg. we are going to send a command
    327          * and how long it is going to be.
    328 	 */
    329 	data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) |
    330 	    (len << MPI_DOORBELL_ADD_DWORDS_SHIFT);
    331 	mpt_write(mpt, MPT_OFFSET_DOORBELL, data);
    332 
    333 	/* Wait for the chip to notice */
    334 	if (mpt_wait_db_int(mpt) != MPT_OK) {
    335 		mpt_prt(mpt, "mpt_send_handshake_cmd timeout1");
    336 		return ETIMEDOUT;
    337 	}
    338 
    339 	/* Clear the interrupt */
    340 	mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    341 
    342 	if (mpt_wait_db_ack(mpt) != MPT_OK) {
    343 		mpt_prt(mpt, "mpt_send_handshake_cmd timeout2");
    344 		return ETIMEDOUT;
    345 	}
    346 
    347 	/* Send the command */
    348 	for (i = 0; i < len; i++) {
    349 		mpt_write(mpt, MPT_OFFSET_DOORBELL, *data32++);
    350 		if (mpt_wait_db_ack(mpt) != MPT_OK) {
    351 			mpt_prt(mpt,
    352 			    "mpt_send_handshake_cmd timeout! index = %d", i);
    353 			return ETIMEDOUT;
    354 		}
    355 	}
    356 	return MPT_OK;
    357 }
    358 
    359 /* Get the response from the handshake register */
    360 int
    361 mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply)
    362 {
    363 	int left, reply_left;
    364 	u_int16_t *data16;
    365 	MSG_DEFAULT_REPLY *hdr;
    366 
    367 	/* We move things out in 16 bit chunks */
    368 	reply_len >>= 1;
    369 	data16 = (u_int16_t *)reply;
    370 
    371 	hdr = (MSG_DEFAULT_REPLY *)reply;
    372 
    373 	/* Get first word */
    374 	if (mpt_wait_db_int(mpt) != MPT_OK) {
    375 		mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1");
    376 		return ETIMEDOUT;
    377 	}
    378 	*data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK;
    379 	mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    380 
    381 	/* Get Second Word */
    382 	if (mpt_wait_db_int(mpt) != MPT_OK) {
    383 		mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2");
    384 		return ETIMEDOUT;
    385 	}
    386 	*data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK;
    387 	mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    388 
    389 	/* With the second word, we can now look at the length */
    390 	if (mpt->verbose > 1 && ((reply_len >> 1) != hdr->MsgLength)) {
    391 		mpt_prt(mpt, "reply length does not match message length: "
    392 			"got 0x%02x, expected 0x%02x",
    393 			hdr->MsgLength << 2, reply_len << 1);
    394 	}
    395 
    396 	/* Get rest of the reply; but don't overflow the provided buffer */
    397 	left = (hdr->MsgLength << 1) - 2;
    398 	reply_left =  reply_len - 2;
    399 	while (left--) {
    400 		u_int16_t datum;
    401 
    402 		if (mpt_wait_db_int(mpt) != MPT_OK) {
    403 			mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3");
    404 			return ETIMEDOUT;
    405 		}
    406 		datum = mpt_read(mpt, MPT_OFFSET_DOORBELL);
    407 
    408 		if (reply_left-- > 0)
    409 			*data16++ = datum & MPT_DB_DATA_MASK;
    410 
    411 		mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    412 	}
    413 
    414 	/* One more wait & clear at the end */
    415 	if (mpt_wait_db_int(mpt) != MPT_OK) {
    416 		mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4");
    417 		return ETIMEDOUT;
    418 	}
    419 	mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    420 
    421 	if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    422 		if (mpt->verbose > 1)
    423 			mpt_print_reply(hdr);
    424 		return (MPT_FAIL | hdr->IOCStatus);
    425 	}
    426 
    427 	return (0);
    428 }
    429 
    430 static int
    431 mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp)
    432 {
    433 	MSG_IOC_FACTS f_req;
    434 	int error;
    435 
    436 	memset(&f_req, 0, sizeof f_req);
    437 	f_req.Function = MPI_FUNCTION_IOC_FACTS;
    438 	f_req.MsgContext =  0x12071942;
    439 	error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
    440 	if (error)
    441 		return(error);
    442 	error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
    443 	return (error);
    444 }
    445 
    446 static int
    447 mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp)
    448 {
    449 	MSG_PORT_FACTS f_req;
    450 	int error;
    451 
    452 	/* XXX: Only getting PORT FACTS for Port 0 */
    453 	memset(&f_req, 0, sizeof f_req);
    454 	f_req.Function = MPI_FUNCTION_PORT_FACTS;
    455 	f_req.MsgContext =  0x12071943;
    456 	error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
    457 	if (error)
    458 		return(error);
    459 	error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
    460 	return (error);
    461 }
    462 
    463 /*
    464  * Send the initialization request. This is where we specify how many
    465  * SCSI busses and how many devices per bus we wish to emulate.
    466  * This is also the command that specifies the max size of the reply
    467  * frames from the IOC that we will be allocating.
    468  */
    469 static int
    470 mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
    471 {
    472 	int error = 0;
    473 	MSG_IOC_INIT init;
    474 	MSG_IOC_INIT_REPLY reply;
    475 
    476 	memset(&init, 0, sizeof init);
    477 	init.WhoInit = who;
    478 	init.Function = MPI_FUNCTION_IOC_INIT;
    479 	init.MaxDevices = mpt->mpt_max_devices;
    480 	init.MaxBuses = 1;
    481 	init.ReplyFrameSize = MPT_REPLY_SIZE;
    482 	init.MsgContext = 0x12071941;
    483 
    484 	if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) {
    485 		return(error);
    486 	}
    487 
    488 	error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply);
    489 	return (error);
    490 }
    491 
    492 
    493 /*
    494  * Utiltity routine to read configuration headers and pages
    495  */
    496 
    497 static int
    498 mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *);
    499 
    500 static int
    501 mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
    502     int PageAddress, fCONFIG_PAGE_HEADER *rslt)
    503 {
    504 	int count;
    505 	request_t *req;
    506 	MSG_CONFIG *cfgp;
    507 	MSG_CONFIG_REPLY *reply;
    508 
    509 	req = mpt_get_request(mpt);
    510 
    511 	cfgp = req->req_vbuf;
    512 	memset(cfgp, 0, sizeof *cfgp);
    513 
    514 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
    515 	cfgp->Function = MPI_FUNCTION_CONFIG;
    516 	cfgp->Header.PageNumber = (U8) PageNumber;
    517 	cfgp->Header.PageType = (U8) PageType;
    518 	cfgp->PageAddress = PageAddress;
    519 	MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
    520 	    (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    521 	    MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
    522 	cfgp->MsgContext = req->index | 0x80000000;
    523 
    524 	mpt_check_doorbell(mpt);
    525 	mpt_send_cmd(mpt, req);
    526 	count = 0;
    527 	do {
    528 		DELAY(500);
    529 		mpt_intr(mpt);
    530 		if (++count == 1000) {
    531 			mpt_prt(mpt, "read_cfg_header timed out");
    532 			return (-1);
    533 		}
    534 	} while (req->debug == REQ_ON_CHIP);
    535 
    536 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    537         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    538 		mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
    539 		    reply->IOCStatus);
    540 		mpt_free_reply(mpt, (req->sequence << 1));
    541 		return (-1);
    542 	}
    543 	bcopy(&reply->Header, rslt, sizeof (fCONFIG_PAGE_HEADER));
    544 	mpt_free_reply(mpt, (req->sequence << 1));
    545 	mpt_free_request(mpt, req);
    546 	return (0);
    547 }
    548 
    549 #define	CFG_DATA_OFF	128
    550 
    551 int
    552 mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
    553 {
    554 	int count;
    555 	request_t *req;
    556 	SGE_SIMPLE32 *se;
    557 	MSG_CONFIG *cfgp;
    558 	size_t amt;
    559 	MSG_CONFIG_REPLY *reply;
    560 
    561 	req = mpt_get_request(mpt);
    562 
    563 	cfgp = req->req_vbuf;
    564 	memset(cfgp, 0, MPT_REQUEST_AREA);
    565 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
    566 	cfgp->Function = MPI_FUNCTION_CONFIG;
    567 	cfgp->Header = *hdr;
    568  	amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
    569 	cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
    570 	cfgp->PageAddress = PageAddress;
    571 	se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
    572 	se->Address = req->req_pbuf + CFG_DATA_OFF;
    573 	MPI_pSGE_SET_LENGTH(se, amt);
    574 	MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
    575 	    MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    576 	    MPI_SGE_FLAGS_END_OF_LIST));
    577 
    578 	cfgp->MsgContext = req->index | 0x80000000;
    579 
    580 	mpt_check_doorbell(mpt);
    581 	mpt_send_cmd(mpt, req);
    582 	count = 0;
    583 	do {
    584 		DELAY(500);
    585 		mpt_intr(mpt);
    586 		if (++count == 1000) {
    587 			mpt_prt(mpt, "read_cfg_page timed out");
    588 			return (-1);
    589 		}
    590 	} while (req->debug == REQ_ON_CHIP);
    591 
    592 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    593         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    594 		mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
    595 		    reply->IOCStatus);
    596 		mpt_free_reply(mpt, (req->sequence << 1));
    597 		return (-1);
    598 	}
    599 	mpt_free_reply(mpt, (req->sequence << 1));
    600 #if 0 /* XXXJRT */
    601 	bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
    602 	    BUS_DMASYNC_POSTREAD);
    603 #endif
    604 	if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    605 	    cfgp->Header.PageNumber == 0) {
    606 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
    607 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    608 	    cfgp->Header.PageNumber == 1) {
    609 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
    610 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    611 	    cfgp->Header.PageNumber == 2) {
    612 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
    613 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    614 	    cfgp->Header.PageNumber == 0) {
    615 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
    616 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    617 	    cfgp->Header.PageNumber == 1) {
    618 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
    619 	}
    620 	memcpy(hdr, (char *)req->req_vbuf + CFG_DATA_OFF, amt);
    621 	mpt_free_request(mpt, req);
    622 	return (0);
    623 }
    624 
    625 int
    626 mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
    627 {
    628 	int count, hdr_attr;
    629 	request_t *req;
    630 	SGE_SIMPLE32 *se;
    631 	MSG_CONFIG *cfgp;
    632 	size_t amt;
    633 	MSG_CONFIG_REPLY *reply;
    634 
    635 	req = mpt_get_request(mpt);
    636 
    637 	cfgp = req->req_vbuf;
    638 	memset(cfgp, 0, sizeof *cfgp);
    639 
    640 	hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
    641 	if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
    642 	    hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
    643 		mpt_prt(mpt, "page type 0x%x not changeable",
    644 		    hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
    645 		return (-1);
    646 	}
    647 	hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
    648 
    649 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
    650 	cfgp->Function = MPI_FUNCTION_CONFIG;
    651 	cfgp->Header = *hdr;
    652  	amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
    653 	cfgp->PageAddress = PageAddress;
    654 
    655 	se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
    656 	se->Address = req->req_pbuf + CFG_DATA_OFF;
    657 	MPI_pSGE_SET_LENGTH(se, amt);
    658 	MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
    659 	    MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    660 	    MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
    661 
    662 	cfgp->MsgContext = req->index | 0x80000000;
    663 
    664 	if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    665 	    cfgp->Header.PageNumber == 0) {
    666 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
    667 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    668 	    cfgp->Header.PageNumber == 1) {
    669 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
    670 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    671 	    cfgp->Header.PageNumber == 2) {
    672 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
    673 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    674 	    cfgp->Header.PageNumber == 0) {
    675 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
    676 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    677 	    cfgp->Header.PageNumber == 1) {
    678 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
    679 	}
    680 	memcpy((char *)req->req_vbuf + CFG_DATA_OFF, hdr, amt);
    681 	/* Restore stripped out attributes */
    682 	hdr->PageType |= hdr_attr;
    683 
    684 	mpt_check_doorbell(mpt);
    685 	mpt_send_cmd(mpt, req);
    686 	count = 0;
    687 	do {
    688 		DELAY(500);
    689 		mpt_intr(mpt);
    690 		if (++count == 1000) {
    691 			hdr->PageType |= hdr_attr;
    692 			mpt_prt(mpt, "mpt_write_cfg_page timed out");
    693 			return (-1);
    694 		}
    695 	} while (req->debug == REQ_ON_CHIP);
    696 
    697 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    698         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    699 		mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
    700 		    reply->IOCStatus);
    701 		mpt_free_reply(mpt, (req->sequence << 1));
    702 		return (-1);
    703 	}
    704 	mpt_free_reply(mpt, (req->sequence << 1));
    705 
    706 	mpt_free_request(mpt, req);
    707 	return (0);
    708 }
    709 
    710 /*
    711  * Read SCSI configuration information
    712  */
    713 static int
    714 mpt_read_config_info_spi(mpt_softc_t *mpt)
    715 {
    716 	int rv, i;
    717 
    718 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
    719 	    0, &mpt->mpt_port_page0.Header);
    720 	if (rv) {
    721 		return (-1);
    722 	}
    723 	if (mpt->verbose > 1) {
    724 		mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
    725 		    mpt->mpt_port_page0.Header.PageVersion,
    726 		    mpt->mpt_port_page0.Header.PageLength,
    727 		    mpt->mpt_port_page0.Header.PageNumber,
    728 		    mpt->mpt_port_page0.Header.PageType);
    729 	}
    730 
    731 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
    732 	    0, &mpt->mpt_port_page1.Header);
    733 	if (rv) {
    734 		return (-1);
    735 	}
    736 	if (mpt->verbose > 1) {
    737 		mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
    738 		    mpt->mpt_port_page1.Header.PageVersion,
    739 		    mpt->mpt_port_page1.Header.PageLength,
    740 		    mpt->mpt_port_page1.Header.PageNumber,
    741 		    mpt->mpt_port_page1.Header.PageType);
    742 	}
    743 
    744 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
    745 	    0, &mpt->mpt_port_page2.Header);
    746 	if (rv) {
    747 		return (-1);
    748 	}
    749 
    750 	if (mpt->verbose > 1) {
    751 		mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
    752 		    mpt->mpt_port_page1.Header.PageVersion,
    753 		    mpt->mpt_port_page1.Header.PageLength,
    754 		    mpt->mpt_port_page1.Header.PageNumber,
    755 		    mpt->mpt_port_page1.Header.PageType);
    756 	}
    757 
    758 	for (i = 0; i < 16; i++) {
    759 		rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
    760 		    0, i, &mpt->mpt_dev_page0[i].Header);
    761 		if (rv) {
    762 			return (-1);
    763 		}
    764 		if (mpt->verbose > 1) {
    765 			mpt_prt(mpt,
    766 			    "SPI Target %d Device Page 0 Header: %x %x %x %x",
    767 			    i, mpt->mpt_dev_page0[i].Header.PageVersion,
    768 			    mpt->mpt_dev_page0[i].Header.PageLength,
    769 			    mpt->mpt_dev_page0[i].Header.PageNumber,
    770 			    mpt->mpt_dev_page0[i].Header.PageType);
    771 		}
    772 
    773 		rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
    774 		    1, i, &mpt->mpt_dev_page1[i].Header);
    775 		if (rv) {
    776 			return (-1);
    777 		}
    778 		if (mpt->verbose > 1) {
    779 			mpt_prt(mpt,
    780 			    "SPI Target %d Device Page 1 Header: %x %x %x %x",
    781 			    i, mpt->mpt_dev_page1[i].Header.PageVersion,
    782 			    mpt->mpt_dev_page1[i].Header.PageLength,
    783 			    mpt->mpt_dev_page1[i].Header.PageNumber,
    784 			    mpt->mpt_dev_page1[i].Header.PageType);
    785 		}
    786 	}
    787 
    788 	/*
    789 	 * At this point, we don't *have* to fail. As long as we have
    790 	 * valid config header information, we can (barely) lurch
    791 	 * along.
    792 	 */
    793 
    794 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
    795 	if (rv) {
    796 		mpt_prt(mpt, "failed to read SPI Port Page 0");
    797 	} else if (mpt->verbose > 1) {
    798 		mpt_prt(mpt,
    799 		    "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
    800 		    mpt->mpt_port_page0.Capabilities,
    801 		    mpt->mpt_port_page0.PhysicalInterface);
    802 	}
    803 
    804 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
    805 	if (rv) {
    806 		mpt_prt(mpt, "failed to read SPI Port Page 1");
    807 	} else if (mpt->verbose > 1) {
    808 		mpt_prt(mpt,
    809 		    "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
    810 		    mpt->mpt_port_page1.Configuration,
    811 		    mpt->mpt_port_page1.OnBusTimerValue);
    812 	}
    813 
    814 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
    815 	if (rv) {
    816 		mpt_prt(mpt, "failed to read SPI Port Page 2");
    817 	} else if (mpt->verbose > 1) {
    818 		mpt_prt(mpt,
    819 		    "SPI Port Page 2: Flags %x Settings %x",
    820 		    mpt->mpt_port_page2.PortFlags,
    821 		    mpt->mpt_port_page2.PortSettings);
    822 		for (i = 0; i < 16; i++) {
    823 			mpt_prt(mpt,
    824 		  	    "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
    825 			    i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
    826 			    mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
    827 			    mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
    828 		}
    829 	}
    830 
    831 	for (i = 0; i < 16; i++) {
    832 		rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
    833 		if (rv) {
    834 			mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
    835 			continue;
    836 		}
    837 		if (mpt->verbose > 1) {
    838 			mpt_prt(mpt,
    839 			    "SPI Tgt %d Page 0: NParms %x Information %x",
    840 			    i, mpt->mpt_dev_page0[i].NegotiatedParameters,
    841 			    mpt->mpt_dev_page0[i].Information);
    842 		}
    843 		rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
    844 		if (rv) {
    845 			mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
    846 			continue;
    847 		}
    848 		if (mpt->verbose > 1) {
    849 			mpt_prt(mpt,
    850 			    "SPI Tgt %d Page 1: RParms %x Configuration %x",
    851 			    i, mpt->mpt_dev_page1[i].RequestedParameters,
    852 			    mpt->mpt_dev_page1[i].Configuration);
    853 		}
    854 	}
    855 	return (0);
    856 }
    857 
    858 /*
    859  * Validate SPI configuration information.
    860  *
    861  * In particular, validate SPI Port Page 1.
    862  */
    863 static int
    864 mpt_set_initial_config_spi(mpt_softc_t *mpt)
    865 {
    866 	int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
    867 
    868 	mpt->mpt_disc_enable = 0xff;
    869 	mpt->mpt_tag_enable = 0;
    870 
    871 	if (mpt->mpt_port_page1.Configuration != pp1val) {
    872 		fCONFIG_PAGE_SCSI_PORT_1 tmp;
    873 		mpt_prt(mpt,
    874 		    "SPI Port Page 1 Config value bad (%x)- should be %x",
    875 		    mpt->mpt_port_page1.Configuration, pp1val);
    876 		tmp = mpt->mpt_port_page1;
    877 		tmp.Configuration = pp1val;
    878 		if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
    879 			return (-1);
    880 		}
    881 		if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
    882 			return (-1);
    883 		}
    884 		if (tmp.Configuration != pp1val) {
    885 			mpt_prt(mpt,
    886 			    "failed to reset SPI Port Page 1 Config value");
    887 			return (-1);
    888 		}
    889 		mpt->mpt_port_page1 = tmp;
    890 	}
    891 
    892 	for (i = 0; i < 16; i++) {
    893 		fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
    894 		tmp = mpt->mpt_dev_page1[i];
    895 		tmp.RequestedParameters = 0;
    896 		tmp.Configuration = 0;
    897 		if (mpt->verbose > 1) {
    898 			mpt_prt(mpt,
    899 			    "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
    900 			    i, tmp.RequestedParameters, tmp.Configuration);
    901 		}
    902 		if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
    903 			return (-1);
    904 		}
    905 		if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
    906 			return (-1);
    907 		}
    908 		mpt->mpt_dev_page1[i] = tmp;
    909 		if (mpt->verbose > 1) {
    910 			mpt_prt(mpt,
    911 		 	    "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
    912 			    mpt->mpt_dev_page1[i].RequestedParameters,
    913 			    mpt->mpt_dev_page1[i].Configuration);
    914 		}
    915 	}
    916 	return (0);
    917 }
    918 
    919 /*
    920  * Enable IOC port
    921  */
    922 static int
    923 mpt_send_port_enable(mpt_softc_t *mpt, int port)
    924 {
    925 	int count;
    926 	request_t *req;
    927 	MSG_PORT_ENABLE *enable_req;
    928 
    929 	req = mpt_get_request(mpt);
    930 
    931 	enable_req = req->req_vbuf;
    932 	memset(enable_req, 0, sizeof *enable_req);
    933 
    934 	enable_req->Function   = MPI_FUNCTION_PORT_ENABLE;
    935 	enable_req->MsgContext = req->index | 0x80000000;
    936 	enable_req->PortNumber = port;
    937 
    938 	mpt_check_doorbell(mpt);
    939 	if (mpt->verbose > 1) {
    940 		mpt_prt(mpt, "enabling port %d", port);
    941 	}
    942 	mpt_send_cmd(mpt, req);
    943 
    944 	count = 0;
    945 	do {
    946 		DELAY(500);
    947 		mpt_intr(mpt);
    948 		if (++count == 100000) {
    949 			mpt_prt(mpt, "port enable timed out");
    950 			return (-1);
    951 		}
    952 	} while (req->debug == REQ_ON_CHIP);
    953 	mpt_free_request(mpt, req);
    954 	return (0);
    955 }
    956 
    957 /*
    958  * Enable/Disable asynchronous event reporting.
    959  *
    960  * NB: this is the first command we send via shared memory
    961  * instead of the handshake register.
    962  */
    963 static int
    964 mpt_send_event_request(mpt_softc_t *mpt, int onoff)
    965 {
    966 	request_t *req;
    967 	MSG_EVENT_NOTIFY *enable_req;
    968 
    969 	req = mpt_get_request(mpt);
    970 
    971 	enable_req = req->req_vbuf;
    972 	memset(enable_req, 0, sizeof *enable_req);
    973 
    974 	enable_req->Function   = MPI_FUNCTION_EVENT_NOTIFICATION;
    975 	enable_req->MsgContext = req->index | 0x80000000;
    976 	enable_req->Switch     = onoff;
    977 
    978 	mpt_check_doorbell(mpt);
    979 	if (mpt->verbose > 1) {
    980 		mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
    981 	}
    982 	mpt_send_cmd(mpt, req);
    983 
    984 	return (0);
    985 }
    986 
    987 /*
    988  * Un-mask the interrupts on the chip.
    989  */
    990 void
    991 mpt_enable_ints(mpt_softc_t *mpt)
    992 {
    993 	/* Unmask every thing except door bell int */
    994 	mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
    995 }
    996 
    997 /*
    998  * Mask the interrupts on the chip.
    999  */
   1000 void
   1001 mpt_disable_ints(mpt_softc_t *mpt)
   1002 {
   1003 	/* Mask all interrupts */
   1004 	mpt_write(mpt, MPT_OFFSET_INTR_MASK,
   1005 	    MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
   1006 }
   1007 
   1008 /* (Re)Initialize the chip for use */
   1009 int
   1010 mpt_hw_init(mpt_softc_t *mpt)
   1011 {
   1012 	u_int32_t	db;
   1013 	int		try;
   1014 
   1015 	/*
   1016 	 * Start by making sure we're not at FAULT or RESET state
   1017 	 */
   1018 	for (try = 0; try < MPT_MAX_TRYS; try++) {
   1019 
   1020 		db = mpt_rd_db(mpt);
   1021 
   1022 		switch (MPT_STATE(db)) {
   1023 		case MPT_DB_STATE_READY:
   1024 			return (0);
   1025 
   1026 		default:
   1027 			/* if peer has already reset us, don't do it again! */
   1028 			if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER)
   1029 				return (0);
   1030 			/*FALLTHRU*/
   1031 		case MPT_DB_STATE_RESET:
   1032 		case MPT_DB_STATE_FAULT:
   1033 			if (mpt_reset(mpt) != MPT_OK) {
   1034 				DELAY(10000);
   1035 				continue;
   1036 			}
   1037 			break;
   1038 		}
   1039 	}
   1040 	return (EIO);
   1041 }
   1042 
   1043 int
   1044 mpt_init(mpt_softc_t *mpt, u_int32_t who)
   1045 {
   1046         int try;
   1047         MSG_IOC_FACTS_REPLY facts;
   1048         MSG_PORT_FACTS_REPLY pfp;
   1049 	u_int32_t pptr;
   1050         int val;
   1051 
   1052 	/* Put all request buffers (back) on the free list */
   1053         SLIST_INIT(&mpt->request_free_list);
   1054 	for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
   1055 		mpt_free_request(mpt, &mpt->request_pool[val]);
   1056 	}
   1057 
   1058 	if (mpt->verbose > 1) {
   1059 		mpt_prt(mpt, "doorbell req = %s",
   1060 		    mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
   1061 	}
   1062 
   1063 	/*
   1064 	 * Start by making sure we're not at FAULT or RESET state
   1065 	 */
   1066 	if (mpt_hw_init(mpt) != 0)
   1067 		return (EIO);
   1068 
   1069 	for (try = 0; try < MPT_MAX_TRYS; try++) {
   1070 		/*
   1071 		 * No need to reset if the IOC is already in the READY state.
   1072 		 */
   1073 
   1074 		if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
   1075 			mpt_prt(mpt, "mpt_get_iocfacts failed");
   1076 			continue;
   1077 		}
   1078 
   1079 		if (mpt->verbose > 1) {
   1080 			mpt_prt(mpt,
   1081 			    "IOCFACTS: GlobalCredits=%d BlockSize=%u "
   1082 			    "Request Frame Size %u\n", facts.GlobalCredits,
   1083 			    facts.BlockSize, facts.RequestFrameSize);
   1084 		}
   1085 		mpt->mpt_max_devices = facts.MaxDevices;
   1086 		mpt->mpt_global_credits = facts.GlobalCredits;
   1087 		mpt->request_frame_size = facts.RequestFrameSize;
   1088 
   1089 		if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
   1090 			mpt_prt(mpt, "mpt_get_portfacts failed");
   1091 			continue;
   1092 		}
   1093 
   1094 		if (mpt->verbose > 1) {
   1095 			mpt_prt(mpt,
   1096 			    "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d\n",
   1097 			    pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
   1098 			    pfp.MaxDevices);
   1099 		}
   1100 
   1101 		if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
   1102 			mpt_prt(mpt, "initiator role unsupported");
   1103 			return (ENXIO);
   1104 		}
   1105 
   1106 		switch (pfp.PortType) {
   1107 		case MPI_PORTFACTS_PORTTYPE_FC:
   1108 			mpt->is_fc = 1;
   1109 			mpt->mpt_max_devices = 255;
   1110 			break;
   1111 		case MPI_PORTFACTS_PORTTYPE_SCSI:
   1112 			mpt->is_scsi = 1;
   1113 			/* some SPI controllers (VMWare, Sun) lie */
   1114 			mpt->mpt_max_devices = 16;
   1115 			break;
   1116 		case MPI_PORTFACTS_PORTTYPE_SAS:
   1117 			mpt->is_sas = 1;
   1118 			break;
   1119 		default:
   1120 			mpt_prt(mpt, "Unsupported Port Type (%x)",
   1121 			    pfp.PortType);
   1122 			return (ENXIO);
   1123 		}
   1124 
   1125 		mpt->mpt_ini_id = pfp.PortSCSIID;
   1126 
   1127 		if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
   1128 			mpt_prt(mpt, "mpt_send_ioc_init failed");
   1129 			continue;
   1130 		}
   1131 
   1132 		if (mpt->verbose > 1) {
   1133 			mpt_prt(mpt, "mpt_send_ioc_init ok");
   1134 		}
   1135 
   1136 		if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
   1137 			mpt_prt(mpt, "IOC failed to go to run state");
   1138 			continue;
   1139 		}
   1140 		if (mpt->verbose > 1) {
   1141 			mpt_prt(mpt, "IOC now at RUNSTATE");
   1142 		}
   1143 
   1144 		/*
   1145 		 * Give it reply buffers
   1146 		 *
   1147 		 * Do *not* except global credits.
   1148 		 */
   1149 		for (val = 0, pptr = mpt->reply_phys;
   1150 		    (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
   1151 		     pptr += MPT_REPLY_SIZE) {
   1152 			mpt_free_reply(mpt, pptr);
   1153 			if (++val == mpt->mpt_global_credits - 1)
   1154 				break;
   1155 		}
   1156 
   1157 		/*
   1158 		 * Enable asynchronous event reporting
   1159 		 */
   1160 		mpt_send_event_request(mpt, 1);
   1161 
   1162 
   1163 		/*
   1164 		 * Read set up initial configuration information
   1165 		 * (SPI only for now)
   1166 		 */
   1167 
   1168 		if (mpt->is_scsi) {
   1169 			if (mpt_read_config_info_spi(mpt)) {
   1170 				return (EIO);
   1171 			}
   1172 			if (mpt_set_initial_config_spi(mpt)) {
   1173 				return (EIO);
   1174 			}
   1175 		}
   1176 
   1177 		/*
   1178 		 * Now enable the port
   1179 		 */
   1180 		if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
   1181 			mpt_prt(mpt, "failed to enable port 0");
   1182 			continue;
   1183 		}
   1184 
   1185 		if (mpt->verbose > 1) {
   1186 			mpt_prt(mpt, "enabled port 0");
   1187 		}
   1188 
   1189 		/* Everything worked */
   1190 		break;
   1191 	}
   1192 
   1193 	if (try >= MPT_MAX_TRYS) {
   1194 		mpt_prt(mpt, "failed to initialize IOC");
   1195 		return (EIO);
   1196 	}
   1197 
   1198 	if (mpt->verbose > 1) {
   1199 		mpt_prt(mpt, "enabling interrupts");
   1200 	}
   1201 
   1202 	mpt_enable_ints(mpt);
   1203 	return (0);
   1204 }
   1205