Home | History | Annotate | Line # | Download | only in ic
mpt.c revision 1.21
      1  1.21     skrll /*	$NetBSD: mpt.c,v 1.21 2019/09/23 16:19:33 skrll 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.14       chs /*-
     31  1.14       chs  * Copyright (c) 2002, 2006 by Matthew Jacob
     32  1.14       chs  * All rights reserved.
     33  1.14       chs  *
     34  1.14       chs  * Redistribution and use in source and binary forms, with or without
     35  1.14       chs  * modification, are permitted provided that the following conditions are
     36  1.14       chs  * met:
     37  1.14       chs  * 1. Redistributions of source code must retain the above copyright
     38  1.14       chs  *    notice, this list of conditions and the following disclaimer.
     39  1.14       chs  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     40  1.14       chs  *    substantially similar to the "NO WARRANTY" disclaimer below
     41  1.14       chs  *    ("Disclaimer") and any redistribution must be conditioned upon including
     42  1.14       chs  *    a substantially similar Disclaimer requirement for further binary
     43  1.14       chs  *    redistribution.
     44  1.14       chs  * 3. Neither the names of the above listed copyright holders nor the names
     45  1.14       chs  *    of any contributors may be used to endorse or promote products derived
     46  1.14       chs  *    from this software without specific prior written permission.
     47  1.14       chs  *
     48  1.14       chs  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     49  1.14       chs  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     50  1.14       chs  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     51  1.14       chs  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     52  1.14       chs  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     53  1.14       chs  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     54  1.14       chs  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     55  1.14       chs  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     56  1.14       chs  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     57  1.14       chs  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
     58  1.14       chs  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     59  1.14       chs  *
     60  1.14       chs  * Support from Chris Ellsworth in order to make SAS adapters work
     61  1.14       chs  * is gratefully acknowledged.
     62  1.14       chs  *
     63  1.14       chs  *
     64  1.14       chs  * Support from LSI-Logic has also gone a great deal toward making this a
     65  1.14       chs  * workable subsystem and is gratefully acknowledged.
     66  1.14       chs  */
     67  1.14       chs /*-
     68  1.14       chs  * Copyright (c) 2004, Avid Technology, Inc. and its contributors.
     69  1.14       chs  * Copyright (c) 2005, WHEEL Sp. z o.o.
     70  1.14       chs  * Copyright (c) 2004, 2005 Justin T. Gibbs
     71  1.14       chs  * All rights reserved.
     72  1.14       chs  *
     73  1.14       chs  * Redistribution and use in source and binary forms, with or without
     74  1.14       chs  * modification, are permitted provided that the following conditions are
     75  1.14       chs  * met:
     76  1.14       chs  * 1. Redistributions of source code must retain the above copyright
     77  1.14       chs  *    notice, this list of conditions and the following disclaimer.
     78  1.14       chs  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
     79  1.14       chs  *    substantially similar to the "NO WARRANTY" disclaimer below
     80  1.14       chs  *    ("Disclaimer") and any redistribution must be conditioned upon including
     81  1.14       chs  *    a substantially similar Disclaimer requirement for further binary
     82  1.14       chs  *    redistribution.
     83  1.14       chs  * 3. Neither the names of the above listed copyright holders nor the names
     84  1.14       chs  *    of any contributors may be used to endorse or promote products derived
     85  1.14       chs  *    from this software without specific prior written permission.
     86  1.14       chs  *
     87  1.14       chs  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     88  1.14       chs  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     89  1.14       chs  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     90  1.14       chs  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
     91  1.14       chs  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     92  1.14       chs  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     93  1.14       chs  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     94  1.14       chs  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     95  1.14       chs  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     96  1.14       chs  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF THE COPYRIGHT
     97  1.14       chs  * OWNER OR CONTRIBUTOR IS ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     98  1.14       chs  */
     99   1.1   thorpej 
    100   1.9      tron 
    101   1.1   thorpej /*
    102   1.1   thorpej  * mpt.c:
    103   1.1   thorpej  *
    104   1.1   thorpej  * Generic routines for LSI Fusion adapters.
    105   1.1   thorpej  *
    106   1.1   thorpej  * Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for
    107   1.1   thorpej  * Wasabi Systems, Inc.
    108   1.9      tron  *
    109   1.9      tron  * Additional contributions by Garrett D'Amore on behalf of TELES AG.
    110   1.1   thorpej  */
    111   1.3     lukem 
    112   1.3     lukem #include <sys/cdefs.h>
    113  1.21     skrll __KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.21 2019/09/23 16:19:33 skrll Exp $");
    114   1.1   thorpej 
    115   1.1   thorpej #include <dev/ic/mpt.h>
    116   1.1   thorpej 
    117   1.1   thorpej #define MPT_MAX_TRYS 3
    118   1.1   thorpej #define MPT_MAX_WAIT 300000
    119   1.1   thorpej 
    120   1.1   thorpej static int maxwait_ack = 0;
    121   1.1   thorpej static int maxwait_int = 0;
    122   1.1   thorpej static int maxwait_state = 0;
    123   1.1   thorpej 
    124   1.7     perry static inline u_int32_t
    125   1.1   thorpej mpt_rd_db(mpt_softc_t *mpt)
    126   1.1   thorpej {
    127   1.1   thorpej 	return mpt_read(mpt, MPT_OFFSET_DOORBELL);
    128   1.1   thorpej }
    129   1.1   thorpej 
    130   1.7     perry static inline u_int32_t
    131   1.1   thorpej mpt_rd_intr(mpt_softc_t *mpt)
    132   1.1   thorpej {
    133   1.1   thorpej 	return mpt_read(mpt, MPT_OFFSET_INTR_STATUS);
    134   1.1   thorpej }
    135   1.1   thorpej 
    136   1.1   thorpej /* Busy wait for a door bell to be read by IOC */
    137   1.1   thorpej static int
    138   1.1   thorpej mpt_wait_db_ack(mpt_softc_t *mpt)
    139   1.1   thorpej {
    140   1.1   thorpej 	int i;
    141   1.1   thorpej 	for (i=0; i < MPT_MAX_WAIT; i++) {
    142   1.1   thorpej 		if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) {
    143   1.1   thorpej 			maxwait_ack = i > maxwait_ack ? i : maxwait_ack;
    144   1.1   thorpej 			return MPT_OK;
    145   1.1   thorpej 		}
    146   1.1   thorpej 
    147   1.1   thorpej 		DELAY(100);
    148   1.1   thorpej 	}
    149   1.1   thorpej 	return MPT_FAIL;
    150   1.1   thorpej }
    151   1.1   thorpej 
    152   1.1   thorpej /* Busy wait for a door bell interrupt */
    153   1.1   thorpej static int
    154   1.1   thorpej mpt_wait_db_int(mpt_softc_t *mpt)
    155   1.1   thorpej {
    156   1.1   thorpej 	int i;
    157   1.1   thorpej 	for (i=0; i < MPT_MAX_WAIT; i++) {
    158   1.1   thorpej 		if (MPT_DB_INTR(mpt_rd_intr(mpt))) {
    159   1.1   thorpej 			maxwait_int = i > maxwait_int ? i : maxwait_int;
    160   1.1   thorpej 			return MPT_OK;
    161   1.1   thorpej 		}
    162   1.1   thorpej 		DELAY(100);
    163   1.1   thorpej 	}
    164   1.1   thorpej 	return MPT_FAIL;
    165   1.1   thorpej }
    166   1.1   thorpej 
    167   1.1   thorpej /* Wait for IOC to transition to a give state */
    168   1.1   thorpej void
    169   1.1   thorpej mpt_check_doorbell(mpt_softc_t *mpt)
    170   1.1   thorpej {
    171   1.1   thorpej 	u_int32_t db = mpt_rd_db(mpt);
    172   1.1   thorpej 	if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) {
    173   1.1   thorpej 		mpt_prt(mpt, "Device not running");
    174   1.1   thorpej 		mpt_print_db(db);
    175   1.1   thorpej 	}
    176   1.1   thorpej }
    177   1.1   thorpej 
    178   1.1   thorpej /* Wait for IOC to transition to a give state */
    179   1.1   thorpej static int
    180   1.1   thorpej mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state)
    181   1.1   thorpej {
    182   1.1   thorpej 	int i;
    183   1.1   thorpej 
    184   1.1   thorpej 	for (i = 0; i < MPT_MAX_WAIT; i++) {
    185   1.1   thorpej 		u_int32_t db = mpt_rd_db(mpt);
    186   1.1   thorpej 		if (MPT_STATE(db) == state) {
    187   1.1   thorpej 			maxwait_state = i > maxwait_state ? i : maxwait_state;
    188   1.1   thorpej 			return (MPT_OK);
    189   1.1   thorpej 		}
    190   1.1   thorpej 		DELAY(100);
    191   1.1   thorpej 	}
    192   1.1   thorpej 	return (MPT_FAIL);
    193   1.1   thorpej }
    194   1.1   thorpej 
    195   1.1   thorpej 
    196   1.1   thorpej /* Issue the reset COMMAND to the IOC */
    197   1.1   thorpej int
    198   1.1   thorpej mpt_soft_reset(mpt_softc_t *mpt)
    199   1.1   thorpej {
    200   1.1   thorpej 	if (mpt->verbose) {
    201   1.1   thorpej 		mpt_prt(mpt, "soft reset");
    202   1.1   thorpej 	}
    203   1.1   thorpej 
    204   1.1   thorpej 	/* Have to use hard reset if we are not in Running state */
    205   1.1   thorpej 	if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) {
    206   1.1   thorpej 		mpt_prt(mpt, "soft reset failed: device not running");
    207   1.1   thorpej 		return MPT_FAIL;
    208   1.1   thorpej 	}
    209   1.1   thorpej 
    210   1.1   thorpej 	/* If door bell is in use we don't have a chance of getting
    211   1.1   thorpej 	 * a word in since the IOC probably crashed in message
    212   1.1   thorpej 	 * processing. So don't waste our time.
    213   1.1   thorpej 	 */
    214   1.1   thorpej 	if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) {
    215   1.1   thorpej 		mpt_prt(mpt, "soft reset failed: doorbell wedged");
    216   1.1   thorpej 		return MPT_FAIL;
    217   1.1   thorpej 	}
    218   1.1   thorpej 
    219   1.1   thorpej 	/* Send the reset request to the IOC */
    220   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_DOORBELL,
    221   1.1   thorpej 	    MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT);
    222   1.1   thorpej 	if (mpt_wait_db_ack(mpt) != MPT_OK) {
    223   1.1   thorpej 		mpt_prt(mpt, "soft reset failed: ack timeout");
    224   1.1   thorpej 		return MPT_FAIL;
    225   1.1   thorpej 	}
    226   1.1   thorpej 
    227   1.1   thorpej 	/* Wait for the IOC to reload and come out of reset state */
    228   1.1   thorpej 	if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) {
    229   1.1   thorpej 		mpt_prt(mpt, "soft reset failed: device did not start running");
    230   1.1   thorpej 		return MPT_FAIL;
    231   1.1   thorpej 	}
    232   1.1   thorpej 
    233   1.1   thorpej 	return MPT_OK;
    234   1.1   thorpej }
    235   1.1   thorpej 
    236   1.1   thorpej /* This is a magic diagnostic reset that resets all the ARM
    237   1.5     perry  * processors in the chip.
    238   1.1   thorpej  */
    239   1.1   thorpej void
    240   1.1   thorpej mpt_hard_reset(mpt_softc_t *mpt)
    241   1.1   thorpej {
    242   1.1   thorpej 	if (mpt->verbose) {
    243   1.1   thorpej 		mpt_prt(mpt, "hard reset");
    244   1.1   thorpej 	}
    245   1.9      tron 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xff);
    246   1.1   thorpej 
    247   1.1   thorpej 	/* Enable diagnostic registers */
    248   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1);
    249   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2);
    250   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3);
    251   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4);
    252   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5);
    253   1.1   thorpej 
    254   1.1   thorpej 	/* Diag. port is now active so we can now hit the reset bit */
    255   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC);
    256   1.1   thorpej 
    257   1.1   thorpej 	DELAY(10000);
    258   1.1   thorpej 
    259   1.1   thorpej 	/* Disable Diagnostic Register */
    260   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF);
    261   1.1   thorpej }
    262   1.1   thorpej 
    263   1.1   thorpej /*
    264   1.1   thorpej  * Reset the IOC when needed. Try software command first then if needed
    265   1.1   thorpej  * poke at the magic diagnostic reset. Note that a hard reset resets
    266   1.1   thorpej  * *both* IOCs on dual function chips (FC929 && LSI1030) as well as
    267   1.1   thorpej  * fouls up the PCI configuration registers.
    268   1.1   thorpej  */
    269   1.1   thorpej int
    270   1.1   thorpej mpt_reset(mpt_softc_t *mpt)
    271   1.1   thorpej {
    272   1.1   thorpej 	int ret;
    273   1.1   thorpej 
    274   1.1   thorpej 	/* Try a soft reset */
    275   1.1   thorpej 	if ((ret = mpt_soft_reset(mpt)) != MPT_OK) {
    276   1.1   thorpej 		/* Failed; do a hard reset */
    277   1.1   thorpej 		mpt_hard_reset(mpt);
    278   1.1   thorpej 
    279   1.1   thorpej 		/* Wait for the IOC to reload and come out of reset state */
    280   1.1   thorpej 		ret = mpt_wait_state(mpt, MPT_DB_STATE_READY);
    281   1.1   thorpej 		if (ret != MPT_OK) {
    282   1.1   thorpej 			mpt_prt(mpt, "failed to reset device");
    283   1.1   thorpej 		}
    284   1.1   thorpej 	}
    285   1.1   thorpej 
    286   1.1   thorpej 	return ret;
    287   1.1   thorpej }
    288   1.1   thorpej 
    289   1.1   thorpej /* Return a command buffer to the free queue */
    290   1.1   thorpej void
    291   1.1   thorpej mpt_free_request(mpt_softc_t *mpt, request_t *req)
    292   1.1   thorpej {
    293   1.1   thorpej 	if (req == NULL || req != &mpt->request_pool[req->index]) {
    294   1.1   thorpej 		panic("mpt_free_request bad req ptr\n");
    295   1.1   thorpej 		return;
    296   1.1   thorpej 	}
    297   1.1   thorpej 	req->sequence = 0;
    298   1.1   thorpej 	req->xfer = NULL;
    299   1.1   thorpej 	req->debug = REQ_FREE;
    300   1.1   thorpej 	SLIST_INSERT_HEAD(&mpt->request_free_list, req, link);
    301   1.1   thorpej }
    302   1.1   thorpej 
    303   1.1   thorpej /* Get a command buffer from the free queue */
    304   1.1   thorpej request_t *
    305   1.1   thorpej mpt_get_request(mpt_softc_t *mpt)
    306   1.1   thorpej {
    307   1.1   thorpej 	request_t *req;
    308   1.1   thorpej 	req = SLIST_FIRST(&mpt->request_free_list);
    309   1.1   thorpej 	if (req != NULL) {
    310   1.1   thorpej 		if (req != &mpt->request_pool[req->index]) {
    311   1.1   thorpej 			panic("mpt_get_request: corrupted request free list\n");
    312   1.1   thorpej 		}
    313   1.1   thorpej 		if (req->xfer != NULL) {
    314   1.1   thorpej 			panic("mpt_get_request: corrupted request free list (xfer)\n");
    315   1.1   thorpej 		}
    316   1.1   thorpej 		SLIST_REMOVE_HEAD(&mpt->request_free_list, link);
    317   1.1   thorpej 		req->debug = REQ_IN_PROGRESS;
    318   1.1   thorpej 	}
    319   1.1   thorpej 	return req;
    320   1.1   thorpej }
    321   1.1   thorpej 
    322   1.1   thorpej /* Pass the command to the IOC */
    323   1.1   thorpej void
    324   1.1   thorpej mpt_send_cmd(mpt_softc_t *mpt, request_t *req)
    325   1.1   thorpej {
    326   1.1   thorpej 	req->sequence = mpt->sequence++;
    327   1.1   thorpej 	if (mpt->verbose > 1) {
    328   1.1   thorpej 		u_int32_t *pReq;
    329   1.1   thorpej 		pReq = req->req_vbuf;
    330  1.21     skrll 		mpt_prt(mpt, "Send Request %d (%#" PRIxBUSADDR "):",
    331  1.21     skrll 		    req->index, req->req_pbuf);
    332   1.1   thorpej 		mpt_prt(mpt, "%08x %08x %08x %08x",
    333   1.1   thorpej 		    pReq[0], pReq[1], pReq[2], pReq[3]);
    334   1.1   thorpej 		mpt_prt(mpt, "%08x %08x %08x %08x",
    335   1.1   thorpej 		    pReq[4], pReq[5], pReq[6], pReq[7]);
    336   1.1   thorpej 		mpt_prt(mpt, "%08x %08x %08x %08x",
    337   1.1   thorpej 		    pReq[8], pReq[9], pReq[10], pReq[11]);
    338   1.1   thorpej 		mpt_prt(mpt, "%08x %08x %08x %08x",
    339   1.1   thorpej 		    pReq[12], pReq[13], pReq[14], pReq[15]);
    340   1.1   thorpej 	}
    341   1.2   thorpej 	MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
    342   1.1   thorpej 	req->debug = REQ_ON_CHIP;
    343   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf);
    344   1.1   thorpej }
    345   1.1   thorpej 
    346   1.1   thorpej /*
    347   1.1   thorpej  * Give the reply buffer back to the IOC after we have
    348   1.1   thorpej  * finished processing it.
    349   1.1   thorpej  */
    350   1.1   thorpej void
    351   1.1   thorpej mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr)
    352   1.1   thorpej {
    353   1.1   thorpej      mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr);
    354   1.1   thorpej }
    355   1.1   thorpej 
    356   1.1   thorpej /* Get a reply from the IOC */
    357   1.1   thorpej u_int32_t
    358   1.1   thorpej mpt_pop_reply_queue(mpt_softc_t *mpt)
    359   1.1   thorpej {
    360   1.1   thorpej      return mpt_read(mpt, MPT_OFFSET_REPLY_Q);
    361   1.1   thorpej }
    362   1.1   thorpej 
    363   1.1   thorpej /*
    364   1.1   thorpej  * Send a command to the IOC via the handshake register.
    365   1.1   thorpej  *
    366   1.1   thorpej  * Only done at initialization time and for certain unusual
    367   1.1   thorpej  * commands such as device/bus reset as specified by LSI.
    368   1.1   thorpej  */
    369   1.1   thorpej int
    370   1.1   thorpej mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd)
    371   1.1   thorpej {
    372   1.1   thorpej 	int i;
    373   1.1   thorpej 	u_int32_t data, *data32;
    374   1.1   thorpej 
    375   1.1   thorpej 	/* Check condition of the IOC */
    376   1.1   thorpej 	data = mpt_rd_db(mpt);
    377   1.1   thorpej 	if (((MPT_STATE(data) != MPT_DB_STATE_READY)	&&
    378   1.1   thorpej 	     (MPT_STATE(data) != MPT_DB_STATE_RUNNING)	&&
    379   1.1   thorpej 	     (MPT_STATE(data) != MPT_DB_STATE_FAULT))	||
    380   1.1   thorpej 	    (  MPT_DB_IS_IN_USE(data) )) {
    381   1.1   thorpej 		mpt_prt(mpt, "handshake aborted due to invalid doorbell state");
    382   1.1   thorpej 		mpt_print_db(data);
    383   1.1   thorpej 		return(EBUSY);
    384   1.1   thorpej 	}
    385   1.1   thorpej 
    386   1.1   thorpej 	/* We move things in 32 bit chunks */
    387   1.1   thorpej 	len = (len + 3) >> 2;
    388   1.1   thorpej 	data32 = cmd;
    389   1.1   thorpej 
    390   1.4       wiz 	/* Clear any left over pending doorbell interrupts */
    391   1.1   thorpej 	if (MPT_DB_INTR(mpt_rd_intr(mpt)))
    392   1.1   thorpej 		mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    393   1.1   thorpej 
    394   1.1   thorpej 	/*
    395   1.1   thorpej 	 * Tell the handshake reg. we are going to send a command
    396   1.1   thorpej          * and how long it is going to be.
    397   1.1   thorpej 	 */
    398   1.1   thorpej 	data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) |
    399   1.1   thorpej 	    (len << MPI_DOORBELL_ADD_DWORDS_SHIFT);
    400   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_DOORBELL, data);
    401   1.1   thorpej 
    402   1.1   thorpej 	/* Wait for the chip to notice */
    403   1.1   thorpej 	if (mpt_wait_db_int(mpt) != MPT_OK) {
    404   1.1   thorpej 		mpt_prt(mpt, "mpt_send_handshake_cmd timeout1");
    405   1.1   thorpej 		return ETIMEDOUT;
    406   1.1   thorpej 	}
    407   1.1   thorpej 
    408   1.1   thorpej 	/* Clear the interrupt */
    409   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    410   1.1   thorpej 
    411   1.1   thorpej 	if (mpt_wait_db_ack(mpt) != MPT_OK) {
    412   1.1   thorpej 		mpt_prt(mpt, "mpt_send_handshake_cmd timeout2");
    413   1.1   thorpej 		return ETIMEDOUT;
    414   1.1   thorpej 	}
    415   1.1   thorpej 
    416   1.1   thorpej 	/* Send the command */
    417   1.1   thorpej 	for (i = 0; i < len; i++) {
    418  1.14       chs 		mpt_write(mpt, MPT_OFFSET_DOORBELL, htole32(*data32++));
    419   1.1   thorpej 		if (mpt_wait_db_ack(mpt) != MPT_OK) {
    420   1.1   thorpej 			mpt_prt(mpt,
    421   1.1   thorpej 			    "mpt_send_handshake_cmd timeout! index = %d", i);
    422   1.1   thorpej 			return ETIMEDOUT;
    423   1.1   thorpej 		}
    424   1.1   thorpej 	}
    425   1.1   thorpej 	return MPT_OK;
    426   1.1   thorpej }
    427   1.1   thorpej 
    428   1.1   thorpej /* Get the response from the handshake register */
    429   1.1   thorpej int
    430   1.1   thorpej mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply)
    431   1.1   thorpej {
    432   1.1   thorpej 	int left, reply_left;
    433   1.1   thorpej 	u_int16_t *data16;
    434   1.1   thorpej 	MSG_DEFAULT_REPLY *hdr;
    435   1.1   thorpej 
    436   1.1   thorpej 	/* We move things out in 16 bit chunks */
    437   1.1   thorpej 	reply_len >>= 1;
    438   1.1   thorpej 	data16 = (u_int16_t *)reply;
    439   1.1   thorpej 
    440   1.1   thorpej 	hdr = (MSG_DEFAULT_REPLY *)reply;
    441   1.1   thorpej 
    442   1.1   thorpej 	/* Get first word */
    443   1.1   thorpej 	if (mpt_wait_db_int(mpt) != MPT_OK) {
    444   1.1   thorpej 		mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1");
    445   1.1   thorpej 		return ETIMEDOUT;
    446   1.1   thorpej 	}
    447  1.14       chs 	*data16++ = le16toh(mpt_read(mpt, MPT_OFFSET_DOORBELL) &
    448  1.14       chs 			    MPT_DB_DATA_MASK);
    449   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    450   1.1   thorpej 
    451   1.1   thorpej 	/* Get Second Word */
    452   1.1   thorpej 	if (mpt_wait_db_int(mpt) != MPT_OK) {
    453   1.1   thorpej 		mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2");
    454   1.1   thorpej 		return ETIMEDOUT;
    455   1.1   thorpej 	}
    456  1.14       chs 	*data16++ = le16toh(mpt_read(mpt, MPT_OFFSET_DOORBELL) &
    457  1.14       chs 			    MPT_DB_DATA_MASK);
    458   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    459   1.1   thorpej 
    460   1.1   thorpej 	/* With the second word, we can now look at the length */
    461   1.1   thorpej 	if (mpt->verbose > 1 && ((reply_len >> 1) != hdr->MsgLength)) {
    462   1.1   thorpej 		mpt_prt(mpt, "reply length does not match message length: "
    463  1.19      maxv 			"got 0x%02x, expected %#02zx",
    464   1.1   thorpej 			hdr->MsgLength << 2, reply_len << 1);
    465   1.1   thorpej 	}
    466   1.1   thorpej 
    467   1.1   thorpej 	/* Get rest of the reply; but don't overflow the provided buffer */
    468   1.1   thorpej 	left = (hdr->MsgLength << 1) - 2;
    469   1.1   thorpej 	reply_left =  reply_len - 2;
    470   1.1   thorpej 	while (left--) {
    471   1.1   thorpej 		u_int16_t datum;
    472   1.1   thorpej 
    473   1.1   thorpej 		if (mpt_wait_db_int(mpt) != MPT_OK) {
    474   1.1   thorpej 			mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3");
    475   1.1   thorpej 			return ETIMEDOUT;
    476   1.1   thorpej 		}
    477   1.1   thorpej 		datum = mpt_read(mpt, MPT_OFFSET_DOORBELL);
    478   1.1   thorpej 
    479   1.1   thorpej 		if (reply_left-- > 0)
    480  1.14       chs 			*data16++ = le16toh(datum & MPT_DB_DATA_MASK);
    481   1.1   thorpej 
    482   1.1   thorpej 		mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    483   1.1   thorpej 	}
    484   1.1   thorpej 
    485   1.1   thorpej 	/* One more wait & clear at the end */
    486   1.1   thorpej 	if (mpt_wait_db_int(mpt) != MPT_OK) {
    487   1.1   thorpej 		mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4");
    488   1.1   thorpej 		return ETIMEDOUT;
    489   1.1   thorpej 	}
    490   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0);
    491   1.1   thorpej 
    492   1.1   thorpej 	if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    493   1.1   thorpej 		if (mpt->verbose > 1)
    494   1.1   thorpej 			mpt_print_reply(hdr);
    495   1.1   thorpej 		return (MPT_FAIL | hdr->IOCStatus);
    496   1.1   thorpej 	}
    497   1.1   thorpej 
    498   1.1   thorpej 	return (0);
    499   1.1   thorpej }
    500   1.1   thorpej 
    501   1.1   thorpej static int
    502   1.1   thorpej mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp)
    503   1.1   thorpej {
    504   1.1   thorpej 	MSG_IOC_FACTS f_req;
    505   1.1   thorpej 	int error;
    506   1.5     perry 
    507  1.11    cegger 	memset(&f_req, 0, sizeof f_req);
    508   1.1   thorpej 	f_req.Function = MPI_FUNCTION_IOC_FACTS;
    509  1.14       chs 	f_req.MsgContext = htole32(0x12071942);
    510   1.1   thorpej 	error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
    511   1.1   thorpej 	if (error)
    512   1.1   thorpej 		return(error);
    513   1.1   thorpej 	error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
    514   1.1   thorpej 	return (error);
    515   1.1   thorpej }
    516   1.1   thorpej 
    517   1.1   thorpej static int
    518   1.1   thorpej mpt_get_portfacts(mpt_softc_t *mpt, MSG_PORT_FACTS_REPLY *freplp)
    519   1.1   thorpej {
    520   1.1   thorpej 	MSG_PORT_FACTS f_req;
    521   1.1   thorpej 	int error;
    522   1.5     perry 
    523   1.1   thorpej 	/* XXX: Only getting PORT FACTS for Port 0 */
    524  1.11    cegger 	memset(&f_req, 0, sizeof f_req);
    525   1.1   thorpej 	f_req.Function = MPI_FUNCTION_PORT_FACTS;
    526  1.14       chs 	f_req.MsgContext =  htole32(0x12071943);
    527   1.1   thorpej 	error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
    528   1.1   thorpej 	if (error)
    529   1.1   thorpej 		return(error);
    530   1.1   thorpej 	error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
    531   1.1   thorpej 	return (error);
    532   1.1   thorpej }
    533   1.1   thorpej 
    534   1.1   thorpej /*
    535   1.1   thorpej  * Send the initialization request. This is where we specify how many
    536   1.1   thorpej  * SCSI busses and how many devices per bus we wish to emulate.
    537   1.1   thorpej  * This is also the command that specifies the max size of the reply
    538   1.1   thorpej  * frames from the IOC that we will be allocating.
    539   1.1   thorpej  */
    540   1.1   thorpej static int
    541   1.1   thorpej mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who)
    542   1.1   thorpej {
    543   1.1   thorpej 	int error = 0;
    544   1.1   thorpej 	MSG_IOC_INIT init;
    545   1.1   thorpej 	MSG_IOC_INIT_REPLY reply;
    546   1.1   thorpej 
    547  1.11    cegger 	memset(&init, 0, sizeof init);
    548   1.1   thorpej 	init.WhoInit = who;
    549   1.1   thorpej 	init.Function = MPI_FUNCTION_IOC_INIT;
    550   1.9      tron 	init.MaxDevices = mpt->mpt_max_devices;
    551   1.1   thorpej 	init.MaxBuses = 1;
    552  1.14       chs 	init.ReplyFrameSize = htole16(MPT_REPLY_SIZE);
    553  1.14       chs 	init.MsgContext = htole32(0x12071941);
    554   1.1   thorpej 
    555   1.1   thorpej 	if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) {
    556   1.1   thorpej 		return(error);
    557   1.1   thorpej 	}
    558   1.1   thorpej 
    559   1.1   thorpej 	error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply);
    560   1.1   thorpej 	return (error);
    561   1.1   thorpej }
    562   1.1   thorpej 
    563   1.1   thorpej 
    564   1.1   thorpej /*
    565   1.1   thorpej  * Utiltity routine to read configuration headers and pages
    566   1.1   thorpej  */
    567   1.1   thorpej 
    568  1.17  jmcneill int
    569   1.1   thorpej mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber,
    570   1.1   thorpej     int PageAddress, fCONFIG_PAGE_HEADER *rslt)
    571   1.1   thorpej {
    572   1.1   thorpej 	int count;
    573   1.1   thorpej 	request_t *req;
    574   1.1   thorpej 	MSG_CONFIG *cfgp;
    575   1.1   thorpej 	MSG_CONFIG_REPLY *reply;
    576   1.1   thorpej 
    577   1.1   thorpej 	req = mpt_get_request(mpt);
    578   1.1   thorpej 
    579   1.1   thorpej 	cfgp = req->req_vbuf;
    580  1.11    cegger 	memset(cfgp, 0, sizeof *cfgp);
    581   1.1   thorpej 
    582   1.1   thorpej 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER;
    583   1.1   thorpej 	cfgp->Function = MPI_FUNCTION_CONFIG;
    584   1.1   thorpej 	cfgp->Header.PageNumber = (U8) PageNumber;
    585   1.1   thorpej 	cfgp->Header.PageType = (U8) PageType;
    586  1.14       chs 	cfgp->PageAddress = htole32(PageAddress);
    587   1.1   thorpej 	MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE),
    588   1.1   thorpej 	    (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    589   1.1   thorpej 	    MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST));
    590  1.14       chs 	cfgp->MsgContext = htole32(req->index | 0x80000000);
    591   1.1   thorpej 
    592   1.1   thorpej 	mpt_check_doorbell(mpt);
    593   1.1   thorpej 	mpt_send_cmd(mpt, req);
    594   1.1   thorpej 	count = 0;
    595   1.1   thorpej 	do {
    596   1.1   thorpej 		DELAY(500);
    597   1.1   thorpej 		mpt_intr(mpt);
    598   1.1   thorpej 		if (++count == 1000) {
    599   1.1   thorpej 			mpt_prt(mpt, "read_cfg_header timed out");
    600   1.1   thorpej 			return (-1);
    601   1.1   thorpej 		}
    602   1.1   thorpej 	} while (req->debug == REQ_ON_CHIP);
    603   1.1   thorpej 
    604   1.1   thorpej 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    605   1.1   thorpej         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    606   1.1   thorpej 		mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x",
    607   1.1   thorpej 		    reply->IOCStatus);
    608   1.1   thorpej 		mpt_free_reply(mpt, (req->sequence << 1));
    609   1.1   thorpej 		return (-1);
    610   1.1   thorpej 	}
    611  1.13   tsutsui 	memcpy(rslt, &reply->Header, sizeof (fCONFIG_PAGE_HEADER));
    612   1.1   thorpej 	mpt_free_reply(mpt, (req->sequence << 1));
    613   1.1   thorpej 	mpt_free_request(mpt, req);
    614   1.1   thorpej 	return (0);
    615   1.1   thorpej }
    616   1.1   thorpej 
    617   1.1   thorpej #define	CFG_DATA_OFF	128
    618   1.1   thorpej 
    619   1.1   thorpej int
    620   1.1   thorpej mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
    621   1.1   thorpej {
    622   1.1   thorpej 	int count;
    623   1.1   thorpej 	request_t *req;
    624   1.1   thorpej 	SGE_SIMPLE32 *se;
    625   1.1   thorpej 	MSG_CONFIG *cfgp;
    626   1.1   thorpej 	size_t amt;
    627   1.1   thorpej 	MSG_CONFIG_REPLY *reply;
    628   1.1   thorpej 
    629   1.1   thorpej 	req = mpt_get_request(mpt);
    630   1.1   thorpej 
    631   1.1   thorpej 	cfgp = req->req_vbuf;
    632  1.11    cegger 	memset(cfgp, 0, MPT_REQUEST_AREA);
    633   1.1   thorpej 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT;
    634   1.1   thorpej 	cfgp->Function = MPI_FUNCTION_CONFIG;
    635   1.1   thorpej 	cfgp->Header = *hdr;
    636   1.1   thorpej  	amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
    637   1.1   thorpej 	cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK;
    638  1.14       chs 	cfgp->PageAddress = htole32(PageAddress);
    639   1.1   thorpej 	se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
    640  1.14       chs 	se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
    641   1.1   thorpej 	MPI_pSGE_SET_LENGTH(se, amt);
    642   1.1   thorpej 	MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
    643   1.1   thorpej 	    MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    644   1.1   thorpej 	    MPI_SGE_FLAGS_END_OF_LIST));
    645  1.14       chs 	se->FlagsLength = htole32(se->FlagsLength);
    646   1.1   thorpej 
    647  1.14       chs 	cfgp->MsgContext = htole32(req->index | 0x80000000);
    648   1.1   thorpej 
    649   1.1   thorpej 	mpt_check_doorbell(mpt);
    650   1.1   thorpej 	mpt_send_cmd(mpt, req);
    651   1.1   thorpej 	count = 0;
    652   1.1   thorpej 	do {
    653   1.1   thorpej 		DELAY(500);
    654   1.1   thorpej 		mpt_intr(mpt);
    655   1.1   thorpej 		if (++count == 1000) {
    656   1.1   thorpej 			mpt_prt(mpt, "read_cfg_page timed out");
    657   1.1   thorpej 			return (-1);
    658   1.1   thorpej 		}
    659   1.1   thorpej 	} while (req->debug == REQ_ON_CHIP);
    660   1.1   thorpej 
    661   1.1   thorpej 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    662   1.1   thorpej         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    663   1.1   thorpej 		mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x",
    664   1.1   thorpej 		    reply->IOCStatus);
    665   1.1   thorpej 		mpt_free_reply(mpt, (req->sequence << 1));
    666   1.1   thorpej 		return (-1);
    667   1.1   thorpej 	}
    668   1.1   thorpej 	mpt_free_reply(mpt, (req->sequence << 1));
    669   1.1   thorpej #if 0 /* XXXJRT */
    670   1.1   thorpej 	bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap,
    671   1.1   thorpej 	    BUS_DMASYNC_POSTREAD);
    672   1.1   thorpej #endif
    673   1.1   thorpej 	if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    674   1.1   thorpej 	    cfgp->Header.PageNumber == 0) {
    675   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
    676   1.1   thorpej 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    677   1.1   thorpej 	    cfgp->Header.PageNumber == 1) {
    678   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
    679   1.1   thorpej 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    680   1.1   thorpej 	    cfgp->Header.PageNumber == 2) {
    681   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
    682   1.1   thorpej 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    683   1.1   thorpej 	    cfgp->Header.PageNumber == 0) {
    684   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
    685   1.1   thorpej 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    686   1.1   thorpej 	    cfgp->Header.PageNumber == 1) {
    687   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
    688   1.1   thorpej 	}
    689   1.8  christos 	memcpy(hdr, (char *)req->req_vbuf + CFG_DATA_OFF, amt);
    690   1.1   thorpej 	mpt_free_request(mpt, req);
    691   1.1   thorpej 	return (0);
    692   1.1   thorpej }
    693   1.1   thorpej 
    694   1.1   thorpej int
    695   1.1   thorpej mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr)
    696   1.1   thorpej {
    697   1.1   thorpej 	int count, hdr_attr;
    698   1.1   thorpej 	request_t *req;
    699   1.1   thorpej 	SGE_SIMPLE32 *se;
    700   1.1   thorpej 	MSG_CONFIG *cfgp;
    701   1.1   thorpej 	size_t amt;
    702   1.1   thorpej 	MSG_CONFIG_REPLY *reply;
    703   1.1   thorpej 
    704   1.1   thorpej 	req = mpt_get_request(mpt);
    705   1.1   thorpej 
    706   1.1   thorpej 	cfgp = req->req_vbuf;
    707  1.11    cegger 	memset(cfgp, 0, sizeof *cfgp);
    708   1.1   thorpej 
    709   1.1   thorpej 	hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK;
    710   1.1   thorpej 	if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE &&
    711   1.1   thorpej 	    hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) {
    712   1.1   thorpej 		mpt_prt(mpt, "page type 0x%x not changeable",
    713   1.1   thorpej 		    hdr->PageType & MPI_CONFIG_PAGETYPE_MASK);
    714   1.1   thorpej 		return (-1);
    715   1.1   thorpej 	}
    716   1.1   thorpej 	hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK;
    717   1.1   thorpej 
    718   1.1   thorpej 	cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT;
    719   1.1   thorpej 	cfgp->Function = MPI_FUNCTION_CONFIG;
    720   1.1   thorpej 	cfgp->Header = *hdr;
    721   1.1   thorpej  	amt = (cfgp->Header.PageLength * sizeof (u_int32_t));
    722  1.14       chs 	cfgp->PageAddress = htole32(PageAddress);
    723   1.1   thorpej 
    724   1.1   thorpej 	se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE;
    725  1.14       chs 	se->Address = htole32(req->req_pbuf + CFG_DATA_OFF);
    726   1.1   thorpej 	MPI_pSGE_SET_LENGTH(se, amt);
    727   1.1   thorpej 	MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT |
    728   1.1   thorpej 	    MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER |
    729   1.1   thorpej 	    MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC));
    730  1.14       chs 	se->FlagsLength = htole32(se->FlagsLength);
    731   1.1   thorpej 
    732  1.14       chs 	cfgp->MsgContext = htole32(req->index | 0x80000000);
    733   1.1   thorpej 
    734   1.1   thorpej 	if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    735   1.1   thorpej 	    cfgp->Header.PageNumber == 0) {
    736   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0);
    737   1.1   thorpej 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    738   1.1   thorpej 	    cfgp->Header.PageNumber == 1) {
    739   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1);
    740   1.1   thorpej 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT &&
    741   1.1   thorpej 	    cfgp->Header.PageNumber == 2) {
    742   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2);
    743   1.1   thorpej 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    744   1.1   thorpej 	    cfgp->Header.PageNumber == 0) {
    745   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0);
    746   1.1   thorpej 	} else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE  &&
    747   1.1   thorpej 	    cfgp->Header.PageNumber == 1) {
    748   1.1   thorpej 		amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1);
    749   1.1   thorpej 	}
    750   1.8  christos 	memcpy((char *)req->req_vbuf + CFG_DATA_OFF, hdr, amt);
    751   1.1   thorpej 	/* Restore stripped out attributes */
    752   1.1   thorpej 	hdr->PageType |= hdr_attr;
    753   1.1   thorpej 
    754   1.1   thorpej 	mpt_check_doorbell(mpt);
    755   1.1   thorpej 	mpt_send_cmd(mpt, req);
    756   1.1   thorpej 	count = 0;
    757   1.1   thorpej 	do {
    758   1.1   thorpej 		DELAY(500);
    759   1.1   thorpej 		mpt_intr(mpt);
    760   1.1   thorpej 		if (++count == 1000) {
    761   1.1   thorpej 			hdr->PageType |= hdr_attr;
    762   1.1   thorpej 			mpt_prt(mpt, "mpt_write_cfg_page timed out");
    763   1.1   thorpej 			return (-1);
    764   1.1   thorpej 		}
    765   1.1   thorpej 	} while (req->debug == REQ_ON_CHIP);
    766   1.1   thorpej 
    767   1.1   thorpej 	reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence);
    768   1.1   thorpej         if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) {
    769   1.1   thorpej 		mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x",
    770  1.14       chs 		    le16toh(reply->IOCStatus));
    771   1.1   thorpej 		mpt_free_reply(mpt, (req->sequence << 1));
    772   1.1   thorpej 		return (-1);
    773   1.1   thorpej 	}
    774   1.1   thorpej 	mpt_free_reply(mpt, (req->sequence << 1));
    775   1.1   thorpej 
    776   1.1   thorpej 	mpt_free_request(mpt, req);
    777   1.1   thorpej 	return (0);
    778   1.1   thorpej }
    779   1.1   thorpej 
    780   1.1   thorpej /*
    781   1.1   thorpej  * Read SCSI configuration information
    782   1.1   thorpej  */
    783   1.1   thorpej static int
    784   1.1   thorpej mpt_read_config_info_spi(mpt_softc_t *mpt)
    785   1.1   thorpej {
    786   1.1   thorpej 	int rv, i;
    787   1.1   thorpej 
    788   1.1   thorpej 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0,
    789   1.1   thorpej 	    0, &mpt->mpt_port_page0.Header);
    790   1.1   thorpej 	if (rv) {
    791   1.1   thorpej 		return (-1);
    792   1.1   thorpej 	}
    793   1.1   thorpej 	if (mpt->verbose > 1) {
    794   1.1   thorpej 		mpt_prt(mpt, "SPI Port Page 0 Header: %x %x %x %x",
    795   1.1   thorpej 		    mpt->mpt_port_page0.Header.PageVersion,
    796   1.1   thorpej 		    mpt->mpt_port_page0.Header.PageLength,
    797   1.1   thorpej 		    mpt->mpt_port_page0.Header.PageNumber,
    798   1.1   thorpej 		    mpt->mpt_port_page0.Header.PageType);
    799   1.1   thorpej 	}
    800   1.1   thorpej 
    801   1.1   thorpej 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1,
    802   1.1   thorpej 	    0, &mpt->mpt_port_page1.Header);
    803   1.1   thorpej 	if (rv) {
    804   1.1   thorpej 		return (-1);
    805   1.1   thorpej 	}
    806   1.1   thorpej 	if (mpt->verbose > 1) {
    807   1.1   thorpej 		mpt_prt(mpt, "SPI Port Page 1 Header: %x %x %x %x",
    808   1.1   thorpej 		    mpt->mpt_port_page1.Header.PageVersion,
    809   1.1   thorpej 		    mpt->mpt_port_page1.Header.PageLength,
    810   1.1   thorpej 		    mpt->mpt_port_page1.Header.PageNumber,
    811   1.1   thorpej 		    mpt->mpt_port_page1.Header.PageType);
    812   1.1   thorpej 	}
    813   1.1   thorpej 
    814   1.1   thorpej 	rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2,
    815   1.1   thorpej 	    0, &mpt->mpt_port_page2.Header);
    816   1.1   thorpej 	if (rv) {
    817   1.1   thorpej 		return (-1);
    818   1.1   thorpej 	}
    819   1.1   thorpej 
    820   1.1   thorpej 	if (mpt->verbose > 1) {
    821   1.1   thorpej 		mpt_prt(mpt, "SPI Port Page 2 Header: %x %x %x %x",
    822   1.1   thorpej 		    mpt->mpt_port_page1.Header.PageVersion,
    823   1.1   thorpej 		    mpt->mpt_port_page1.Header.PageLength,
    824   1.1   thorpej 		    mpt->mpt_port_page1.Header.PageNumber,
    825   1.1   thorpej 		    mpt->mpt_port_page1.Header.PageType);
    826   1.1   thorpej 	}
    827   1.1   thorpej 
    828   1.1   thorpej 	for (i = 0; i < 16; i++) {
    829   1.1   thorpej 		rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
    830   1.1   thorpej 		    0, i, &mpt->mpt_dev_page0[i].Header);
    831   1.1   thorpej 		if (rv) {
    832   1.1   thorpej 			return (-1);
    833   1.1   thorpej 		}
    834   1.1   thorpej 		if (mpt->verbose > 1) {
    835   1.1   thorpej 			mpt_prt(mpt,
    836   1.1   thorpej 			    "SPI Target %d Device Page 0 Header: %x %x %x %x",
    837   1.1   thorpej 			    i, mpt->mpt_dev_page0[i].Header.PageVersion,
    838   1.1   thorpej 			    mpt->mpt_dev_page0[i].Header.PageLength,
    839   1.1   thorpej 			    mpt->mpt_dev_page0[i].Header.PageNumber,
    840   1.1   thorpej 			    mpt->mpt_dev_page0[i].Header.PageType);
    841   1.1   thorpej 		}
    842   1.5     perry 
    843   1.1   thorpej 		rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE,
    844   1.1   thorpej 		    1, i, &mpt->mpt_dev_page1[i].Header);
    845   1.1   thorpej 		if (rv) {
    846   1.1   thorpej 			return (-1);
    847   1.1   thorpej 		}
    848   1.1   thorpej 		if (mpt->verbose > 1) {
    849   1.1   thorpej 			mpt_prt(mpt,
    850   1.1   thorpej 			    "SPI Target %d Device Page 1 Header: %x %x %x %x",
    851   1.1   thorpej 			    i, mpt->mpt_dev_page1[i].Header.PageVersion,
    852   1.1   thorpej 			    mpt->mpt_dev_page1[i].Header.PageLength,
    853   1.1   thorpej 			    mpt->mpt_dev_page1[i].Header.PageNumber,
    854   1.1   thorpej 			    mpt->mpt_dev_page1[i].Header.PageType);
    855   1.1   thorpej 		}
    856   1.1   thorpej 	}
    857   1.1   thorpej 
    858   1.1   thorpej 	/*
    859   1.1   thorpej 	 * At this point, we don't *have* to fail. As long as we have
    860   1.1   thorpej 	 * valid config header information, we can (barely) lurch
    861   1.1   thorpej 	 * along.
    862   1.1   thorpej 	 */
    863   1.1   thorpej 
    864   1.1   thorpej 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header);
    865  1.14       chs 	mpt2host_config_page_scsi_port_0(&mpt->mpt_port_page0);
    866   1.1   thorpej 	if (rv) {
    867   1.1   thorpej 		mpt_prt(mpt, "failed to read SPI Port Page 0");
    868   1.1   thorpej 	} else if (mpt->verbose > 1) {
    869   1.1   thorpej 		mpt_prt(mpt,
    870   1.1   thorpej 		    "SPI Port Page 0: Capabilities %x PhysicalInterface %x",
    871   1.1   thorpej 		    mpt->mpt_port_page0.Capabilities,
    872   1.1   thorpej 		    mpt->mpt_port_page0.PhysicalInterface);
    873   1.1   thorpej 	}
    874   1.1   thorpej 
    875   1.1   thorpej 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header);
    876  1.14       chs 	mpt2host_config_page_scsi_port_1(&mpt->mpt_port_page1);
    877   1.1   thorpej 	if (rv) {
    878   1.1   thorpej 		mpt_prt(mpt, "failed to read SPI Port Page 1");
    879   1.1   thorpej 	} else if (mpt->verbose > 1) {
    880   1.1   thorpej 		mpt_prt(mpt,
    881   1.1   thorpej 		    "SPI Port Page 1: Configuration %x OnBusTimerValue %x",
    882   1.1   thorpej 		    mpt->mpt_port_page1.Configuration,
    883   1.1   thorpej 		    mpt->mpt_port_page1.OnBusTimerValue);
    884   1.1   thorpej 	}
    885   1.1   thorpej 
    886   1.1   thorpej 	rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header);
    887  1.14       chs 	mpt2host_config_page_scsi_port_2(&mpt->mpt_port_page2);
    888   1.1   thorpej 	if (rv) {
    889   1.1   thorpej 		mpt_prt(mpt, "failed to read SPI Port Page 2");
    890   1.1   thorpej 	} else if (mpt->verbose > 1) {
    891   1.1   thorpej 		mpt_prt(mpt,
    892   1.1   thorpej 		    "SPI Port Page 2: Flags %x Settings %x",
    893   1.1   thorpej 		    mpt->mpt_port_page2.PortFlags,
    894   1.1   thorpej 		    mpt->mpt_port_page2.PortSettings);
    895  1.14       chs 		for (i = 0; i < 1; i++) {
    896   1.1   thorpej 			mpt_prt(mpt,
    897   1.1   thorpej 		  	    "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x",
    898   1.1   thorpej 			    i, mpt->mpt_port_page2.DeviceSettings[i].Timeout,
    899   1.1   thorpej 			    mpt->mpt_port_page2.DeviceSettings[i].SyncFactor,
    900   1.1   thorpej 			    mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags);
    901   1.1   thorpej 		}
    902   1.1   thorpej 	}
    903   1.1   thorpej 
    904   1.1   thorpej 	for (i = 0; i < 16; i++) {
    905   1.1   thorpej 		rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header);
    906  1.14       chs 		mpt2host_config_page_scsi_device_0(&mpt->mpt_dev_page0[i]);
    907   1.1   thorpej 		if (rv) {
    908   1.1   thorpej 			mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i);
    909   1.1   thorpej 			continue;
    910   1.1   thorpej 		}
    911   1.1   thorpej 		if (mpt->verbose > 1) {
    912   1.1   thorpej 			mpt_prt(mpt,
    913   1.1   thorpej 			    "SPI Tgt %d Page 0: NParms %x Information %x",
    914   1.1   thorpej 			    i, mpt->mpt_dev_page0[i].NegotiatedParameters,
    915   1.1   thorpej 			    mpt->mpt_dev_page0[i].Information);
    916   1.1   thorpej 		}
    917   1.1   thorpej 		rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header);
    918  1.14       chs 		mpt2host_config_page_scsi_device_1(&mpt->mpt_dev_page1[i]);
    919   1.1   thorpej 		if (rv) {
    920   1.1   thorpej 			mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i);
    921   1.1   thorpej 			continue;
    922   1.1   thorpej 		}
    923   1.1   thorpej 		if (mpt->verbose > 1) {
    924   1.1   thorpej 			mpt_prt(mpt,
    925   1.1   thorpej 			    "SPI Tgt %d Page 1: RParms %x Configuration %x",
    926   1.1   thorpej 			    i, mpt->mpt_dev_page1[i].RequestedParameters,
    927   1.1   thorpej 			    mpt->mpt_dev_page1[i].Configuration);
    928   1.1   thorpej 		}
    929   1.1   thorpej 	}
    930   1.1   thorpej 	return (0);
    931   1.1   thorpej }
    932   1.1   thorpej 
    933   1.1   thorpej /*
    934   1.1   thorpej  * Validate SPI configuration information.
    935   1.1   thorpej  *
    936   1.1   thorpej  * In particular, validate SPI Port Page 1.
    937   1.1   thorpej  */
    938   1.1   thorpej static int
    939   1.1   thorpej mpt_set_initial_config_spi(mpt_softc_t *mpt)
    940   1.1   thorpej {
    941   1.1   thorpej 	int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id;
    942   1.1   thorpej 
    943  1.18  jakllsch 	mpt->mpt_disc_enable = 0xffff;
    944   1.1   thorpej 	mpt->mpt_tag_enable = 0;
    945   1.1   thorpej 
    946   1.1   thorpej 	if (mpt->mpt_port_page1.Configuration != pp1val) {
    947   1.1   thorpej 		fCONFIG_PAGE_SCSI_PORT_1 tmp;
    948  1.14       chs 
    949   1.1   thorpej 		mpt_prt(mpt,
    950   1.1   thorpej 		    "SPI Port Page 1 Config value bad (%x)- should be %x",
    951   1.1   thorpej 		    mpt->mpt_port_page1.Configuration, pp1val);
    952   1.1   thorpej 		tmp = mpt->mpt_port_page1;
    953   1.1   thorpej 		tmp.Configuration = pp1val;
    954  1.14       chs 		host2mpt_config_page_scsi_port_1(&tmp);
    955   1.1   thorpej 		if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) {
    956   1.1   thorpej 			return (-1);
    957   1.1   thorpej 		}
    958   1.1   thorpej 		if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) {
    959   1.1   thorpej 			return (-1);
    960   1.1   thorpej 		}
    961  1.14       chs 		mpt2host_config_page_scsi_port_1(&tmp);
    962   1.1   thorpej 		if (tmp.Configuration != pp1val) {
    963   1.1   thorpej 			mpt_prt(mpt,
    964   1.1   thorpej 			    "failed to reset SPI Port Page 1 Config value");
    965   1.1   thorpej 			return (-1);
    966   1.1   thorpej 		}
    967   1.1   thorpej 		mpt->mpt_port_page1 = tmp;
    968   1.1   thorpej 	}
    969   1.1   thorpej 
    970  1.14       chs 	i = 0;
    971   1.1   thorpej 	for (i = 0; i < 16; i++) {
    972   1.1   thorpej 		fCONFIG_PAGE_SCSI_DEVICE_1 tmp;
    973  1.14       chs 
    974   1.1   thorpej 		tmp = mpt->mpt_dev_page1[i];
    975   1.1   thorpej 		tmp.RequestedParameters = 0;
    976   1.1   thorpej 		tmp.Configuration = 0;
    977   1.1   thorpej 		if (mpt->verbose > 1) {
    978   1.1   thorpej 			mpt_prt(mpt,
    979   1.1   thorpej 			    "Set Tgt %d SPI DevicePage 1 values to %x 0 %x",
    980   1.1   thorpej 			    i, tmp.RequestedParameters, tmp.Configuration);
    981   1.1   thorpej 		}
    982  1.14       chs 		host2mpt_config_page_scsi_device_1(&tmp);
    983   1.1   thorpej 		if (mpt_write_cfg_page(mpt, i, &tmp.Header)) {
    984   1.1   thorpej 			return (-1);
    985   1.1   thorpej 		}
    986   1.1   thorpej 		if (mpt_read_cfg_page(mpt, i, &tmp.Header)) {
    987   1.1   thorpej 			return (-1);
    988   1.1   thorpej 		}
    989  1.14       chs 		mpt2host_config_page_scsi_device_1(&tmp);
    990   1.1   thorpej 		mpt->mpt_dev_page1[i] = tmp;
    991   1.1   thorpej 		if (mpt->verbose > 1) {
    992   1.1   thorpej 			mpt_prt(mpt,
    993   1.1   thorpej 		 	    "SPI Tgt %d Page 1: RParm %x Configuration %x", i,
    994   1.1   thorpej 			    mpt->mpt_dev_page1[i].RequestedParameters,
    995   1.1   thorpej 			    mpt->mpt_dev_page1[i].Configuration);
    996   1.1   thorpej 		}
    997   1.1   thorpej 	}
    998   1.1   thorpej 	return (0);
    999   1.1   thorpej }
   1000   1.1   thorpej 
   1001   1.1   thorpej /*
   1002   1.1   thorpej  * Enable IOC port
   1003   1.1   thorpej  */
   1004   1.1   thorpej static int
   1005   1.1   thorpej mpt_send_port_enable(mpt_softc_t *mpt, int port)
   1006   1.1   thorpej {
   1007   1.1   thorpej 	int count;
   1008   1.1   thorpej 	request_t *req;
   1009   1.1   thorpej 	MSG_PORT_ENABLE *enable_req;
   1010   1.1   thorpej 
   1011   1.1   thorpej 	req = mpt_get_request(mpt);
   1012   1.1   thorpej 
   1013   1.1   thorpej 	enable_req = req->req_vbuf;
   1014  1.11    cegger 	memset(enable_req, 0, sizeof *enable_req);
   1015   1.1   thorpej 
   1016   1.1   thorpej 	enable_req->Function   = MPI_FUNCTION_PORT_ENABLE;
   1017  1.14       chs 	enable_req->MsgContext = htole32(req->index | 0x80000000);
   1018   1.1   thorpej 	enable_req->PortNumber = port;
   1019   1.1   thorpej 
   1020   1.1   thorpej 	mpt_check_doorbell(mpt);
   1021   1.1   thorpej 	if (mpt->verbose > 1) {
   1022   1.1   thorpej 		mpt_prt(mpt, "enabling port %d", port);
   1023   1.1   thorpej 	}
   1024   1.1   thorpej 	mpt_send_cmd(mpt, req);
   1025   1.1   thorpej 
   1026   1.1   thorpej 	count = 0;
   1027   1.1   thorpej 	do {
   1028   1.1   thorpej 		DELAY(500);
   1029   1.1   thorpej 		mpt_intr(mpt);
   1030   1.1   thorpej 		if (++count == 100000) {
   1031   1.1   thorpej 			mpt_prt(mpt, "port enable timed out");
   1032   1.1   thorpej 			return (-1);
   1033   1.1   thorpej 		}
   1034   1.1   thorpej 	} while (req->debug == REQ_ON_CHIP);
   1035   1.1   thorpej 	mpt_free_request(mpt, req);
   1036   1.1   thorpej 	return (0);
   1037   1.1   thorpej }
   1038   1.1   thorpej 
   1039   1.1   thorpej /*
   1040   1.1   thorpej  * Enable/Disable asynchronous event reporting.
   1041   1.1   thorpej  *
   1042   1.1   thorpej  * NB: this is the first command we send via shared memory
   1043   1.1   thorpej  * instead of the handshake register.
   1044   1.1   thorpej  */
   1045   1.1   thorpej static int
   1046   1.1   thorpej mpt_send_event_request(mpt_softc_t *mpt, int onoff)
   1047   1.1   thorpej {
   1048   1.1   thorpej 	request_t *req;
   1049   1.1   thorpej 	MSG_EVENT_NOTIFY *enable_req;
   1050   1.1   thorpej 
   1051   1.1   thorpej 	req = mpt_get_request(mpt);
   1052   1.1   thorpej 
   1053   1.1   thorpej 	enable_req = req->req_vbuf;
   1054  1.11    cegger 	memset(enable_req, 0, sizeof *enable_req);
   1055   1.1   thorpej 
   1056   1.1   thorpej 	enable_req->Function   = MPI_FUNCTION_EVENT_NOTIFICATION;
   1057  1.14       chs 	enable_req->MsgContext = htole32(req->index | 0x80000000);
   1058   1.1   thorpej 	enable_req->Switch     = onoff;
   1059   1.1   thorpej 
   1060   1.1   thorpej 	mpt_check_doorbell(mpt);
   1061   1.1   thorpej 	if (mpt->verbose > 1) {
   1062   1.1   thorpej 		mpt_prt(mpt, "%sabling async events", onoff? "en" : "dis");
   1063   1.1   thorpej 	}
   1064   1.1   thorpej 	mpt_send_cmd(mpt, req);
   1065   1.1   thorpej 
   1066   1.1   thorpej 	return (0);
   1067   1.1   thorpej }
   1068   1.1   thorpej 
   1069   1.1   thorpej /*
   1070   1.4       wiz  * Un-mask the interrupts on the chip.
   1071   1.1   thorpej  */
   1072   1.1   thorpej void
   1073   1.1   thorpej mpt_enable_ints(mpt_softc_t *mpt)
   1074   1.1   thorpej {
   1075   1.1   thorpej 	/* Unmask every thing except door bell int */
   1076   1.1   thorpej 	mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK);
   1077   1.1   thorpej }
   1078   1.1   thorpej 
   1079   1.1   thorpej /*
   1080   1.4       wiz  * Mask the interrupts on the chip.
   1081   1.1   thorpej  */
   1082   1.1   thorpej void
   1083   1.1   thorpej mpt_disable_ints(mpt_softc_t *mpt)
   1084   1.1   thorpej {
   1085   1.1   thorpej 	/* Mask all interrupts */
   1086   1.5     perry 	mpt_write(mpt, MPT_OFFSET_INTR_MASK,
   1087   1.1   thorpej 	    MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK);
   1088   1.1   thorpej }
   1089   1.1   thorpej 
   1090   1.1   thorpej /* (Re)Initialize the chip for use */
   1091   1.1   thorpej int
   1092   1.9      tron mpt_hw_init(mpt_softc_t *mpt)
   1093   1.9      tron {
   1094   1.9      tron 	u_int32_t	db;
   1095   1.9      tron 	int		try;
   1096   1.9      tron 
   1097   1.9      tron 	/*
   1098   1.9      tron 	 * Start by making sure we're not at FAULT or RESET state
   1099   1.9      tron 	 */
   1100   1.9      tron 	for (try = 0; try < MPT_MAX_TRYS; try++) {
   1101   1.9      tron 
   1102   1.9      tron 		db = mpt_rd_db(mpt);
   1103   1.9      tron 
   1104   1.9      tron 		switch (MPT_STATE(db)) {
   1105   1.9      tron 		case MPT_DB_STATE_READY:
   1106   1.9      tron 			return (0);
   1107   1.9      tron 
   1108   1.9      tron 		default:
   1109   1.9      tron 			/* if peer has already reset us, don't do it again! */
   1110   1.9      tron 			if (MPT_WHO(db) == MPT_DB_INIT_PCIPEER)
   1111   1.9      tron 				return (0);
   1112   1.9      tron 			/*FALLTHRU*/
   1113   1.9      tron 		case MPT_DB_STATE_RESET:
   1114   1.9      tron 		case MPT_DB_STATE_FAULT:
   1115   1.9      tron 			if (mpt_reset(mpt) != MPT_OK) {
   1116   1.9      tron 				DELAY(10000);
   1117   1.9      tron 				continue;
   1118   1.9      tron 			}
   1119   1.9      tron 			break;
   1120   1.9      tron 		}
   1121   1.9      tron 	}
   1122   1.9      tron 	return (EIO);
   1123   1.9      tron }
   1124   1.9      tron 
   1125   1.9      tron int
   1126   1.1   thorpej mpt_init(mpt_softc_t *mpt, u_int32_t who)
   1127   1.1   thorpej {
   1128   1.1   thorpej         int try;
   1129   1.1   thorpej         MSG_IOC_FACTS_REPLY facts;
   1130   1.1   thorpej         MSG_PORT_FACTS_REPLY pfp;
   1131  1.15       mrg         prop_dictionary_t dict;
   1132  1.15       mrg         uint32_t ini_id;
   1133  1.15       mrg         uint32_t pptr;
   1134   1.1   thorpej         int val;
   1135   1.1   thorpej 
   1136   1.1   thorpej 	/* Put all request buffers (back) on the free list */
   1137   1.1   thorpej         SLIST_INIT(&mpt->request_free_list);
   1138   1.1   thorpej 	for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) {
   1139   1.1   thorpej 		mpt_free_request(mpt, &mpt->request_pool[val]);
   1140   1.1   thorpej 	}
   1141   1.1   thorpej 
   1142   1.1   thorpej 	if (mpt->verbose > 1) {
   1143   1.1   thorpej 		mpt_prt(mpt, "doorbell req = %s",
   1144   1.1   thorpej 		    mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
   1145   1.1   thorpej 	}
   1146   1.1   thorpej 
   1147   1.1   thorpej 	/*
   1148   1.1   thorpej 	 * Start by making sure we're not at FAULT or RESET state
   1149   1.1   thorpej 	 */
   1150   1.9      tron 	if (mpt_hw_init(mpt) != 0)
   1151   1.9      tron 		return (EIO);
   1152   1.5     perry 
   1153  1.16    martin 	dict = device_properties(mpt->sc_dev);
   1154  1.15       mrg 
   1155   1.1   thorpej 	for (try = 0; try < MPT_MAX_TRYS; try++) {
   1156   1.1   thorpej 		/*
   1157   1.1   thorpej 		 * No need to reset if the IOC is already in the READY state.
   1158   1.1   thorpej 		 */
   1159   1.1   thorpej 
   1160   1.1   thorpej 		if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
   1161   1.1   thorpej 			mpt_prt(mpt, "mpt_get_iocfacts failed");
   1162   1.1   thorpej 			continue;
   1163   1.1   thorpej 		}
   1164  1.14       chs 		mpt2host_iocfacts_reply(&facts);
   1165   1.1   thorpej 
   1166   1.1   thorpej 		if (mpt->verbose > 1) {
   1167   1.1   thorpej 			mpt_prt(mpt,
   1168   1.1   thorpej 			    "IOCFACTS: GlobalCredits=%d BlockSize=%u "
   1169  1.14       chs 			    "Request Frame Size %u", facts.GlobalCredits,
   1170   1.1   thorpej 			    facts.BlockSize, facts.RequestFrameSize);
   1171   1.1   thorpej 		}
   1172   1.9      tron 		mpt->mpt_max_devices = facts.MaxDevices;
   1173   1.1   thorpej 		mpt->mpt_global_credits = facts.GlobalCredits;
   1174   1.1   thorpej 		mpt->request_frame_size = facts.RequestFrameSize;
   1175   1.1   thorpej 
   1176   1.1   thorpej 		if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
   1177   1.1   thorpej 			mpt_prt(mpt, "mpt_get_portfacts failed");
   1178   1.1   thorpej 			continue;
   1179   1.1   thorpej 		}
   1180  1.14       chs 		mpt2host_portfacts_reply(&pfp);
   1181   1.1   thorpej 
   1182   1.1   thorpej 		if (mpt->verbose > 1) {
   1183   1.1   thorpej 			mpt_prt(mpt,
   1184  1.14       chs 			    "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d",
   1185   1.1   thorpej 			    pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
   1186   1.1   thorpej 			    pfp.MaxDevices);
   1187   1.1   thorpej 		}
   1188   1.1   thorpej 
   1189   1.1   thorpej 		if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) {
   1190   1.1   thorpej 			mpt_prt(mpt, "initiator role unsupported");
   1191   1.1   thorpej 			return (ENXIO);
   1192   1.1   thorpej 		}
   1193   1.9      tron 
   1194   1.9      tron 		switch (pfp.PortType) {
   1195   1.9      tron 		case MPI_PORTFACTS_PORTTYPE_FC:
   1196   1.1   thorpej 			mpt->is_fc = 1;
   1197  1.10      tron 			mpt->mpt_max_devices = 255;
   1198   1.9      tron 			break;
   1199   1.9      tron 		case MPI_PORTFACTS_PORTTYPE_SCSI:
   1200   1.9      tron 			mpt->is_scsi = 1;
   1201   1.9      tron 			/* some SPI controllers (VMWare, Sun) lie */
   1202   1.9      tron 			mpt->mpt_max_devices = 16;
   1203   1.9      tron 			break;
   1204   1.9      tron 		case MPI_PORTFACTS_PORTTYPE_SAS:
   1205   1.9      tron 			mpt->is_sas = 1;
   1206   1.9      tron 			break;
   1207   1.9      tron 		default:
   1208   1.9      tron 			mpt_prt(mpt, "Unsupported Port Type (%x)",
   1209   1.9      tron 			    pfp.PortType);
   1210   1.9      tron 			return (ENXIO);
   1211   1.1   thorpej 		}
   1212   1.9      tron 
   1213  1.15       mrg 		if (!mpt->is_sas && !mpt->is_fc &&
   1214  1.15       mrg 		    prop_dictionary_get_uint32(dict, "scsi-initiator-id", &ini_id))
   1215  1.15       mrg 			mpt->mpt_ini_id = ini_id;
   1216  1.15       mrg 		else
   1217  1.15       mrg 			mpt->mpt_ini_id = pfp.PortSCSIID;
   1218   1.1   thorpej 
   1219   1.1   thorpej 		if (mpt_send_ioc_init(mpt, who) != MPT_OK) {
   1220   1.1   thorpej 			mpt_prt(mpt, "mpt_send_ioc_init failed");
   1221   1.1   thorpej 			continue;
   1222   1.1   thorpej 		}
   1223   1.1   thorpej 
   1224   1.1   thorpej 		if (mpt->verbose > 1) {
   1225   1.1   thorpej 			mpt_prt(mpt, "mpt_send_ioc_init ok");
   1226   1.1   thorpej 		}
   1227   1.1   thorpej 
   1228   1.1   thorpej 		if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) {
   1229   1.1   thorpej 			mpt_prt(mpt, "IOC failed to go to run state");
   1230   1.1   thorpej 			continue;
   1231   1.1   thorpej 		}
   1232   1.1   thorpej 		if (mpt->verbose > 1) {
   1233   1.1   thorpej 			mpt_prt(mpt, "IOC now at RUNSTATE");
   1234   1.1   thorpej 		}
   1235   1.1   thorpej 
   1236   1.1   thorpej 		/*
   1237   1.1   thorpej 		 * Give it reply buffers
   1238   1.1   thorpej 		 *
   1239   1.1   thorpej 		 * Do *not* except global credits.
   1240   1.1   thorpej 		 */
   1241   1.5     perry 		for (val = 0, pptr = mpt->reply_phys;
   1242   1.5     perry 		    (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
   1243   1.1   thorpej 		     pptr += MPT_REPLY_SIZE) {
   1244   1.1   thorpej 			mpt_free_reply(mpt, pptr);
   1245   1.1   thorpej 			if (++val == mpt->mpt_global_credits - 1)
   1246   1.1   thorpej 				break;
   1247   1.1   thorpej 		}
   1248   1.1   thorpej 
   1249   1.1   thorpej 		/*
   1250   1.1   thorpej 		 * Enable asynchronous event reporting
   1251   1.1   thorpej 		 */
   1252   1.1   thorpej 		mpt_send_event_request(mpt, 1);
   1253   1.1   thorpej 
   1254   1.1   thorpej 
   1255   1.1   thorpej 		/*
   1256   1.1   thorpej 		 * Read set up initial configuration information
   1257   1.1   thorpej 		 * (SPI only for now)
   1258   1.1   thorpej 		 */
   1259   1.1   thorpej 
   1260   1.9      tron 		if (mpt->is_scsi) {
   1261   1.1   thorpej 			if (mpt_read_config_info_spi(mpt)) {
   1262   1.1   thorpej 				return (EIO);
   1263   1.1   thorpej 			}
   1264   1.1   thorpej 			if (mpt_set_initial_config_spi(mpt)) {
   1265   1.1   thorpej 				return (EIO);
   1266   1.1   thorpej 			}
   1267   1.1   thorpej 		}
   1268   1.1   thorpej 
   1269   1.1   thorpej 		/*
   1270   1.1   thorpej 		 * Now enable the port
   1271   1.1   thorpej 		 */
   1272   1.1   thorpej 		if (mpt_send_port_enable(mpt, 0) != MPT_OK) {
   1273   1.1   thorpej 			mpt_prt(mpt, "failed to enable port 0");
   1274   1.1   thorpej 			continue;
   1275   1.1   thorpej 		}
   1276   1.1   thorpej 
   1277   1.1   thorpej 		if (mpt->verbose > 1) {
   1278   1.1   thorpej 			mpt_prt(mpt, "enabled port 0");
   1279   1.1   thorpej 		}
   1280   1.1   thorpej 
   1281   1.1   thorpej 		/* Everything worked */
   1282   1.1   thorpej 		break;
   1283   1.1   thorpej 	}
   1284   1.1   thorpej 
   1285   1.1   thorpej 	if (try >= MPT_MAX_TRYS) {
   1286   1.1   thorpej 		mpt_prt(mpt, "failed to initialize IOC");
   1287   1.1   thorpej 		return (EIO);
   1288   1.1   thorpej 	}
   1289   1.1   thorpej 
   1290   1.1   thorpej 	if (mpt->verbose > 1) {
   1291   1.1   thorpej 		mpt_prt(mpt, "enabling interrupts");
   1292   1.1   thorpej 	}
   1293   1.1   thorpej 
   1294   1.1   thorpej 	mpt_enable_ints(mpt);
   1295   1.1   thorpej 	return (0);
   1296   1.1   thorpej }
   1297  1.14       chs 
   1298  1.14       chs /*
   1299  1.14       chs  * Endian Conversion Functions- only used on Big Endian machines
   1300  1.14       chs  */
   1301  1.14       chs #if	_BYTE_ORDER == _BIG_ENDIAN
   1302  1.14       chs void
   1303  1.14       chs mpt2host_sge_simple_union(SGE_SIMPLE_UNION *sge)
   1304  1.14       chs {
   1305  1.14       chs 
   1306  1.14       chs 	MPT_2_HOST32(sge, FlagsLength);
   1307  1.14       chs 	MPT_2_HOST32(sge, _u.Address64.Low);
   1308  1.14       chs 	MPT_2_HOST32(sge, _u.Address64.High);
   1309  1.14       chs }
   1310  1.14       chs 
   1311  1.14       chs void
   1312  1.14       chs mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *rp)
   1313  1.14       chs {
   1314  1.14       chs 
   1315  1.14       chs 	MPT_2_HOST16(rp, MsgVersion);
   1316  1.14       chs #if 0
   1317  1.14       chs 	MPT_2_HOST16(rp, HeaderVersion);
   1318  1.14       chs #endif
   1319  1.14       chs 	MPT_2_HOST32(rp, MsgContext);
   1320  1.14       chs 	MPT_2_HOST16(rp, IOCExceptions);
   1321  1.14       chs 	MPT_2_HOST16(rp, IOCStatus);
   1322  1.14       chs 	MPT_2_HOST32(rp, IOCLogInfo);
   1323  1.14       chs 	MPT_2_HOST16(rp, ReplyQueueDepth);
   1324  1.14       chs 	MPT_2_HOST16(rp, RequestFrameSize);
   1325  1.14       chs 	MPT_2_HOST16(rp, Reserved_0101_FWVersion);
   1326  1.14       chs 	MPT_2_HOST16(rp, ProductID);
   1327  1.14       chs 	MPT_2_HOST32(rp, CurrentHostMfaHighAddr);
   1328  1.14       chs 	MPT_2_HOST16(rp, GlobalCredits);
   1329  1.14       chs 	MPT_2_HOST32(rp, CurrentSenseBufferHighAddr);
   1330  1.14       chs 	MPT_2_HOST16(rp, CurReplyFrameSize);
   1331  1.14       chs 	MPT_2_HOST32(rp, FWImageSize);
   1332  1.14       chs #if 0
   1333  1.14       chs 	MPT_2_HOST32(rp, IOCCapabilities);
   1334  1.14       chs #endif
   1335  1.14       chs 	MPT_2_HOST32(rp, FWVersion.Word);
   1336  1.14       chs #if 0
   1337  1.14       chs 	MPT_2_HOST16(rp, HighPriorityQueueDepth);
   1338  1.14       chs 	MPT_2_HOST16(rp, Reserved2);
   1339  1.14       chs 	mpt2host_sge_simple_union(&rp->HostPageBufferSGE);
   1340  1.14       chs 	MPT_2_HOST32(rp, ReplyFifoHostSignalingAddr);
   1341  1.14       chs #endif
   1342  1.14       chs }
   1343  1.14       chs 
   1344  1.14       chs void
   1345  1.14       chs mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *pfp)
   1346  1.14       chs {
   1347  1.14       chs 
   1348  1.14       chs 	MPT_2_HOST16(pfp, Reserved);
   1349  1.14       chs 	MPT_2_HOST16(pfp, Reserved1);
   1350  1.14       chs 	MPT_2_HOST32(pfp, MsgContext);
   1351  1.14       chs 	MPT_2_HOST16(pfp, Reserved2);
   1352  1.14       chs 	MPT_2_HOST16(pfp, IOCStatus);
   1353  1.14       chs 	MPT_2_HOST32(pfp, IOCLogInfo);
   1354  1.14       chs 	MPT_2_HOST16(pfp, MaxDevices);
   1355  1.14       chs 	MPT_2_HOST16(pfp, PortSCSIID);
   1356  1.14       chs 	MPT_2_HOST16(pfp, ProtocolFlags);
   1357  1.14       chs 	MPT_2_HOST16(pfp, MaxPostedCmdBuffers);
   1358  1.14       chs 	MPT_2_HOST16(pfp, MaxPersistentIDs);
   1359  1.14       chs 	MPT_2_HOST16(pfp, MaxLanBuckets);
   1360  1.14       chs 	MPT_2_HOST16(pfp, Reserved4);
   1361  1.14       chs 	MPT_2_HOST32(pfp, Reserved5);
   1362  1.14       chs }
   1363  1.14       chs 
   1364  1.14       chs void
   1365  1.14       chs mpt2host_config_page_scsi_port_0(fCONFIG_PAGE_SCSI_PORT_0 *sp0)
   1366  1.14       chs {
   1367  1.14       chs 
   1368  1.14       chs 	MPT_2_HOST32(sp0, Capabilities);
   1369  1.14       chs 	MPT_2_HOST32(sp0, PhysicalInterface);
   1370  1.14       chs }
   1371  1.14       chs 
   1372  1.14       chs void
   1373  1.14       chs mpt2host_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
   1374  1.14       chs {
   1375  1.14       chs 
   1376  1.14       chs 	MPT_2_HOST32(sp1, Configuration);
   1377  1.14       chs 	MPT_2_HOST32(sp1, OnBusTimerValue);
   1378  1.14       chs #if 0
   1379  1.14       chs 	MPT_2_HOST16(sp1, IDConfig);
   1380  1.14       chs #endif
   1381  1.14       chs }
   1382  1.14       chs 
   1383  1.14       chs void
   1384  1.14       chs host2mpt_config_page_scsi_port_1(fCONFIG_PAGE_SCSI_PORT_1 *sp1)
   1385  1.14       chs {
   1386  1.14       chs 
   1387  1.14       chs 	HOST_2_MPT32(sp1, Configuration);
   1388  1.14       chs 	HOST_2_MPT32(sp1, OnBusTimerValue);
   1389  1.14       chs #if 0
   1390  1.14       chs 	HOST_2_MPT16(sp1, IDConfig);
   1391  1.14       chs #endif
   1392  1.14       chs }
   1393  1.14       chs 
   1394  1.14       chs void
   1395  1.14       chs mpt2host_config_page_scsi_port_2(fCONFIG_PAGE_SCSI_PORT_2 *sp2)
   1396  1.14       chs {
   1397  1.14       chs 	int i;
   1398  1.14       chs 
   1399  1.14       chs 	MPT_2_HOST32(sp2, PortFlags);
   1400  1.14       chs 	MPT_2_HOST32(sp2, PortSettings);
   1401  1.14       chs 	for (i = 0; i < sizeof(sp2->DeviceSettings) /
   1402  1.14       chs 	    sizeof(*sp2->DeviceSettings); i++) {
   1403  1.14       chs 		MPT_2_HOST16(sp2, DeviceSettings[i].DeviceFlags);
   1404  1.14       chs 	}
   1405  1.14       chs }
   1406  1.14       chs 
   1407  1.14       chs void
   1408  1.14       chs mpt2host_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
   1409  1.14       chs {
   1410  1.14       chs 
   1411  1.14       chs 	MPT_2_HOST32(sd0, NegotiatedParameters);
   1412  1.14       chs 	MPT_2_HOST32(sd0, Information);
   1413  1.14       chs }
   1414  1.14       chs 
   1415  1.14       chs void
   1416  1.14       chs host2mpt_config_page_scsi_device_0(fCONFIG_PAGE_SCSI_DEVICE_0 *sd0)
   1417  1.14       chs {
   1418  1.14       chs 
   1419  1.14       chs 	HOST_2_MPT32(sd0, NegotiatedParameters);
   1420  1.14       chs 	HOST_2_MPT32(sd0, Information);
   1421  1.14       chs }
   1422  1.14       chs 
   1423  1.14       chs void
   1424  1.14       chs mpt2host_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
   1425  1.14       chs {
   1426  1.14       chs 
   1427  1.14       chs 	MPT_2_HOST32(sd1, RequestedParameters);
   1428  1.14       chs 	MPT_2_HOST32(sd1, Reserved);
   1429  1.14       chs 	MPT_2_HOST32(sd1, Configuration);
   1430  1.14       chs }
   1431  1.14       chs 
   1432  1.14       chs void
   1433  1.14       chs host2mpt_config_page_scsi_device_1(fCONFIG_PAGE_SCSI_DEVICE_1 *sd1)
   1434  1.14       chs {
   1435  1.14       chs 
   1436  1.14       chs 	HOST_2_MPT32(sd1, RequestedParameters);
   1437  1.14       chs 	HOST_2_MPT32(sd1, Reserved);
   1438  1.14       chs 	HOST_2_MPT32(sd1, Configuration);
   1439  1.14       chs }
   1440  1.14       chs 
   1441  1.14       chs void
   1442  1.14       chs mpt2host_config_page_fc_port_0(fCONFIG_PAGE_FC_PORT_0 *fp0)
   1443  1.14       chs {
   1444  1.14       chs 
   1445  1.14       chs 	MPT_2_HOST32(fp0, Flags);
   1446  1.14       chs 	MPT_2_HOST32(fp0, PortIdentifier);
   1447  1.14       chs 	MPT_2_HOST32(fp0, WWNN.Low);
   1448  1.14       chs 	MPT_2_HOST32(fp0, WWNN.High);
   1449  1.14       chs 	MPT_2_HOST32(fp0, WWPN.Low);
   1450  1.14       chs 	MPT_2_HOST32(fp0, WWPN.High);
   1451  1.14       chs 	MPT_2_HOST32(fp0, SupportedServiceClass);
   1452  1.14       chs 	MPT_2_HOST32(fp0, SupportedSpeeds);
   1453  1.14       chs 	MPT_2_HOST32(fp0, CurrentSpeed);
   1454  1.14       chs 	MPT_2_HOST32(fp0, MaxFrameSize);
   1455  1.14       chs 	MPT_2_HOST32(fp0, FabricWWNN.Low);
   1456  1.14       chs 	MPT_2_HOST32(fp0, FabricWWNN.High);
   1457  1.14       chs 	MPT_2_HOST32(fp0, FabricWWPN.Low);
   1458  1.14       chs 	MPT_2_HOST32(fp0, FabricWWPN.High);
   1459  1.14       chs 	MPT_2_HOST32(fp0, DiscoveredPortsCount);
   1460  1.14       chs 	MPT_2_HOST32(fp0, MaxInitiators);
   1461  1.14       chs }
   1462  1.14       chs 
   1463  1.14       chs void
   1464  1.14       chs mpt2host_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
   1465  1.14       chs {
   1466  1.14       chs 
   1467  1.14       chs 	MPT_2_HOST32(fp1, Flags);
   1468  1.14       chs 	MPT_2_HOST32(fp1, NoSEEPROMWWNN.Low);
   1469  1.14       chs 	MPT_2_HOST32(fp1, NoSEEPROMWWNN.High);
   1470  1.14       chs 	MPT_2_HOST32(fp1, NoSEEPROMWWPN.Low);
   1471  1.14       chs 	MPT_2_HOST32(fp1, NoSEEPROMWWPN.High);
   1472  1.14       chs }
   1473  1.14       chs 
   1474  1.14       chs void
   1475  1.14       chs host2mpt_config_page_fc_port_1(fCONFIG_PAGE_FC_PORT_1 *fp1)
   1476  1.14       chs {
   1477  1.14       chs 
   1478  1.14       chs 	HOST_2_MPT32(fp1, Flags);
   1479  1.14       chs 	HOST_2_MPT32(fp1, NoSEEPROMWWNN.Low);
   1480  1.14       chs 	HOST_2_MPT32(fp1, NoSEEPROMWWNN.High);
   1481  1.14       chs 	HOST_2_MPT32(fp1, NoSEEPROMWWPN.Low);
   1482  1.14       chs 	HOST_2_MPT32(fp1, NoSEEPROMWWPN.High);
   1483  1.14       chs }
   1484  1.14       chs 
   1485  1.14       chs void
   1486  1.14       chs mpt2host_config_page_raid_vol_0(fCONFIG_PAGE_RAID_VOL_0 *volp)
   1487  1.14       chs {
   1488  1.14       chs 	int i;
   1489  1.14       chs 
   1490  1.14       chs 	MPT_2_HOST16(volp, VolumeStatus.Reserved);
   1491  1.14       chs 	MPT_2_HOST16(volp, VolumeSettings.Settings);
   1492  1.14       chs 	MPT_2_HOST32(volp, MaxLBA);
   1493  1.14       chs #if 0
   1494  1.14       chs 	MPT_2_HOST32(volp, MaxLBAHigh);
   1495  1.14       chs #endif
   1496  1.14       chs 	MPT_2_HOST32(volp, StripeSize);
   1497  1.14       chs 	MPT_2_HOST32(volp, Reserved2);
   1498  1.14       chs 	MPT_2_HOST32(volp, Reserved3);
   1499  1.14       chs 	for (i = 0; i < MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX; i++) {
   1500  1.14       chs 		MPT_2_HOST16(volp, PhysDisk[i].Reserved);
   1501  1.14       chs 	}
   1502  1.14       chs }
   1503  1.14       chs 
   1504  1.14       chs void
   1505  1.14       chs mpt2host_config_page_raid_phys_disk_0(fCONFIG_PAGE_RAID_PHYS_DISK_0 *rpd0)
   1506  1.14       chs {
   1507  1.14       chs 
   1508  1.14       chs 	MPT_2_HOST32(rpd0, Reserved1);
   1509  1.14       chs 	MPT_2_HOST16(rpd0, PhysDiskStatus.Reserved);
   1510  1.14       chs 	MPT_2_HOST32(rpd0, MaxLBA);
   1511  1.14       chs 	MPT_2_HOST16(rpd0, ErrorData.Reserved);
   1512  1.14       chs 	MPT_2_HOST16(rpd0, ErrorData.ErrorCount);
   1513  1.14       chs 	MPT_2_HOST16(rpd0, ErrorData.SmartCount);
   1514  1.14       chs }
   1515  1.14       chs 
   1516  1.17  jmcneill void
   1517  1.17  jmcneill mpt2host_config_page_ioc_2(fCONFIG_PAGE_IOC_2 *ioc2)
   1518  1.17  jmcneill {
   1519  1.17  jmcneill 	MPT_2_HOST32(ioc2, CapabilitiesFlags);
   1520  1.17  jmcneill }
   1521  1.17  jmcneill 
   1522  1.14       chs #endif
   1523