Home | History | Annotate | Line # | Download | only in ic
mpt.c revision 1.14
      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 
    120 static int maxwait_ack = 0;
    121 static int maxwait_int = 0;
    122 static int maxwait_state = 0;
    123 
    124 static inline u_int32_t
    125 mpt_rd_db(mpt_softc_t *mpt)
    126 {
    127 	return mpt_read(mpt, MPT_OFFSET_DOORBELL);
    128 }
    129 
    130 static inline u_int32_t
    131 mpt_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 */
    137 static int
    138 mpt_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 */
    153 static int
    154 mpt_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 */
    168 void
    169 mpt_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 */
    179 static int
    180 mpt_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 */
    197 int
    198 mpt_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  */
    239 void
    240 mpt_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  */
    269 int
    270 mpt_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 */
    290 void
    291 mpt_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 */
    304 request_t *
    305 mpt_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 */
    323 void
    324 mpt_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  */
    350 void
    351 mpt_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 */
    357 u_int32_t
    358 mpt_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  */
    369 int
    370 mpt_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 */
    429 int
    430 mpt_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 
    501 static int
    502 mpt_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 
    517 static int
    518 mpt_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  */
    540 static int
    541 mpt_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 
    568 static int
    569 mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *);
    570 
    571 static int
    572 mpt_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 
    622 int
    623 mpt_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 
    697 int
    698 mpt_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  */
    786 static int
    787 mpt_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  */
    941 static int
    942 mpt_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  */
   1007 static int
   1008 mpt_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  */
   1048 static int
   1049 mpt_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  */
   1075 void
   1076 mpt_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  */
   1085 void
   1086 mpt_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 */
   1094 int
   1095 mpt_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 
   1128 int
   1129 mpt_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 	u_int32_t pptr;
   1135         int val;
   1136 
   1137 	/* Put all request buffers (back) on the free list */
   1138         SLIST_INIT(&mpt->request_free_list);
   1139 	for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
   1140 		mpt_free_request(mpt, &mpt->request_pool[val]);
   1141 	}
   1142 
   1143 	if (mpt->verbose > 1) {
   1144 		mpt_prt(mpt, "doorbell req = %s",
   1145 		    mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
   1146 	}
   1147 
   1148 	/*
   1149 	 * Start by making sure we're not at FAULT or RESET state
   1150 	 */
   1151 	if (mpt_hw_init(mpt) != 0)
   1152 		return (EIO);
   1153 
   1154 	for (try = 0; try < MPT_MAX_TRYS; try++) {
   1155 		/*
   1156 		 * No need to reset if the IOC is already in the READY state.
   1157 		 */
   1158 
   1159 		if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
   1160 			mpt_prt(mpt, "mpt_get_iocfacts failed");
   1161 			continue;
   1162 		}
   1163 		mpt2host_iocfacts_reply(&facts);
   1164 
   1165 		if (mpt->verbose > 1) {
   1166 			mpt_prt(mpt,
   1167 			    "IOCFACTS: GlobalCredits=%d BlockSize=%u "
   1168 			    "Request Frame Size %u", facts.GlobalCredits,
   1169 			    facts.BlockSize, facts.RequestFrameSize);
   1170 		}
   1171 		mpt->mpt_max_devices = facts.MaxDevices;
   1172 		mpt->mpt_global_credits = facts.GlobalCredits;
   1173 		mpt->request_frame_size = facts.RequestFrameSize;
   1174 
   1175 		if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
   1176 			mpt_prt(mpt, "mpt_get_portfacts failed");
   1177 			continue;
   1178 		}
   1179 		mpt2host_portfacts_reply(&pfp);
   1180 
   1181 		if (mpt->verbose > 1) {
   1182 			mpt_prt(mpt,
   1183 			    "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d",
   1184 			    pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
   1185 			    pfp.MaxDevices);
   1186 		}
   1187 
   1188 		if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
   1189 			mpt_prt(mpt, "initiator role unsupported");
   1190 			return (ENXIO);
   1191 		}
   1192 
   1193 		switch (pfp.PortType) {
   1194 		case MPI_PORTFACTS_PORTTYPE_FC:
   1195 			mpt->is_fc = 1;
   1196 			mpt->mpt_max_devices = 255;
   1197 			break;
   1198 		case MPI_PORTFACTS_PORTTYPE_SCSI:
   1199 			mpt->is_scsi = 1;
   1200 			/* some SPI controllers (VMWare, Sun) lie */
   1201 			mpt->mpt_max_devices = 16;
   1202 			break;
   1203 		case MPI_PORTFACTS_PORTTYPE_SAS:
   1204 			mpt->is_sas = 1;
   1205 			break;
   1206 		default:
   1207 			mpt_prt(mpt, "Unsupported Port Type (%x)",
   1208 			    pfp.PortType);
   1209 			return (ENXIO);
   1210 		}
   1211 
   1212 		mpt->mpt_ini_id = pfp.PortSCSIID;
   1213 
   1214 		if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
   1215 			mpt_prt(mpt, "mpt_send_ioc_init failed");
   1216 			continue;
   1217 		}
   1218 
   1219 		if (mpt->verbose > 1) {
   1220 			mpt_prt(mpt, "mpt_send_ioc_init ok");
   1221 		}
   1222 
   1223 		if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
   1224 			mpt_prt(mpt, "IOC failed to go to run state");
   1225 			continue;
   1226 		}
   1227 		if (mpt->verbose > 1) {
   1228 			mpt_prt(mpt, "IOC now at RUNSTATE");
   1229 		}
   1230 
   1231 		/*
   1232 		 * Give it reply buffers
   1233 		 *
   1234 		 * Do *not* except global credits.
   1235 		 */
   1236 		for (val = 0, pptr = mpt->reply_phys;
   1237 		    (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
   1238 		     pptr += MPT_REPLY_SIZE) {
   1239 			mpt_free_reply(mpt, pptr);
   1240 			if (++val == mpt->mpt_global_credits - 1)
   1241 				break;
   1242 		}
   1243 
   1244 		/*
   1245 		 * Enable asynchronous event reporting
   1246 		 */
   1247 		mpt_send_event_request(mpt, 1);
   1248 
   1249 
   1250 		/*
   1251 		 * Read set up initial configuration information
   1252 		 * (SPI only for now)
   1253 		 */
   1254 
   1255 		if (mpt->is_scsi) {
   1256 			if (mpt_read_config_info_spi(mpt)) {
   1257 				return (EIO);
   1258 			}
   1259 			if (mpt_set_initial_config_spi(mpt)) {
   1260 				return (EIO);
   1261 			}
   1262 		}
   1263 
   1264 		/*
   1265 		 * Now enable the port
   1266 		 */
   1267 		if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
   1268 			mpt_prt(mpt, "failed to enable port 0");
   1269 			continue;
   1270 		}
   1271 
   1272 		if (mpt->verbose > 1) {
   1273 			mpt_prt(mpt, "enabled port 0");
   1274 		}
   1275 
   1276 		/* Everything worked */
   1277 		break;
   1278 	}
   1279 
   1280 	if (try >= MPT_MAX_TRYS) {
   1281 		mpt_prt(mpt, "failed to initialize IOC");
   1282 		return (EIO);
   1283 	}
   1284 
   1285 	if (mpt->verbose > 1) {
   1286 		mpt_prt(mpt, "enabling interrupts");
   1287 	}
   1288 
   1289 	mpt_enable_ints(mpt);
   1290 	return (0);
   1291 }
   1292 
   1293 /*
   1294  * Endian Conversion Functions- only used on Big Endian machines
   1295  */
   1296 #if	_BYTE_ORDER == _BIG_ENDIAN
   1297 void
   1298 mpt2host_sge_simple_union(SGE_SIMPLE_UNION *sge)
   1299 {
   1300 
   1301 	MPT_2_HOST32(sge, FlagsLength);
   1302 	MPT_2_HOST32(sge, _u.Address64.Low);
   1303 	MPT_2_HOST32(sge, _u.Address64.High);
   1304 }
   1305 
   1306 void
   1307 mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *rp)
   1308 {
   1309 
   1310 	MPT_2_HOST16(rp, MsgVersion);
   1311 #if 0
   1312 	MPT_2_HOST16(rp, HeaderVersion);
   1313 #endif
   1314 	MPT_2_HOST32(rp, MsgContext);
   1315 	MPT_2_HOST16(rp, IOCExceptions);
   1316 	MPT_2_HOST16(rp, IOCStatus);
   1317 	MPT_2_HOST32(rp, IOCLogInfo);
   1318 	MPT_2_HOST16(rp, ReplyQueueDepth);
   1319 	MPT_2_HOST16(rp, RequestFrameSize);
   1320 	MPT_2_HOST16(rp, Reserved_0101_FWVersion);
   1321 	MPT_2_HOST16(rp, ProductID);
   1322 	MPT_2_HOST32(rp, CurrentHostMfaHighAddr);
   1323 	MPT_2_HOST16(rp, GlobalCredits);
   1324 	MPT_2_HOST32(rp, CurrentSenseBufferHighAddr);
   1325 	MPT_2_HOST16(rp, CurReplyFrameSize);
   1326 	MPT_2_HOST32(rp, FWImageSize);
   1327 #if 0
   1328 	MPT_2_HOST32(rp, IOCCapabilities);
   1329 #endif
   1330 	MPT_2_HOST32(rp, FWVersion.Word);
   1331 #if 0
   1332 	MPT_2_HOST16(rp, HighPriorityQueueDepth);
   1333 	MPT_2_HOST16(rp, Reserved2);
   1334 	mpt2host_sge_simple_union(&rp->HostPageBufferSGE);
   1335 	MPT_2_HOST32(rp, ReplyFifoHostSignalingAddr);
   1336 #endif
   1337 }
   1338 
   1339 void
   1340 mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *pfp)
   1341 {
   1342 
   1343 	MPT_2_HOST16(pfp, Reserved);
   1344 	MPT_2_HOST16(pfp, Reserved1);
   1345 	MPT_2_HOST32(pfp, MsgContext);
   1346 	MPT_2_HOST16(pfp, Reserved2);
   1347 	MPT_2_HOST16(pfp, IOCStatus);
   1348 	MPT_2_HOST32(pfp, IOCLogInfo);
   1349 	MPT_2_HOST16(pfp, MaxDevices);
   1350 	MPT_2_HOST16(pfp, PortSCSIID);
   1351 	MPT_2_HOST16(pfp, ProtocolFlags);
   1352 	MPT_2_HOST16(pfp, MaxPostedCmdBuffers);
   1353 	MPT_2_HOST16(pfp, MaxPersistentIDs);
   1354 	MPT_2_HOST16(pfp, MaxLanBuckets);
   1355 	MPT_2_HOST16(pfp, Reserved4);
   1356 	MPT_2_HOST32(pfp, Reserved5);
   1357 }
   1358 
   1359 void
   1360 mpt2host_config_page_scsi_port_0(fCONFIG_PAGE_SCSI_PORT_0 *sp0)
   1361 {
   1362 
   1363 	MPT_2_HOST32(sp0, Capabilities);
   1364 	MPT_2_HOST32(sp0, PhysicalInterface);
   1365 }
   1366 
   1367 void
   1368 mpt2host_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
   1369 {
   1370 
   1371 	MPT_2_HOST32(sp1, Configuration);
   1372 	MPT_2_HOST32(sp1, OnBusTimerValue);
   1373 #if 0
   1374 	MPT_2_HOST16(sp1, IDConfig);
   1375 #endif
   1376 }
   1377 
   1378 void
   1379 host2mpt_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
   1380 {
   1381 
   1382 	HOST_2_MPT32(sp1, Configuration);
   1383 	HOST_2_MPT32(sp1, OnBusTimerValue);
   1384 #if 0
   1385 	HOST_2_MPT16(sp1, IDConfig);
   1386 #endif
   1387 }
   1388 
   1389 void
   1390 mpt2host_config_page_scsi_port_2(fCONFIG_PAGE_SCSI_PORT_2 *sp2)
   1391 {
   1392 	int i;
   1393 
   1394 	MPT_2_HOST32(sp2, PortFlags);
   1395 	MPT_2_HOST32(sp2, PortSettings);
   1396 	for (i = 0; i < sizeof(sp2->DeviceSettings) /
   1397 	    sizeof(*sp2->DeviceSettings); i++) {
   1398 		MPT_2_HOST16(sp2, DeviceSettings[i].DeviceFlags);
   1399 	}
   1400 }
   1401 
   1402 void
   1403 mpt2host_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
   1404 {
   1405 
   1406 	MPT_2_HOST32(sd0, NegotiatedParameters);
   1407 	MPT_2_HOST32(sd0, Information);
   1408 }
   1409 
   1410 void
   1411 host2mpt_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
   1412 {
   1413 
   1414 	HOST_2_MPT32(sd0, NegotiatedParameters);
   1415 	HOST_2_MPT32(sd0, Information);
   1416 }
   1417 
   1418 void
   1419 mpt2host_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
   1420 {
   1421 
   1422 	MPT_2_HOST32(sd1, RequestedParameters);
   1423 	MPT_2_HOST32(sd1, Reserved);
   1424 	MPT_2_HOST32(sd1, Configuration);
   1425 }
   1426 
   1427 void
   1428 host2mpt_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
   1429 {
   1430 
   1431 	HOST_2_MPT32(sd1, RequestedParameters);
   1432 	HOST_2_MPT32(sd1, Reserved);
   1433 	HOST_2_MPT32(sd1, Configuration);
   1434 }
   1435 
   1436 void
   1437 mpt2host_config_page_fc_port_0(fCONFIG_PAGE_FC_PORT_0 *fp0)
   1438 {
   1439 
   1440 	MPT_2_HOST32(fp0, Flags);
   1441 	MPT_2_HOST32(fp0, PortIdentifier);
   1442 	MPT_2_HOST32(fp0, WWNN.Low);
   1443 	MPT_2_HOST32(fp0, WWNN.High);
   1444 	MPT_2_HOST32(fp0, WWPN.Low);
   1445 	MPT_2_HOST32(fp0, WWPN.High);
   1446 	MPT_2_HOST32(fp0, SupportedServiceClass);
   1447 	MPT_2_HOST32(fp0, SupportedSpeeds);
   1448 	MPT_2_HOST32(fp0, CurrentSpeed);
   1449 	MPT_2_HOST32(fp0, MaxFrameSize);
   1450 	MPT_2_HOST32(fp0, FabricWWNN.Low);
   1451 	MPT_2_HOST32(fp0, FabricWWNN.High);
   1452 	MPT_2_HOST32(fp0, FabricWWPN.Low);
   1453 	MPT_2_HOST32(fp0, FabricWWPN.High);
   1454 	MPT_2_HOST32(fp0, DiscoveredPortsCount);
   1455 	MPT_2_HOST32(fp0, MaxInitiators);
   1456 }
   1457 
   1458 void
   1459 mpt2host_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
   1460 {
   1461 
   1462 	MPT_2_HOST32(fp1, Flags);
   1463 	MPT_2_HOST32(fp1, NoSEEPROMWWNN.Low);
   1464 	MPT_2_HOST32(fp1, NoSEEPROMWWNN.High);
   1465 	MPT_2_HOST32(fp1, NoSEEPROMWWPN.Low);
   1466 	MPT_2_HOST32(fp1, NoSEEPROMWWPN.High);
   1467 }
   1468 
   1469 void
   1470 host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
   1471 {
   1472 
   1473 	HOST_2_MPT32(fp1, Flags);
   1474 	HOST_2_MPT32(fp1, NoSEEPROMWWNN.Low);
   1475 	HOST_2_MPT32(fp1, NoSEEPROMWWNN.High);
   1476 	HOST_2_MPT32(fp1, NoSEEPROMWWPN.Low);
   1477 	HOST_2_MPT32(fp1, NoSEEPROMWWPN.High);
   1478 }
   1479 
   1480 void
   1481 mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 *volp)
   1482 {
   1483 	int i;
   1484 
   1485 	MPT_2_HOST16(volp, VolumeStatus.Reserved);
   1486 	MPT_2_HOST16(volp, VolumeSettings.Settings);
   1487 	MPT_2_HOST32(volp, MaxLBA);
   1488 #if 0
   1489 	MPT_2_HOST32(volp, MaxLBAHigh);
   1490 #endif
   1491 	MPT_2_HOST32(volp, StripeSize);
   1492 	MPT_2_HOST32(volp, Reserved2);
   1493 	MPT_2_HOST32(volp, Reserved3);
   1494 	for (i = 0; i < MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX; i++) {
   1495 		MPT_2_HOST16(volp, PhysDisk[i].Reserved);
   1496 	}
   1497 }
   1498 
   1499 void
   1500 mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *rpd0)
   1501 {
   1502 
   1503 	MPT_2_HOST32(rpd0, Reserved1);
   1504 	MPT_2_HOST16(rpd0, PhysDiskStatus.Reserved);
   1505 	MPT_2_HOST32(rpd0, MaxLBA);
   1506 	MPT_2_HOST16(rpd0, ErrorData.Reserved);
   1507 	MPT_2_HOST16(rpd0, ErrorData.ErrorCount);
   1508 	MPT_2_HOST16(rpd0, ErrorData.SmartCount);
   1509 }
   1510 
   1511 #endif
   1512