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