Home | History | Annotate | Line # | Download | only in ic
      1 /*	$NetBSD: mpt.c,v 1.21 2019/09/23 16:19:33 skrll 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.21 2019/09/23 16:19:33 skrll 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 (%#" PRIxBUSADDR "):",
    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 %#02zx",
    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 int
    569 mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
    570     int PageAddress, fCONFIG_PAGE_HEADER *rslt)
    571 {
    572 	int count;
    573 	request_t *req;
    574 	MSG_CONFIG *cfgp;
    575 	MSG_CONFIG_REPLY *reply;
    576 
    577 	req = mpt_get_request(mpt);
    578 
    579 	cfgp = req->req_vbuf;
    580 	memset(cfgp, 0, sizeof *cfgp);
    581 
    582 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
    583 	cfgp->Function = MPI_FUNCTION_CONFIG;
    584 	cfgp->Header.PageNumber = (U8) PageNumber;
    585 	cfgp->Header.PageType = (U8) PageType;
    586 	cfgp->PageAddress = htole32(PageAddress);
    587 	MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
    588 	    (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    589 	    MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
    590 	cfgp->MsgContext = htole32(req->index | 0x80000000);
    591 
    592 	mpt_check_doorbell(mpt);
    593 	mpt_send_cmd(mpt, req);
    594 	count = 0;
    595 	do {
    596 		DELAY(500);
    597 		mpt_intr(mpt);
    598 		if (++count == 1000) {
    599 			mpt_prt(mpt, "read_cfg_header timed out");
    600 			return (-1);
    601 		}
    602 	} while (req->debug == REQ_ON_CHIP);
    603 
    604 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    605         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    606 		mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
    607 		    reply->IOCStatus);
    608 		mpt_free_reply(mpt, (req->sequence << 1));
    609 		return (-1);
    610 	}
    611 	memcpy(rslt, &reply->Header, sizeof (fCONFIG_PAGE_HEADER));
    612 	mpt_free_reply(mpt, (req->sequence << 1));
    613 	mpt_free_request(mpt, req);
    614 	return (0);
    615 }
    616 
    617 #define	CFG_DATA_OFF	128
    618 
    619 int
    620 mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
    621 {
    622 	int count;
    623 	request_t *req;
    624 	SGE_SIMPLE32 *se;
    625 	MSG_CONFIG *cfgp;
    626 	size_t amt;
    627 	MSG_CONFIG_REPLY *reply;
    628 
    629 	req = mpt_get_request(mpt);
    630 
    631 	cfgp = req->req_vbuf;
    632 	memset(cfgp, 0, MPT_REQUEST_AREA);
    633 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
    634 	cfgp->Function = MPI_FUNCTION_CONFIG;
    635 	cfgp->Header = *hdr;
    636  	amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
    637 	cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
    638 	cfgp->PageAddress = htole32(PageAddress);
    639 	se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
    640 	se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
    641 	MPI_pSGE_SET_LENGTH(se, amt);
    642 	MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
    643 	    MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    644 	    MPI_SGE_FLAGS_END_OF_LIST));
    645 	se->FlagsLength = htole32(se->FlagsLength);
    646 
    647 	cfgp->MsgContext = htole32(req->index | 0x80000000);
    648 
    649 	mpt_check_doorbell(mpt);
    650 	mpt_send_cmd(mpt, req);
    651 	count = 0;
    652 	do {
    653 		DELAY(500);
    654 		mpt_intr(mpt);
    655 		if (++count == 1000) {
    656 			mpt_prt(mpt, "read_cfg_page timed out");
    657 			return (-1);
    658 		}
    659 	} while (req->debug == REQ_ON_CHIP);
    660 
    661 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    662         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    663 		mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
    664 		    reply->IOCStatus);
    665 		mpt_free_reply(mpt, (req->sequence << 1));
    666 		return (-1);
    667 	}
    668 	mpt_free_reply(mpt, (req->sequence << 1));
    669 #if 0 /* XXXJRT */
    670 	bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
    671 	    BUS_DMASYNC_POSTREAD);
    672 #endif
    673 	if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    674 	    cfgp->Header.PageNumber == 0) {
    675 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
    676 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    677 	    cfgp->Header.PageNumber == 1) {
    678 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
    679 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    680 	    cfgp->Header.PageNumber == 2) {
    681 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
    682 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    683 	    cfgp->Header.PageNumber == 0) {
    684 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
    685 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    686 	    cfgp->Header.PageNumber == 1) {
    687 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
    688 	}
    689 	memcpy(hdr, (char *)req->req_vbuf + CFG_DATA_OFF, amt);
    690 	mpt_free_request(mpt, req);
    691 	return (0);
    692 }
    693 
    694 int
    695 mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
    696 {
    697 	int count, hdr_attr;
    698 	request_t *req;
    699 	SGE_SIMPLE32 *se;
    700 	MSG_CONFIG *cfgp;
    701 	size_t amt;
    702 	MSG_CONFIG_REPLY *reply;
    703 
    704 	req = mpt_get_request(mpt);
    705 
    706 	cfgp = req->req_vbuf;
    707 	memset(cfgp, 0, sizeof *cfgp);
    708 
    709 	hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
    710 	if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
    711 	    hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
    712 		mpt_prt(mpt, "page type 0x%x not changeable",
    713 		    hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
    714 		return (-1);
    715 	}
    716 	hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
    717 
    718 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
    719 	cfgp->Function = MPI_FUNCTION_CONFIG;
    720 	cfgp->Header = *hdr;
    721  	amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
    722 	cfgp->PageAddress = htole32(PageAddress);
    723 
    724 	se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
    725 	se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
    726 	MPI_pSGE_SET_LENGTH(se, amt);
    727 	MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
    728 	    MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    729 	    MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
    730 	se->FlagsLength = htole32(se->FlagsLength);
    731 
    732 	cfgp->MsgContext = htole32(req->index | 0x80000000);
    733 
    734 	if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    735 	    cfgp->Header.PageNumber == 0) {
    736 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
    737 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    738 	    cfgp->Header.PageNumber == 1) {
    739 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
    740 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    741 	    cfgp->Header.PageNumber == 2) {
    742 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
    743 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    744 	    cfgp->Header.PageNumber == 0) {
    745 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
    746 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    747 	    cfgp->Header.PageNumber == 1) {
    748 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
    749 	}
    750 	memcpy((char *)req->req_vbuf + CFG_DATA_OFF, hdr, amt);
    751 	/* Restore stripped out attributes */
    752 	hdr->PageType |= hdr_attr;
    753 
    754 	mpt_check_doorbell(mpt);
    755 	mpt_send_cmd(mpt, req);
    756 	count = 0;
    757 	do {
    758 		DELAY(500);
    759 		mpt_intr(mpt);
    760 		if (++count == 1000) {
    761 			hdr->PageType |= hdr_attr;
    762 			mpt_prt(mpt, "mpt_write_cfg_page timed out");
    763 			return (-1);
    764 		}
    765 	} while (req->debug == REQ_ON_CHIP);
    766 
    767 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    768         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    769 		mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
    770 		    le16toh(reply->IOCStatus));
    771 		mpt_free_reply(mpt, (req->sequence << 1));
    772 		return (-1);
    773 	}
    774 	mpt_free_reply(mpt, (req->sequence << 1));
    775 
    776 	mpt_free_request(mpt, req);
    777 	return (0);
    778 }
    779 
    780 /*
    781  * Read SCSI configuration information
    782  */
    783 static int
    784 mpt_read_config_info_spi(mpt_softc_t *mpt)
    785 {
    786 	int rv, i;
    787 
    788 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
    789 	    0, &mpt->mpt_port_page0.Header);
    790 	if (rv) {
    791 		return (-1);
    792 	}
    793 	if (mpt->verbose > 1) {
    794 		mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
    795 		    mpt->mpt_port_page0.Header.PageVersion,
    796 		    mpt->mpt_port_page0.Header.PageLength,
    797 		    mpt->mpt_port_page0.Header.PageNumber,
    798 		    mpt->mpt_port_page0.Header.PageType);
    799 	}
    800 
    801 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
    802 	    0, &mpt->mpt_port_page1.Header);
    803 	if (rv) {
    804 		return (-1);
    805 	}
    806 	if (mpt->verbose > 1) {
    807 		mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
    808 		    mpt->mpt_port_page1.Header.PageVersion,
    809 		    mpt->mpt_port_page1.Header.PageLength,
    810 		    mpt->mpt_port_page1.Header.PageNumber,
    811 		    mpt->mpt_port_page1.Header.PageType);
    812 	}
    813 
    814 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
    815 	    0, &mpt->mpt_port_page2.Header);
    816 	if (rv) {
    817 		return (-1);
    818 	}
    819 
    820 	if (mpt->verbose > 1) {
    821 		mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
    822 		    mpt->mpt_port_page1.Header.PageVersion,
    823 		    mpt->mpt_port_page1.Header.PageLength,
    824 		    mpt->mpt_port_page1.Header.PageNumber,
    825 		    mpt->mpt_port_page1.Header.PageType);
    826 	}
    827 
    828 	for (i = 0; i < 16; i++) {
    829 		rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
    830 		    0, i, &mpt->mpt_dev_page0[i].Header);
    831 		if (rv) {
    832 			return (-1);
    833 		}
    834 		if (mpt->verbose > 1) {
    835 			mpt_prt(mpt,
    836 			    "SPI Target %d Device Page 0 Header: %x %x %x %x",
    837 			    i, mpt->mpt_dev_page0[i].Header.PageVersion,
    838 			    mpt->mpt_dev_page0[i].Header.PageLength,
    839 			    mpt->mpt_dev_page0[i].Header.PageNumber,
    840 			    mpt->mpt_dev_page0[i].Header.PageType);
    841 		}
    842 
    843 		rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
    844 		    1, i, &mpt->mpt_dev_page1[i].Header);
    845 		if (rv) {
    846 			return (-1);
    847 		}
    848 		if (mpt->verbose > 1) {
    849 			mpt_prt(mpt,
    850 			    "SPI Target %d Device Page 1 Header: %x %x %x %x",
    851 			    i, mpt->mpt_dev_page1[i].Header.PageVersion,
    852 			    mpt->mpt_dev_page1[i].Header.PageLength,
    853 			    mpt->mpt_dev_page1[i].Header.PageNumber,
    854 			    mpt->mpt_dev_page1[i].Header.PageType);
    855 		}
    856 	}
    857 
    858 	/*
    859 	 * At this point, we don't *have* to fail. As long as we have
    860 	 * valid config header information, we can (barely) lurch
    861 	 * along.
    862 	 */
    863 
    864 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
    865 	mpt2host_config_page_scsi_port_0(&mpt->mpt_port_page0);
    866 	if (rv) {
    867 		mpt_prt(mpt, "failed to read SPI Port Page 0");
    868 	} else if (mpt->verbose > 1) {
    869 		mpt_prt(mpt,
    870 		    "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
    871 		    mpt->mpt_port_page0.Capabilities,
    872 		    mpt->mpt_port_page0.PhysicalInterface);
    873 	}
    874 
    875 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
    876 	mpt2host_config_page_scsi_port_1(&mpt->mpt_port_page1);
    877 	if (rv) {
    878 		mpt_prt(mpt, "failed to read SPI Port Page 1");
    879 	} else if (mpt->verbose > 1) {
    880 		mpt_prt(mpt,
    881 		    "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
    882 		    mpt->mpt_port_page1.Configuration,
    883 		    mpt->mpt_port_page1.OnBusTimerValue);
    884 	}
    885 
    886 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
    887 	mpt2host_config_page_scsi_port_2(&mpt->mpt_port_page2);
    888 	if (rv) {
    889 		mpt_prt(mpt, "failed to read SPI Port Page 2");
    890 	} else if (mpt->verbose > 1) {
    891 		mpt_prt(mpt,
    892 		    "SPI Port Page 2: Flags %x Settings %x",
    893 		    mpt->mpt_port_page2.PortFlags,
    894 		    mpt->mpt_port_page2.PortSettings);
    895 		for (i = 0; i < 1; i++) {
    896 			mpt_prt(mpt,
    897 		  	    "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
    898 			    i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
    899 			    mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
    900 			    mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
    901 		}
    902 	}
    903 
    904 	for (i = 0; i < 16; i++) {
    905 		rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
    906 		mpt2host_config_page_scsi_device_0(&mpt->mpt_dev_page0[i]);
    907 		if (rv) {
    908 			mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
    909 			continue;
    910 		}
    911 		if (mpt->verbose > 1) {
    912 			mpt_prt(mpt,
    913 			    "SPI Tgt %d Page 0: NParms %x Information %x",
    914 			    i, mpt->mpt_dev_page0[i].NegotiatedParameters,
    915 			    mpt->mpt_dev_page0[i].Information);
    916 		}
    917 		rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
    918 		mpt2host_config_page_scsi_device_1(&mpt->mpt_dev_page1[i]);
    919 		if (rv) {
    920 			mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
    921 			continue;
    922 		}
    923 		if (mpt->verbose > 1) {
    924 			mpt_prt(mpt,
    925 			    "SPI Tgt %d Page 1: RParms %x Configuration %x",
    926 			    i, mpt->mpt_dev_page1[i].RequestedParameters,
    927 			    mpt->mpt_dev_page1[i].Configuration);
    928 		}
    929 	}
    930 	return (0);
    931 }
    932 
    933 /*
    934  * Validate SPI configuration information.
    935  *
    936  * In particular, validate SPI Port Page 1.
    937  */
    938 static int
    939 mpt_set_initial_config_spi(mpt_softc_t *mpt)
    940 {
    941 	int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
    942 
    943 	mpt->mpt_disc_enable = 0xffff;
    944 	mpt->mpt_tag_enable = 0;
    945 
    946 	if (mpt->mpt_port_page1.Configuration != pp1val) {
    947 		fCONFIG_PAGE_SCSI_PORT_1 tmp;
    948 
    949 		mpt_prt(mpt,
    950 		    "SPI Port Page 1 Config value bad (%x)- should be %x",
    951 		    mpt->mpt_port_page1.Configuration, pp1val);
    952 		tmp = mpt->mpt_port_page1;
    953 		tmp.Configuration = pp1val;
    954 		host2mpt_config_page_scsi_port_1(&tmp);
    955 		if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
    956 			return (-1);
    957 		}
    958 		if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
    959 			return (-1);
    960 		}
    961 		mpt2host_config_page_scsi_port_1(&tmp);
    962 		if (tmp.Configuration != pp1val) {
    963 			mpt_prt(mpt,
    964 			    "failed to reset SPI Port Page 1 Config value");
    965 			return (-1);
    966 		}
    967 		mpt->mpt_port_page1 = tmp;
    968 	}
    969 
    970 	i = 0;
    971 	for (i = 0; i < 16; i++) {
    972 		fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
    973 
    974 		tmp = mpt->mpt_dev_page1[i];
    975 		tmp.RequestedParameters = 0;
    976 		tmp.Configuration = 0;
    977 		if (mpt->verbose > 1) {
    978 			mpt_prt(mpt,
    979 			    "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
    980 			    i, tmp.RequestedParameters, tmp.Configuration);
    981 		}
    982 		host2mpt_config_page_scsi_device_1(&tmp);
    983 		if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
    984 			return (-1);
    985 		}
    986 		if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
    987 			return (-1);
    988 		}
    989 		mpt2host_config_page_scsi_device_1(&tmp);
    990 		mpt->mpt_dev_page1[i] = tmp;
    991 		if (mpt->verbose > 1) {
    992 			mpt_prt(mpt,
    993 		 	    "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
    994 			    mpt->mpt_dev_page1[i].RequestedParameters,
    995 			    mpt->mpt_dev_page1[i].Configuration);
    996 		}
    997 	}
    998 	return (0);
    999 }
   1000 
   1001 /*
   1002  * Enable IOC port
   1003  */
   1004 static int
   1005 mpt_send_port_enable(mpt_softc_t *mpt, int port)
   1006 {
   1007 	int count;
   1008 	request_t *req;
   1009 	MSG_PORT_ENABLE *enable_req;
   1010 
   1011 	req = mpt_get_request(mpt);
   1012 
   1013 	enable_req = req->req_vbuf;
   1014 	memset(enable_req, 0, sizeof *enable_req);
   1015 
   1016 	enable_req->Function   = MPI_FUNCTION_PORT_ENABLE;
   1017 	enable_req->MsgContext = htole32(req->index | 0x80000000);
   1018 	enable_req->PortNumber = port;
   1019 
   1020 	mpt_check_doorbell(mpt);
   1021 	if (mpt->verbose > 1) {
   1022 		mpt_prt(mpt, "enabling port %d", port);
   1023 	}
   1024 	mpt_send_cmd(mpt, req);
   1025 
   1026 	count = 0;
   1027 	do {
   1028 		DELAY(500);
   1029 		mpt_intr(mpt);
   1030 		if (++count == 100000) {
   1031 			mpt_prt(mpt, "port enable timed out");
   1032 			return (-1);
   1033 		}
   1034 	} while (req->debug == REQ_ON_CHIP);
   1035 	mpt_free_request(mpt, req);
   1036 	return (0);
   1037 }
   1038 
   1039 /*
   1040  * Enable/Disable asynchronous event reporting.
   1041  *
   1042  * NB: this is the first command we send via shared memory
   1043  * instead of the handshake register.
   1044  */
   1045 static int
   1046 mpt_send_event_request(mpt_softc_t *mpt, int onoff)
   1047 {
   1048 	request_t *req;
   1049 	MSG_EVENT_NOTIFY *enable_req;
   1050 
   1051 	req = mpt_get_request(mpt);
   1052 
   1053 	enable_req = req->req_vbuf;
   1054 	memset(enable_req, 0, sizeof *enable_req);
   1055 
   1056 	enable_req->Function   = MPI_FUNCTION_EVENT_NOTIFICATION;
   1057 	enable_req->MsgContext = htole32(req->index | 0x80000000);
   1058 	enable_req->Switch     = onoff;
   1059 
   1060 	mpt_check_doorbell(mpt);
   1061 	if (mpt->verbose > 1) {
   1062 		mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
   1063 	}
   1064 	mpt_send_cmd(mpt, req);
   1065 
   1066 	return (0);
   1067 }
   1068 
   1069 /*
   1070  * Un-mask the interrupts on the chip.
   1071  */
   1072 void
   1073 mpt_enable_ints(mpt_softc_t *mpt)
   1074 {
   1075 	/* Unmask every thing except door bell int */
   1076 	mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
   1077 }
   1078 
   1079 /*
   1080  * Mask the interrupts on the chip.
   1081  */
   1082 void
   1083 mpt_disable_ints(mpt_softc_t *mpt)
   1084 {
   1085 	/* Mask all interrupts */
   1086 	mpt_write(mpt, MPT_OFFSET_INTR_MASK,
   1087 	    MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
   1088 }
   1089 
   1090 /* (Re)Initialize the chip for use */
   1091 int
   1092 mpt_hw_init(mpt_softc_t *mpt)
   1093 {
   1094 	u_int32_t	db;
   1095 	int		try;
   1096 
   1097 	/*
   1098 	 * Start by making sure we're not at FAULT or RESET state
   1099 	 */
   1100 	for (try = 0; try < MPT_MAX_TRYS; try++) {
   1101 
   1102 		db = mpt_rd_db(mpt);
   1103 
   1104 		switch (MPT_STATE(db)) {
   1105 		case MPT_DB_STATE_READY:
   1106 			return (0);
   1107 
   1108 		default:
   1109 			/* if peer has already reset us, don't do it again! */
   1110 			if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER)
   1111 				return (0);
   1112 			/*FALLTHRU*/
   1113 		case MPT_DB_STATE_RESET:
   1114 		case MPT_DB_STATE_FAULT:
   1115 			if (mpt_reset(mpt) != MPT_OK) {
   1116 				DELAY(10000);
   1117 				continue;
   1118 			}
   1119 			break;
   1120 		}
   1121 	}
   1122 	return (EIO);
   1123 }
   1124 
   1125 int
   1126 mpt_init(mpt_softc_t *mpt, u_int32_t who)
   1127 {
   1128         int try;
   1129         MSG_IOC_FACTS_REPLY facts;
   1130         MSG_PORT_FACTS_REPLY pfp;
   1131         prop_dictionary_t dict;
   1132         uint32_t ini_id;
   1133         uint32_t pptr;
   1134         int val;
   1135 
   1136 	/* Put all request buffers (back) on the free list */
   1137         SLIST_INIT(&mpt->request_free_list);
   1138 	for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
   1139 		mpt_free_request(mpt, &mpt->request_pool[val]);
   1140 	}
   1141 
   1142 	if (mpt->verbose > 1) {
   1143 		mpt_prt(mpt, "doorbell req = %s",
   1144 		    mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
   1145 	}
   1146 
   1147 	/*
   1148 	 * Start by making sure we're not at FAULT or RESET state
   1149 	 */
   1150 	if (mpt_hw_init(mpt) != 0)
   1151 		return (EIO);
   1152 
   1153 	dict = device_properties(mpt->sc_dev);
   1154 
   1155 	for (try = 0; try < MPT_MAX_TRYS; try++) {
   1156 		/*
   1157 		 * No need to reset if the IOC is already in the READY state.
   1158 		 */
   1159 
   1160 		if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
   1161 			mpt_prt(mpt, "mpt_get_iocfacts failed");
   1162 			continue;
   1163 		}
   1164 		mpt2host_iocfacts_reply(&facts);
   1165 
   1166 		if (mpt->verbose > 1) {
   1167 			mpt_prt(mpt,
   1168 			    "IOCFACTS: GlobalCredits=%d BlockSize=%u "
   1169 			    "Request Frame Size %u", facts.GlobalCredits,
   1170 			    facts.BlockSize, facts.RequestFrameSize);
   1171 		}
   1172 		mpt->mpt_max_devices = facts.MaxDevices;
   1173 		mpt->mpt_global_credits = facts.GlobalCredits;
   1174 		mpt->request_frame_size = facts.RequestFrameSize;
   1175 
   1176 		if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
   1177 			mpt_prt(mpt, "mpt_get_portfacts failed");
   1178 			continue;
   1179 		}
   1180 		mpt2host_portfacts_reply(&pfp);
   1181 
   1182 		if (mpt->verbose > 1) {
   1183 			mpt_prt(mpt,
   1184 			    "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d",
   1185 			    pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
   1186 			    pfp.MaxDevices);
   1187 		}
   1188 
   1189 		if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
   1190 			mpt_prt(mpt, "initiator role unsupported");
   1191 			return (ENXIO);
   1192 		}
   1193 
   1194 		switch (pfp.PortType) {
   1195 		case MPI_PORTFACTS_PORTTYPE_FC:
   1196 			mpt->is_fc = 1;
   1197 			mpt->mpt_max_devices = 255;
   1198 			break;
   1199 		case MPI_PORTFACTS_PORTTYPE_SCSI:
   1200 			mpt->is_scsi = 1;
   1201 			/* some SPI controllers (VMWare, Sun) lie */
   1202 			mpt->mpt_max_devices = 16;
   1203 			break;
   1204 		case MPI_PORTFACTS_PORTTYPE_SAS:
   1205 			mpt->is_sas = 1;
   1206 			break;
   1207 		default:
   1208 			mpt_prt(mpt, "Unsupported Port Type (%x)",
   1209 			    pfp.PortType);
   1210 			return (ENXIO);
   1211 		}
   1212 
   1213 		if (!mpt->is_sas && !mpt->is_fc &&
   1214 		    prop_dictionary_get_uint32(dict, "scsi-initiator-id", &ini_id))
   1215 			mpt->mpt_ini_id = ini_id;
   1216 		else
   1217 			mpt->mpt_ini_id = pfp.PortSCSIID;
   1218 
   1219 		if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
   1220 			mpt_prt(mpt, "mpt_send_ioc_init failed");
   1221 			continue;
   1222 		}
   1223 
   1224 		if (mpt->verbose > 1) {
   1225 			mpt_prt(mpt, "mpt_send_ioc_init ok");
   1226 		}
   1227 
   1228 		if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
   1229 			mpt_prt(mpt, "IOC failed to go to run state");
   1230 			continue;
   1231 		}
   1232 		if (mpt->verbose > 1) {
   1233 			mpt_prt(mpt, "IOC now at RUNSTATE");
   1234 		}
   1235 
   1236 		/*
   1237 		 * Give it reply buffers
   1238 		 *
   1239 		 * Do *not* except global credits.
   1240 		 */
   1241 		for (val = 0, pptr = mpt->reply_phys;
   1242 		    (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
   1243 		     pptr += MPT_REPLY_SIZE) {
   1244 			mpt_free_reply(mpt, pptr);
   1245 			if (++val == mpt->mpt_global_credits - 1)
   1246 				break;
   1247 		}
   1248 
   1249 		/*
   1250 		 * Enable asynchronous event reporting
   1251 		 */
   1252 		mpt_send_event_request(mpt, 1);
   1253 
   1254 
   1255 		/*
   1256 		 * Read set up initial configuration information
   1257 		 * (SPI only for now)
   1258 		 */
   1259 
   1260 		if (mpt->is_scsi) {
   1261 			if (mpt_read_config_info_spi(mpt)) {
   1262 				return (EIO);
   1263 			}
   1264 			if (mpt_set_initial_config_spi(mpt)) {
   1265 				return (EIO);
   1266 			}
   1267 		}
   1268 
   1269 		/*
   1270 		 * Now enable the port
   1271 		 */
   1272 		if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
   1273 			mpt_prt(mpt, "failed to enable port 0");
   1274 			continue;
   1275 		}
   1276 
   1277 		if (mpt->verbose > 1) {
   1278 			mpt_prt(mpt, "enabled port 0");
   1279 		}
   1280 
   1281 		/* Everything worked */
   1282 		break;
   1283 	}
   1284 
   1285 	if (try >= MPT_MAX_TRYS) {
   1286 		mpt_prt(mpt, "failed to initialize IOC");
   1287 		return (EIO);
   1288 	}
   1289 
   1290 	if (mpt->verbose > 1) {
   1291 		mpt_prt(mpt, "enabling interrupts");
   1292 	}
   1293 
   1294 	mpt_enable_ints(mpt);
   1295 	return (0);
   1296 }
   1297 
   1298 /*
   1299  * Endian Conversion Functions- only used on Big Endian machines
   1300  */
   1301 #if	_BYTE_ORDER == _BIG_ENDIAN
   1302 void
   1303 mpt2host_sge_simple_union(SGE_SIMPLE_UNION *sge)
   1304 {
   1305 
   1306 	MPT_2_HOST32(sge, FlagsLength);
   1307 	MPT_2_HOST32(sge, _u.Address64.Low);
   1308 	MPT_2_HOST32(sge, _u.Address64.High);
   1309 }
   1310 
   1311 void
   1312 mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *rp)
   1313 {
   1314 
   1315 	MPT_2_HOST16(rp, MsgVersion);
   1316 #if 0
   1317 	MPT_2_HOST16(rp, HeaderVersion);
   1318 #endif
   1319 	MPT_2_HOST32(rp, MsgContext);
   1320 	MPT_2_HOST16(rp, IOCExceptions);
   1321 	MPT_2_HOST16(rp, IOCStatus);
   1322 	MPT_2_HOST32(rp, IOCLogInfo);
   1323 	MPT_2_HOST16(rp, ReplyQueueDepth);
   1324 	MPT_2_HOST16(rp, RequestFrameSize);
   1325 	MPT_2_HOST16(rp, Reserved_0101_FWVersion);
   1326 	MPT_2_HOST16(rp, ProductID);
   1327 	MPT_2_HOST32(rp, CurrentHostMfaHighAddr);
   1328 	MPT_2_HOST16(rp, GlobalCredits);
   1329 	MPT_2_HOST32(rp, CurrentSenseBufferHighAddr);
   1330 	MPT_2_HOST16(rp, CurReplyFrameSize);
   1331 	MPT_2_HOST32(rp, FWImageSize);
   1332 #if 0
   1333 	MPT_2_HOST32(rp, IOCCapabilities);
   1334 #endif
   1335 	MPT_2_HOST32(rp, FWVersion.Word);
   1336 #if 0
   1337 	MPT_2_HOST16(rp, HighPriorityQueueDepth);
   1338 	MPT_2_HOST16(rp, Reserved2);
   1339 	mpt2host_sge_simple_union(&rp->HostPageBufferSGE);
   1340 	MPT_2_HOST32(rp, ReplyFifoHostSignalingAddr);
   1341 #endif
   1342 }
   1343 
   1344 void
   1345 mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *pfp)
   1346 {
   1347 
   1348 	MPT_2_HOST16(pfp, Reserved);
   1349 	MPT_2_HOST16(pfp, Reserved1);
   1350 	MPT_2_HOST32(pfp, MsgContext);
   1351 	MPT_2_HOST16(pfp, Reserved2);
   1352 	MPT_2_HOST16(pfp, IOCStatus);
   1353 	MPT_2_HOST32(pfp, IOCLogInfo);
   1354 	MPT_2_HOST16(pfp, MaxDevices);
   1355 	MPT_2_HOST16(pfp, PortSCSIID);
   1356 	MPT_2_HOST16(pfp, ProtocolFlags);
   1357 	MPT_2_HOST16(pfp, MaxPostedCmdBuffers);
   1358 	MPT_2_HOST16(pfp, MaxPersistentIDs);
   1359 	MPT_2_HOST16(pfp, MaxLanBuckets);
   1360 	MPT_2_HOST16(pfp, Reserved4);
   1361 	MPT_2_HOST32(pfp, Reserved5);
   1362 }
   1363 
   1364 void
   1365 mpt2host_config_page_scsi_port_0(fCONFIG_PAGE_SCSI_PORT_0 *sp0)
   1366 {
   1367 
   1368 	MPT_2_HOST32(sp0, Capabilities);
   1369 	MPT_2_HOST32(sp0, PhysicalInterface);
   1370 }
   1371 
   1372 void
   1373 mpt2host_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
   1374 {
   1375 
   1376 	MPT_2_HOST32(sp1, Configuration);
   1377 	MPT_2_HOST32(sp1, OnBusTimerValue);
   1378 #if 0
   1379 	MPT_2_HOST16(sp1, IDConfig);
   1380 #endif
   1381 }
   1382 
   1383 void
   1384 host2mpt_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
   1385 {
   1386 
   1387 	HOST_2_MPT32(sp1, Configuration);
   1388 	HOST_2_MPT32(sp1, OnBusTimerValue);
   1389 #if 0
   1390 	HOST_2_MPT16(sp1, IDConfig);
   1391 #endif
   1392 }
   1393 
   1394 void
   1395 mpt2host_config_page_scsi_port_2(fCONFIG_PAGE_SCSI_PORT_2 *sp2)
   1396 {
   1397 	int i;
   1398 
   1399 	MPT_2_HOST32(sp2, PortFlags);
   1400 	MPT_2_HOST32(sp2, PortSettings);
   1401 	for (i = 0; i < sizeof(sp2->DeviceSettings) /
   1402 	    sizeof(*sp2->DeviceSettings); i++) {
   1403 		MPT_2_HOST16(sp2, DeviceSettings[i].DeviceFlags);
   1404 	}
   1405 }
   1406 
   1407 void
   1408 mpt2host_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
   1409 {
   1410 
   1411 	MPT_2_HOST32(sd0, NegotiatedParameters);
   1412 	MPT_2_HOST32(sd0, Information);
   1413 }
   1414 
   1415 void
   1416 host2mpt_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
   1417 {
   1418 
   1419 	HOST_2_MPT32(sd0, NegotiatedParameters);
   1420 	HOST_2_MPT32(sd0, Information);
   1421 }
   1422 
   1423 void
   1424 mpt2host_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
   1425 {
   1426 
   1427 	MPT_2_HOST32(sd1, RequestedParameters);
   1428 	MPT_2_HOST32(sd1, Reserved);
   1429 	MPT_2_HOST32(sd1, Configuration);
   1430 }
   1431 
   1432 void
   1433 host2mpt_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
   1434 {
   1435 
   1436 	HOST_2_MPT32(sd1, RequestedParameters);
   1437 	HOST_2_MPT32(sd1, Reserved);
   1438 	HOST_2_MPT32(sd1, Configuration);
   1439 }
   1440 
   1441 void
   1442 mpt2host_config_page_fc_port_0(fCONFIG_PAGE_FC_PORT_0 *fp0)
   1443 {
   1444 
   1445 	MPT_2_HOST32(fp0, Flags);
   1446 	MPT_2_HOST32(fp0, PortIdentifier);
   1447 	MPT_2_HOST32(fp0, WWNN.Low);
   1448 	MPT_2_HOST32(fp0, WWNN.High);
   1449 	MPT_2_HOST32(fp0, WWPN.Low);
   1450 	MPT_2_HOST32(fp0, WWPN.High);
   1451 	MPT_2_HOST32(fp0, SupportedServiceClass);
   1452 	MPT_2_HOST32(fp0, SupportedSpeeds);
   1453 	MPT_2_HOST32(fp0, CurrentSpeed);
   1454 	MPT_2_HOST32(fp0, MaxFrameSize);
   1455 	MPT_2_HOST32(fp0, FabricWWNN.Low);
   1456 	MPT_2_HOST32(fp0, FabricWWNN.High);
   1457 	MPT_2_HOST32(fp0, FabricWWPN.Low);
   1458 	MPT_2_HOST32(fp0, FabricWWPN.High);
   1459 	MPT_2_HOST32(fp0, DiscoveredPortsCount);
   1460 	MPT_2_HOST32(fp0, MaxInitiators);
   1461 }
   1462 
   1463 void
   1464 mpt2host_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
   1465 {
   1466 
   1467 	MPT_2_HOST32(fp1, Flags);
   1468 	MPT_2_HOST32(fp1, NoSEEPROMWWNN.Low);
   1469 	MPT_2_HOST32(fp1, NoSEEPROMWWNN.High);
   1470 	MPT_2_HOST32(fp1, NoSEEPROMWWPN.Low);
   1471 	MPT_2_HOST32(fp1, NoSEEPROMWWPN.High);
   1472 }
   1473 
   1474 void
   1475 host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
   1476 {
   1477 
   1478 	HOST_2_MPT32(fp1, Flags);
   1479 	HOST_2_MPT32(fp1, NoSEEPROMWWNN.Low);
   1480 	HOST_2_MPT32(fp1, NoSEEPROMWWNN.High);
   1481 	HOST_2_MPT32(fp1, NoSEEPROMWWPN.Low);
   1482 	HOST_2_MPT32(fp1, NoSEEPROMWWPN.High);
   1483 }
   1484 
   1485 void
   1486 mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 *volp)
   1487 {
   1488 	int i;
   1489 
   1490 	MPT_2_HOST16(volp, VolumeStatus.Reserved);
   1491 	MPT_2_HOST16(volp, VolumeSettings.Settings);
   1492 	MPT_2_HOST32(volp, MaxLBA);
   1493 #if 0
   1494 	MPT_2_HOST32(volp, MaxLBAHigh);
   1495 #endif
   1496 	MPT_2_HOST32(volp, StripeSize);
   1497 	MPT_2_HOST32(volp, Reserved2);
   1498 	MPT_2_HOST32(volp, Reserved3);
   1499 	for (i = 0; i < MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX; i++) {
   1500 		MPT_2_HOST16(volp, PhysDisk[i].Reserved);
   1501 	}
   1502 }
   1503 
   1504 void
   1505 mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *rpd0)
   1506 {
   1507 
   1508 	MPT_2_HOST32(rpd0, Reserved1);
   1509 	MPT_2_HOST16(rpd0, PhysDiskStatus.Reserved);
   1510 	MPT_2_HOST32(rpd0, MaxLBA);
   1511 	MPT_2_HOST16(rpd0, ErrorData.Reserved);
   1512 	MPT_2_HOST16(rpd0, ErrorData.ErrorCount);
   1513 	MPT_2_HOST16(rpd0, ErrorData.SmartCount);
   1514 }
   1515 
   1516 void
   1517 mpt2host_config_page_ioc_2(fCONFIG_PAGE_IOC_2 *ioc2)
   1518 {
   1519 	MPT_2_HOST32(ioc2, CapabilitiesFlags);
   1520 }
   1521 
   1522 #endif
   1523