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