diff options
Diffstat (limited to 'sys/dev/ic/mpt.c')
-rw-r--r-- | sys/dev/ic/mpt.c | 2018 |
1 files changed, 0 insertions, 2018 deletions
diff --git a/sys/dev/ic/mpt.c b/sys/dev/ic/mpt.c deleted file mode 100644 index a33a79425f0..00000000000 --- a/sys/dev/ic/mpt.c +++ /dev/null @@ -1,2018 +0,0 @@ -/* $OpenBSD: mpt.c,v 1.24 2006/02/11 01:20:43 krw Exp $ */ -/* $NetBSD: mpt.c,v 1.4 2003/11/02 11:07:45 wiz Exp $ */ - -/* - * Copyright (c) 2000, 2001 by Greg Ansley - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * Additional Copyright (c) 2002 by Matthew Jacob under same license. - */ - -/* - * mpt.c: - * - * Generic routines for LSI Fusion adapters. - * - * Adapted from the FreeBSD "mpt" driver by Jason R. Thorpe for - * Wasabi Systems, Inc. - */ - -#include <sys/cdefs.h> -/* __KERNEL_RCSID(0, "$NetBSD: mpt.c,v 1.4 2003/11/02 11:07:45 wiz Exp $"); */ - -#include <dev/ic/mpt.h> - -#define MPT_MAX_TRIES 3 -#define MPT_MAX_WAIT 300000 - -static int maxwait_ack = 0; -static int maxwait_int = 0; -static int maxwait_state = 0; - -#ifdef MPT_DEBUG -int mpt_debug = 11; -#endif /* MPT_DEBUG */ - -__inline u_int32_t mpt_rd_db(struct mpt_softc *); -__inline u_int32_t mpt_rd_intr(struct mpt_softc *); -int mpt_wait_db_ack(struct mpt_softc *); -int mpt_wait_db_int(struct mpt_softc *); -int mpt_wait_state(struct mpt_softc *, enum DB_STATE_BITS); -int mpt_get_iocfacts(struct mpt_softc *, MSG_IOC_FACTS_REPLY *); -int mpt_get_portfacts(struct mpt_softc *, MSG_PORT_FACTS_REPLY *); -int mpt_send_ioc_init(struct mpt_softc *, u_int32_t); -#ifdef MPT_DEBUG -void mpt_print_header(struct mpt_softc *, char *, CONFIG_PAGE_HEADER *); -#endif /* MPT_DEBUG */ -int mpt_read_config_info_mfg(struct mpt_softc *); -int mpt_read_config_info_iou(struct mpt_softc *); -int mpt_read_config_info_ioc(struct mpt_softc *); -int mpt_read_config_info_raid(struct mpt_softc *); -int mpt_read_config_info_spi(struct mpt_softc *); -int mpt_set_initial_config_spi(struct mpt_softc *); -int mpt_send_port_enable(struct mpt_softc *, int); -int mpt_send_event_request(struct mpt_softc *, int); - -__inline u_int32_t -mpt_rd_db(struct mpt_softc *mpt) -{ - return mpt_read(mpt, MPT_OFFSET_DOORBELL); -} - -__inline u_int32_t -mpt_rd_intr(struct mpt_softc *mpt) -{ - return mpt_read(mpt, MPT_OFFSET_INTR_STATUS); -} - -/* Busy wait for a door bell to be read by IOC */ -int -mpt_wait_db_ack(struct mpt_softc *mpt) -{ - int i; - for (i=0; i < MPT_MAX_WAIT; i++) { - if (!MPT_DB_IS_BUSY(mpt_rd_intr(mpt))) { - maxwait_ack = i > maxwait_ack ? i : maxwait_ack; - return MPT_OK; - } - - DELAY(100); - } - return MPT_FAIL; -} - -/* Busy wait for a door bell interrupt */ -int -mpt_wait_db_int(struct mpt_softc *mpt) -{ - int i; - for (i=0; i < MPT_MAX_WAIT; i++) { - if (MPT_DB_INTR(mpt_rd_intr(mpt))) { - maxwait_int = i > maxwait_int ? i : maxwait_int; - return MPT_OK; - } - DELAY(100); - } - return MPT_FAIL; -} - -/* Wait for IOC to transition to a give state */ -void -mpt_check_doorbell(struct mpt_softc *mpt) -{ - u_int32_t db = mpt_rd_db(mpt); - - /* prepare this function for error path */ - /* if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) { */ - switch (MPT_STATE(db)) { - case MPT_DB_STATE_FAULT: - case MPT_DB_STATE_READY: - /* 1030 needs reset, issue IOC_INIT */ - /* FIXME */ - if (mpt_init(mpt, MPT_DB_INIT_HOST) != 0) - panic("%s: Can't get MPT IOC operational", - mpt->mpt_dev.dv_xname); - break; - - default: - /* nothing done for now */ - break; - } -} - -/* Wait for IOC to transition to a give state */ -int -mpt_wait_state(struct mpt_softc *mpt, enum DB_STATE_BITS state) -{ - int i; - - for (i = 0; i < MPT_MAX_WAIT; i++) { - u_int32_t db = mpt_rd_db(mpt); - if (MPT_STATE(db) == state) { - maxwait_state = i > maxwait_state ? i : maxwait_state; - return (MPT_OK); - } - DELAY(100); - } - return (MPT_FAIL); -} - - -/* Issue the reset COMMAND to the IOC */ -int -mpt_soft_reset(struct mpt_softc *mpt) -{ - DNPRINTF(10, "soft reset\n"); - - /* Have to use hard reset if we are not in Running state */ - if (MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_RUNNING) { - mpt_prt(mpt, "soft reset failed: device not running"); - return MPT_FAIL; - } - - /* If door bell is in use we don't have a chance of getting - * a word in since the IOC probably crashed in message - * processing. So don't waste our time. - */ - if (MPT_DB_IS_IN_USE(mpt_rd_db(mpt))) { - mpt_prt(mpt, "soft reset failed: doorbell wedged"); - return MPT_FAIL; - } - - /* Send the reset request to the IOC */ - mpt_write(mpt, MPT_OFFSET_DOORBELL, - MPI_FUNCTION_IOC_MESSAGE_UNIT_RESET << MPI_DOORBELL_FUNCTION_SHIFT); - if (mpt_wait_db_ack(mpt) != MPT_OK) { - mpt_prt(mpt, "soft reset failed: ack timeout"); - return MPT_FAIL; - } - - /* Wait for the IOC to reload and come out of reset state */ - if (mpt_wait_state(mpt, MPT_DB_STATE_READY) != MPT_OK) { - mpt_prt(mpt, "soft reset failed: device did not start running"); - return MPT_FAIL; - } - - return MPT_OK; -} - -/* This is a magic diagnostic reset that resets all the ARM - * processors in the chip. - */ -void -mpt_hard_reset(struct mpt_softc *mpt) -{ - u_int32_t diag0; - int count; - - /* This extra read comes for the Linux source - * released by LSI. It's function is undocumented! - */ - DNPRINTF(10, "hard reset\n"); - mpt_read(mpt, MPT_OFFSET_FUBAR); - - /* Enable diagnostic registers */ - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5); - - /* Diag. port is now active so we can now hit the reset bit */ - mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, MPT_DIAG_RESET_IOC); - - DELAY(10000); - - /* Disable Diagnostic Register */ - mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF); - - /* Restore the config register values */ - /* Hard resets are known to screw up the BAR for diagnostic - memory accesses (Mem1). */ - mpt_set_config_regs(mpt); - if (mpt->mpt2 != NULL) { - mpt_set_config_regs(mpt->mpt2); - } - - /* Note that if there is no valid firmware to run, the doorbell will - remain in the reset state (0x00000000) */ - - /* try to download firmware, if available */ - if (mpt->fw) { - /* wait for the adapter to finish the reset */ - for (count = 0; count < 30; count++) { - diag0 = mpt_read(mpt, MPI_DIAGNOSTIC_OFFSET); - mpt_prt(mpt, "diag0=%08x", diag0); - if (!(diag0 & MPI_DIAG_RESET_ADAPTER)) { - break; - } - - /* wait 1 second */ - DELAY(1000); - } - count = mpt_downloadboot(mpt); - if (count < 0) { - panic("firmware downloadboot failure (%d)!", count); - } - } -} - -/* - * Reset the IOC when needed. Try software command first then if needed - * poke at the magic diagnostic reset. Note that a hard reset resets - * *both* IOCs on dual function chips (FC929 && LSI1030) as well as - * fouls up the PCI configuration registers. - */ -int -mpt_reset(struct mpt_softc *mpt) -{ - int ret; - - /* Try a soft reset */ - if ((ret = mpt_soft_reset(mpt)) != MPT_OK) { - /* Failed; do a hard reset */ - mpt_hard_reset(mpt); - - /* Wait for the IOC to reload and come out of reset state */ - ret = mpt_wait_state(mpt, MPT_DB_STATE_READY); - if (ret != MPT_OK) { - mpt_prt(mpt, "failed to reset device"); - } - } - - return ret; -} - -/* Return a command buffer to the free queue */ -void -mpt_free_request(struct mpt_softc *mpt, struct req_entry *req) -{ - if (req == NULL || req != &mpt->request_pool[req->index]) { - panic("mpt_free_request bad req ptr"); - return; - } - if (req->debug == REQ_FREE) { - /* - * XXX MU this should not happen but do not corrupt the free - * list if it does - */ - mpt_prt(mpt, "request %d already free", req->index); - return; - } - req->sequence = 0; - req->xfer = NULL; - req->debug = REQ_FREE; - SLIST_INSERT_HEAD(&mpt->request_free_list, req, link); -} - -/* Initialize command buffer */ -void -mpt_init_request(struct mpt_softc *mpt, struct req_entry *req) -{ - if (req == NULL || req != &mpt->request_pool[req->index]) { - panic("mpt_init_request bad req ptr"); - return; - } - req->sequence = 0; - req->xfer = NULL; - req->debug = REQ_FREE; - SLIST_INSERT_HEAD(&mpt->request_free_list, req, link); -} -/* Get a command buffer from the free queue */ -struct req_entry * -mpt_get_request(struct mpt_softc *mpt) -{ - struct req_entry *req; - req = SLIST_FIRST(&mpt->request_free_list); - if (req != NULL) { - if (req != &mpt->request_pool[req->index]) { - panic("mpt_get_request: corrupted request free list"); - } - if (req->xfer != NULL) { - panic("mpt_get_request: corrupted request free list " - "(xfer)"); - } - SLIST_REMOVE_HEAD(&mpt->request_free_list, link); - req->debug = REQ_IN_PROGRESS; - } - return req; -} - -/* Pass the command to the IOC */ -void -mpt_send_cmd(struct mpt_softc *mpt, struct req_entry *req) -{ -#ifdef MPT_DEBUG - u_int32_t *pReq = req->req_vbuf; - - DNPRINTF(50, "%s: Send Request %d (0x%x):\n", - DEVNAME(mpt), req->index, req->req_pbuf); - DNPRINTF(50, "%s: %08x %08x %08x %08x\n", - DEVNAME(mpt), pReq[0], pReq[1], pReq[2], pReq[3]); - DNPRINTF(50, "%s: %08x %08x %08x %08x\n", - DEVNAME(mpt), pReq[4], pReq[5], pReq[6], pReq[7]); - DNPRINTF(50, "%s: %08x %08x %08x %08x\n", - DEVNAME(mpt), pReq[8], pReq[9], pReq[10], pReq[11]); - DNPRINTF(50, "%s: %08x %08x %08x %08x\n", - DEVNAME(mpt), pReq[12], pReq[13], pReq[14], pReq[15]); -#endif /* MPT_DEBUG */ - - req->sequence = mpt->sequence++; - MPT_SYNC_REQ(mpt, req, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); - - req->debug = REQ_ON_CHIP; - mpt_write(mpt, MPT_OFFSET_REQUEST_Q, (u_int32_t) req->req_pbuf); -} - -/* - * Give the reply buffer back to the IOC after we have - * finished processing it. - */ -void -mpt_free_reply(struct mpt_softc *mpt, u_int32_t ptr) -{ - mpt_write(mpt, MPT_OFFSET_REPLY_Q, ptr); -} - -/* Get a reply from the IOC */ -u_int32_t -mpt_pop_reply_queue(struct mpt_softc *mpt) -{ - return mpt_read(mpt, MPT_OFFSET_REPLY_Q); -} - -/* - * Send a command to the IOC via the handshake register. - * - * Only done at initialization time and for certain unusual - * commands such as device/bus reset as specified by LSI. - */ -int -mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd) -{ - int i; - u_int32_t data, *data32; - - /* Check condition of the IOC */ - data = mpt_rd_db(mpt); - if (((MPT_STATE(data) != MPT_DB_STATE_READY) && - (MPT_STATE(data) != MPT_DB_STATE_RUNNING) && - (MPT_STATE(data) != MPT_DB_STATE_FAULT)) || - (MPT_DB_IS_IN_USE(data))) { - mpt_prt(mpt, "handshake aborted due to invalid doorbell state"); -#ifdef MPT_DEBUG - mpt_print_db(data); -#endif /* MPT_DEBUG */ - return(EBUSY); - } - - /* We move things in 32 bit chunks */ - len = (len + 3) >> 2; - data32 = cmd; - - /* Clear any left over pending doorbell interrupts */ - if (MPT_DB_INTR(mpt_rd_intr(mpt))) - mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); - - /* - * Tell the handshake reg. we are going to send a command - * and how long it is going to be. - */ - data = (MPI_FUNCTION_HANDSHAKE << MPI_DOORBELL_FUNCTION_SHIFT) | - (len << MPI_DOORBELL_ADD_DWORDS_SHIFT); - mpt_write(mpt, MPT_OFFSET_DOORBELL, data); - - /* Wait for the chip to notice */ - if (mpt_wait_db_int(mpt) != MPT_OK) { - mpt_prt(mpt, "mpt_send_handshake_cmd timeout1"); - return ETIMEDOUT; - } - - /* Clear the interrupt */ - mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); - - if (mpt_wait_db_ack(mpt) != MPT_OK) { - mpt_prt(mpt, "mpt_send_handshake_cmd timeout2"); - return ETIMEDOUT; - } - - /* Send the command */ - for (i = 0; i < len; i++) { - mpt_write(mpt, MPT_OFFSET_DOORBELL, *data32++); - if (mpt_wait_db_ack(mpt) != MPT_OK) { - mpt_prt(mpt, - "mpt_send_handshake_cmd timeout! index = %d", i); - return ETIMEDOUT; - } - } - return MPT_OK; -} - -/* Get the response from the handshake register */ -int -mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply) -{ - int left, reply_left; - u_int16_t *data16; - MSG_DEFAULT_REPLY *hdr; - - /* We move things out in 16 bit chunks */ - reply_len >>= 1; - data16 = (u_int16_t *)reply; - - hdr = (MSG_DEFAULT_REPLY *)reply; - - /* Get first word */ - if (mpt_wait_db_int(mpt) != MPT_OK) { - mpt_prt(mpt, "mpt_recv_handshake_cmd timeout1"); - return ETIMEDOUT; - } - *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK; - mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); - - /* Get Second Word */ - if (mpt_wait_db_int(mpt) != MPT_OK) { - mpt_prt(mpt, "mpt_recv_handshake_cmd timeout2"); - return ETIMEDOUT; - } - *data16++ = mpt_read(mpt, MPT_OFFSET_DOORBELL) & MPT_DB_DATA_MASK; - mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); - -#ifdef MPT_DEBUG - /* With the second word, we can now look at the length */ - if ((reply_len >> 1) != hdr->MsgLength) - /* XXX don't remove brackets! */ - DNPRINTF(50, "%s: reply length does not match message length: " - "got 0x%02x, expected 0x%02x\n", - DEVNAME(mpt), hdr->MsgLength << 2, reply_len << 1); -#endif /* MPT_DEBUG */ - - /* Get rest of the reply; but don't overflow the provided buffer */ - left = (hdr->MsgLength << 1) - 2; - reply_left = reply_len - 2; - while (left--) { - u_int16_t datum; - - if (mpt_wait_db_int(mpt) != MPT_OK) { - mpt_prt(mpt, "mpt_recv_handshake_cmd timeout3"); - return ETIMEDOUT; - } - datum = mpt_read(mpt, MPT_OFFSET_DOORBELL); - - if (reply_left-- > 0) - *data16++ = datum & MPT_DB_DATA_MASK; - - mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); - } - - /* One more wait & clear at the end */ - if (mpt_wait_db_int(mpt) != MPT_OK) { - mpt_prt(mpt, "mpt_recv_handshake_cmd timeout4"); - return ETIMEDOUT; - } - mpt_write(mpt, MPT_OFFSET_INTR_STATUS, 0); - - if ((hdr->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { -#ifdef MPT_DEBUG - if (mpt_debug > 50) - mpt_print_reply(hdr); -#endif - return (MPT_FAIL | hdr->IOCStatus); - } - - return (0); -} - -int -mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp) -{ - MSG_IOC_FACTS f_req; - int error; - - bzero(&f_req, sizeof f_req); - f_req.Function = MPI_FUNCTION_IOC_FACTS; - f_req.MsgContext = 0x12071942; - error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req); - if (error) - return(error); - error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp); - return (error); -} - -int -mpt_get_portfacts(struct mpt_softc *mpt, MSG_PORT_FACTS_REPLY *freplp) -{ - MSG_PORT_FACTS f_req; - int error; - - /* XXX: Only getting PORT FACTS for Port 0 */ - bzero(&f_req, sizeof f_req); - f_req.Function = MPI_FUNCTION_PORT_FACTS; - f_req.MsgContext = 0x12071943; - error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req); - if (error) - return(error); - error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp); - return (error); -} - -/* - * Send the initialization request. This is where we specify how many - * SCSI busses and how many devices per bus we wish to emulate. - * This is also the command that specifies the max size of the reply - * frames from the IOC that we will be allocating. - */ -int -mpt_send_ioc_init(struct mpt_softc *mpt, u_int32_t who) -{ - int error = 0; - MSG_IOC_INIT init; - MSG_IOC_INIT_REPLY reply; - - bzero(&init, sizeof init); - init.WhoInit = who; - init.Function = MPI_FUNCTION_IOC_INIT; - if (mpt->is_fc) { - init.MaxDevices = 255; - } else { - init.MaxDevices = 16; - } - init.MaxBuses = 1; - init.ReplyFrameSize = MPT_REPLY_SIZE; - init.MsgContext = 0x12071941; - - /* - * If we are in a recovery mode and we uploaded the FW image, - * then the fw pointer is not NULL. Skip the upload a second time - * Set this flag if fw set for IOC. - */ - mpt->upload_fw = 0; - - if (mpt->fw_download_boot) { - if (mpt->fw) { - init.Flags = MPI_IOCINIT_FLAGS_DISCARD_FW_IMAGE; - } - else { - mpt->upload_fw = 1; - } - } - - DNPRINTF(10, "%s: flags %d, upload_fw %d\n", DEVNAME(mpt), init.Flags, - mpt->upload_fw); - - if ((error = mpt_send_handshake_cmd(mpt, sizeof init, &init)) != 0) { - return(error); - } - - error = mpt_recv_handshake_reply(mpt, sizeof reply, &reply); - return (error); -} - - -/* - * Utiltity routine to read configuration headers and pages - */ - -int -mpt_read_cfg_header(struct mpt_softc *mpt, int PageType, int PageNumber, - int PageAddress, CONFIG_PAGE_HEADER *rslt) -{ - int count; - struct req_entry *req; - MSG_CONFIG *cfgp; - MSG_CONFIG_REPLY *reply; - - req = mpt_get_request(mpt); - - cfgp = req->req_vbuf; - bzero(cfgp, sizeof *cfgp); - - cfgp->Action = MPI_CONFIG_ACTION_PAGE_HEADER; - cfgp->Function = MPI_FUNCTION_CONFIG; - cfgp->Header.PageNumber = (U8) PageNumber; - cfgp->Header.PageType = (U8) PageType; - cfgp->PageAddress = PageAddress; - MPI_pSGE_SET_FLAGS(((SGE_SIMPLE32 *) &cfgp->PageBufferSGE), - (MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | - MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST)); - cfgp->MsgContext = req->index | 0x80000000; - - mpt_check_doorbell(mpt); - mpt_send_cmd(mpt, req); - count = 0; - do { - DELAY(500); - mpt_intr(mpt); - if (++count == 1000) { - mpt_prt(mpt, "read_cfg_header timed out"); - return (-1); - } - } while (req->debug == REQ_ON_CHIP); - - reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence); - if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { - mpt_prt(mpt, "mpt_read_cfg_header: Config Info Status %x", - reply->IOCStatus); - mpt_free_reply(mpt, (req->sequence << 1)); - return (-1); - } - bcopy(&reply->Header, rslt, sizeof (CONFIG_PAGE_HEADER)); - mpt_free_reply(mpt, (req->sequence << 1)); - mpt_free_request(mpt, req); - return (0); -} - -#define CFG_DATA_OFF 128 - -int -mpt_read_cfg_page(struct mpt_softc *mpt, int PageAddress, CONFIG_PAGE_HEADER *hdr) -{ - int count; - struct req_entry *req; - SGE_SIMPLE32 *se; - MSG_CONFIG *cfgp; - size_t amt; - MSG_CONFIG_REPLY *reply; - - req = mpt_get_request(mpt); - - cfgp = req->req_vbuf; - bzero(cfgp, MPT_REQUEST_AREA); - cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; - cfgp->Function = MPI_FUNCTION_CONFIG; - cfgp->Header = *hdr; - amt = (cfgp->Header.PageLength * sizeof (u_int32_t)); - cfgp->Header.PageType &= MPI_CONFIG_PAGETYPE_MASK; - cfgp->PageAddress = PageAddress; - se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE; - se->Address = req->req_pbuf + CFG_DATA_OFF; - MPI_pSGE_SET_LENGTH(se, amt); - MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | - MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | - MPI_SGE_FLAGS_END_OF_LIST)); - - cfgp->MsgContext = req->index | 0x80000000; - - mpt_check_doorbell(mpt); - mpt_send_cmd(mpt, req); - count = 0; - do { - DELAY(500); - mpt_intr(mpt); - if (++count == 1000) { - mpt_prt(mpt, "read_cfg_page timed out"); - return (-1); - } - } while (req->debug == REQ_ON_CHIP); - - reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence); - if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { - mpt_prt(mpt, "mpt_read_cfg_page: Config Info Status %x", - reply->IOCStatus); - mpt_free_reply(mpt, (req->sequence << 1)); - return (-1); - } - mpt_free_reply(mpt, (req->sequence << 1)); -#if 0 /* XXXJRT */ - bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap, - BUS_DMASYNC_POSTREAD); -#endif - if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && - cfgp->Header.PageNumber == 0) { - amt = sizeof (CONFIG_PAGE_SCSI_PORT_0); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && - cfgp->Header.PageNumber == 1) { - amt = sizeof (CONFIG_PAGE_SCSI_PORT_1); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && - cfgp->Header.PageNumber == 2) { - amt = sizeof (CONFIG_PAGE_SCSI_PORT_2); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && - cfgp->Header.PageNumber == 0) { - amt = sizeof (CONFIG_PAGE_SCSI_DEVICE_0); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && - cfgp->Header.PageNumber == 1) { - amt = sizeof (CONFIG_PAGE_SCSI_DEVICE_1); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_MANUFACTURING && - cfgp->Header.PageNumber == 0) { - amt = sizeof (CONFIG_PAGE_MANUFACTURING_0); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_IOC && - cfgp->Header.PageNumber == 2) { - amt = sizeof (CONFIG_PAGE_IOC_2); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_RAID_VOLUME && - cfgp->Header.PageNumber == 0) { - amt = sizeof (CONFIG_PAGE_RAID_VOL_0); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_RAID_PHYSDISK && - cfgp->Header.PageNumber == 0) { - amt = sizeof (CONFIG_PAGE_RAID_PHYS_DISK_0); - } - - bcopy(((caddr_t)req->req_vbuf)+CFG_DATA_OFF, hdr, amt); - mpt_free_request(mpt, req); - return (0); -} - -int -mpt_write_cfg_page(struct mpt_softc *mpt, int PageAddress, CONFIG_PAGE_HEADER *hdr) -{ - int count, hdr_attr; - struct req_entry *req; - SGE_SIMPLE32 *se; - MSG_CONFIG *cfgp; - size_t amt; - MSG_CONFIG_REPLY *reply; - - req = mpt_get_request(mpt); - - cfgp = req->req_vbuf; - bzero(cfgp, sizeof *cfgp); - - hdr_attr = hdr->PageType & MPI_CONFIG_PAGEATTR_MASK; - if (hdr_attr != MPI_CONFIG_PAGEATTR_CHANGEABLE && - hdr_attr != MPI_CONFIG_PAGEATTR_PERSISTENT) { - mpt_prt(mpt, "page type 0x%x not changeable", - hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); - return (-1); - } - hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK; - - cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; - cfgp->Function = MPI_FUNCTION_CONFIG; - cfgp->Header = *hdr; - amt = (cfgp->Header.PageLength * sizeof (u_int32_t)); - cfgp->PageAddress = PageAddress; - - se = (SGE_SIMPLE32 *) &cfgp->PageBufferSGE; - se->Address = req->req_pbuf + CFG_DATA_OFF; - MPI_pSGE_SET_LENGTH(se, amt); - MPI_pSGE_SET_FLAGS(se, (MPI_SGE_FLAGS_SIMPLE_ELEMENT | - MPI_SGE_FLAGS_LAST_ELEMENT | MPI_SGE_FLAGS_END_OF_BUFFER | - MPI_SGE_FLAGS_END_OF_LIST | MPI_SGE_FLAGS_HOST_TO_IOC)); - - cfgp->MsgContext = req->index | 0x80000000; - - if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && - cfgp->Header.PageNumber == 0) { - amt = sizeof (CONFIG_PAGE_SCSI_PORT_0); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && - cfgp->Header.PageNumber == 1) { - amt = sizeof (CONFIG_PAGE_SCSI_PORT_1); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && - cfgp->Header.PageNumber == 2) { - amt = sizeof (CONFIG_PAGE_SCSI_PORT_2); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && - cfgp->Header.PageNumber == 0) { - amt = sizeof (CONFIG_PAGE_SCSI_DEVICE_0); - } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && - cfgp->Header.PageNumber == 1) { - amt = sizeof (CONFIG_PAGE_SCSI_DEVICE_1); - } - bcopy(hdr, ((caddr_t)req->req_vbuf)+CFG_DATA_OFF, amt); - /* Restore stripped out attributes */ - hdr->PageType |= hdr_attr; - - mpt_check_doorbell(mpt); - mpt_send_cmd(mpt, req); - count = 0; - do { - DELAY(500); - mpt_intr(mpt); - if (++count == 1000) { - hdr->PageType |= hdr_attr; - mpt_prt(mpt, "mpt_write_cfg_page timed out"); - return (-1); - } - } while (req->debug == REQ_ON_CHIP); - - reply = (MSG_CONFIG_REPLY *) MPT_REPLY_PTOV(mpt, req->sequence); - if ((reply->IOCStatus & MPI_IOCSTATUS_MASK) != MPI_IOCSTATUS_SUCCESS) { - mpt_prt(mpt, "mpt_write_cfg_page: Config Info Status %x", - reply->IOCStatus); - mpt_free_reply(mpt, (req->sequence << 1)); - return (-1); - } - mpt_free_reply(mpt, (req->sequence << 1)); - - mpt_free_request(mpt, req); - return (0); -} - -#ifdef MPT_DEBUG -void -mpt_print_header(struct mpt_softc *mpt, char *s, CONFIG_PAGE_HEADER *phdr) -{ - DNPRINTF(10,"%s: %s %x: %x %x %x %x\n", - DEVNAME(mpt), - s, - phdr->PageNumber, - phdr->PageType, - phdr->PageNumber, - phdr->PageLength, - phdr->PageVersion); -} -#endif /* MPT_DEBUG */ - -/* - * Read manufacturing configuration information - */ -int -mpt_read_config_info_mfg(struct mpt_softc *mpt) -{ - int rv, i; - CONFIG_PAGE_HEADER *phdr[5] = { - phdr[0] = &mpt->mpt_mfg_page0.Header, - phdr[1] = &mpt->mpt_mfg_page1.Header, - phdr[2] = &mpt->mpt_mfg_page2.Header, - phdr[3] = &mpt->mpt_mfg_page3.Header, - phdr[4] = &mpt->mpt_mfg_page4.Header - }; - - for (i = 0; i < 5 /* 5 pages total */; i++) { - /* retrieve MFG headers */ - rv = mpt_read_cfg_header(mpt, - MPI_CONFIG_PAGETYPE_MANUFACTURING, i, 0, phdr[i]); - if (rv) { - mpt_prt(mpt, "Could not retrieve Manufacturing Page " - "%i Header.", i); - return (-1); - } -#ifdef MPT_DEBUG - mpt_print_header(mpt, "Manufacturing Header Page", phdr[i]); -#endif /* MPT_DEBUG */ - - /* retrieve MFG config pages using retrieved headers */ - rv = mpt_read_cfg_page(mpt, i, phdr[i]); - if (rv) { - mpt_prt(mpt, "Could not retrieve manufacturing Page" - " %i", i); - return (-1); - } - } - -#ifdef MPT_DEBUG - if (mpt_debug > 10) { - mpt_prt(mpt, "Manufacturing Page 0 data: %s %s %s %s %s", - mpt->mpt_mfg_page0.ChipName, - mpt->mpt_mfg_page0.ChipRevision, - mpt->mpt_mfg_page0.BoardName, - mpt->mpt_mfg_page0.BoardAssembly, - mpt->mpt_mfg_page0.BoardTracerNumber); - - mpt_prt(mpt, "Manufacturing Page 1 data:"); - for (i = 0; - i < ((mpt->mpt_mfg_page1.Header.PageLength - 1)<< 2); i++) { - printf("%02x ", mpt->mpt_mfg_page1.VPD[i]); - } - printf("\n"); - - mpt_prt(mpt, "Manufacturing Page 2 data: %x %x", - mpt->mpt_mfg_page2.ChipId.PCIRevisionID, - mpt->mpt_mfg_page2.ChipId.DeviceID); - for (i = 0; - i < (mpt->mpt_mfg_page2.Header.PageLength - 2); i++) { - printf("%08x ", mpt->mpt_mfg_page2.HwSettings[i]); - } - printf("\n"); - - mpt_prt(mpt, "Manufacturing Page 3 data: %x %x", - mpt->mpt_mfg_page3.ChipId.PCIRevisionID, - mpt->mpt_mfg_page3.ChipId.DeviceID); - for (i = 0; - i < (mpt->mpt_mfg_page3.Header.PageLength - 2); i++) { - printf("%08x ", mpt->mpt_mfg_page3.Info[i]); - } - printf("\n"); - - mpt_prt(mpt, "Manufacturing Page 4 data: %x %x %x %x %x", - mpt->mpt_mfg_page4.InfoSize1, - mpt->mpt_mfg_page4.InfoOffset1, - mpt->mpt_mfg_page4.InfoSize0, - mpt->mpt_mfg_page4.InfoOffset0, - mpt->mpt_mfg_page4.InquirySize, - mpt->mpt_mfg_page4.ISVolumeSettings, - mpt->mpt_mfg_page4.IMEVolumeSettings, - mpt->mpt_mfg_page4.IMVolumeSettings); - for (i = 0; i < sizeof(mpt->mpt_mfg_page4.InquiryData); i++) { - printf("%02x ", mpt->mpt_mfg_page4.InquiryData[i]); - } - printf("\n"); - } -#endif /* MPT_DEBUG */ - - return (0); -} - -/* - * Read IO Unit configuration information - */ -int -mpt_read_config_info_iou(struct mpt_softc *mpt) -{ - int rv, i; - - CONFIG_PAGE_HEADER *phdr[4] = { - phdr[0] = &mpt->mpt_iou_page0.Header, - phdr[1] = &mpt->mpt_iou_page1.Header, - phdr[2] = &mpt->mpt_iou_page2.Header, - phdr[3] = &mpt->mpt_iou_page2.Header, - }; - - for (i = 0; i < 4 /* 4 pages total */; i++) { - /* retrieve IO Unit headers */ - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_IO_UNIT, i, - 0, phdr[i]); - if (rv) { - mpt_prt(mpt, "Could not retrieve IO Unit Page %i " - "header.", i); - return (-1); - } -#ifdef MPT_DEBUG - mpt_print_header(mpt, "IO Unit Header Page", phdr[i]); -#endif /* MPT_DEBUG */ - - /* retrieve IO Unit config pages using retrieved headers */ - rv = mpt_read_cfg_page(mpt, i, phdr[i]); - if (rv) { - mpt_prt(mpt, "Could not retrieve IO Unit Page %i", i); - return (-1); - } - - if (i == 0 && - mpt->mpt_iou_page0.UniqueValue.High == 0xdeadbeef && - mpt->mpt_iou_page0.UniqueValue.Low == 0xdeadbeef) - { - /* vmware returns a lot of dead beef in page 0 */ - mpt->vmware = 1; - } - } - - DNPRINTF(10, "%s: IO Unit Page 0 data: %llx\n", - DEVNAME(mpt), - mpt->mpt_iou_page0.UniqueValue); - DNPRINTF(10, "%s: IO Unit Page 1 data: %x\n", - DEVNAME(mpt), - mpt->mpt_iou_page1.Flags); - DNPRINTF(10, "%s: IO Unit Page 2 data: %x %x %x %x %x %x\n", - DEVNAME(mpt), - mpt->mpt_iou_page2.Flags, - mpt->mpt_iou_page2.BiosVersion, - mpt->mpt_iou_page2.AdapterOrder[0], - mpt->mpt_iou_page2.AdapterOrder[1], - mpt->mpt_iou_page2.AdapterOrder[2], - mpt->mpt_iou_page2.AdapterOrder[3]); - - return (0); -} - -/* - * Read IOC configuration information - */ -int -mpt_read_config_info_ioc(struct mpt_softc *mpt) -{ - int rv, i; - CONFIG_PAGE_HEADER *phdr[5] = { - phdr[0] = &mpt->mpt_ioc_page0.Header, - phdr[1] = &mpt->mpt_ioc_page1.Header, - phdr[2] = &mpt->mpt_ioc_page2.Header, - phdr[3] = &mpt->mpt_ioc_page3.Header, - phdr[4] = &mpt->mpt_ioc_page4.Header - }; - - for (i = 0; i < 5 /* 5 pages total */; i++) { - /* retrieve IOC headers */ - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_IOC, i, - 0, phdr[i]); - if (rv) { - mpt_prt(mpt, "Could not retrieve IOC Page %i header.", - i); - return (-1); - } -#ifdef MPT_DEBUG - mpt_print_header(mpt, "IOC Header Page", phdr[i]); -#endif /* MPT_DEBUG */ - - /* retrieve IOC config pages using retrieved headers */ - rv = mpt_read_cfg_page(mpt, i, phdr[i]); - if (rv) { - mpt_prt(mpt, "Could not retrieve IOC Page %i", i); - return (-1); - } - } - -#ifdef MPT_DEBUG - if (mpt_debug > 10) { - mpt_prt(mpt, "IOC Page 0 data: %x %x %x %x %x %x %x %x", - mpt->mpt_ioc_page0.TotalNVStore, - mpt->mpt_ioc_page0.FreeNVStore, - mpt->mpt_ioc_page0.DeviceID, - mpt->mpt_ioc_page0.VendorID, - mpt->mpt_ioc_page0.RevisionID, - mpt->mpt_ioc_page0.ClassCode, - mpt->mpt_ioc_page0.SubsystemID, - mpt->mpt_ioc_page0.SubsystemVendorID - ); - - mpt_prt(mpt, "IOC Page 1 data: %x %x %x", - mpt->mpt_ioc_page1.Flags, - mpt->mpt_ioc_page1.CoalescingTimeout, - mpt->mpt_ioc_page1.CoalescingDepth); - - mpt_prt(mpt, "IOC Page 2 data: %x %x %x %x %x", - mpt->mpt_ioc_page2.CapabilitiesFlags, - mpt->mpt_ioc_page2.MaxPhysDisks, - mpt->mpt_ioc_page2.NumActivePhysDisks, - mpt->mpt_ioc_page2.MaxVolumes, - mpt->mpt_ioc_page2.NumActiveVolumes); - - /* FIXME: move this to attach */ - if (mpt->mpt_ioc_page2.MaxVolumes > - MPI_IOC_PAGE_2_RAID_VOLUME_MAX) { - /* complain */ - } - for (i = 0; i < mpt->mpt_ioc_page2.MaxVolumes; i++) { - mpt_prt(mpt, "IOC Page 2 RAID Volume %x %x %x %x %x", - mpt->mpt_ioc_page2.RaidVolume[i].VolumeType, - mpt->mpt_ioc_page2.RaidVolume[i].VolumePageNumber, - mpt->mpt_ioc_page2.RaidVolume[i].VolumeIOC, - mpt->mpt_ioc_page2.RaidVolume[i].VolumeBus, - mpt->mpt_ioc_page2.RaidVolume[i].VolumeID); - } - - mpt_prt(mpt, "IOC Page 3 data: %x ", - mpt->mpt_ioc_page3.NumPhysDisks); - - for (i = 0; i < mpt->mpt_ioc_page3.NumPhysDisks; i++) { - mpt_prt(mpt, "IOC Page 3 Physical Disk: %x %x %x %x", - mpt->mpt_ioc_page3.PhysDisk[i].PhysDiskNum, - mpt->mpt_ioc_page3.PhysDisk[i].PhysDiskIOC, - mpt->mpt_ioc_page3.PhysDisk[i].PhysDiskBus, - mpt->mpt_ioc_page3.PhysDisk[i].PhysDiskID); - } - - mpt_prt(mpt, "IOC Page 4 data: %x %x", - mpt->mpt_ioc_page4.MaxSEP, - mpt->mpt_ioc_page4.ActiveSEP); - - for (i = 0; i < mpt->mpt_ioc_page4.MaxSEP; i++) { - mpt_prt(mpt, "IOC Page 4 SEP: %x %x", - mpt->mpt_ioc_page4.SEP[i].SEPTargetID, - mpt->mpt_ioc_page4.SEP[i].SEPBus); - } - } -#endif /* MPT_DEBUG */ - - return (0); -} - -/* - * Read RAID Volume pages - */ -int -mpt_read_config_info_raid(struct mpt_softc *mpt) -{ - int rv; - - /* retrieve raid volume headers */ - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0, - 0, &mpt->mpt_raidvol_page0.Header); - if (rv) { - mpt_prt(mpt, "Could not retrieve RAID Volume Page 0 Header"); - return (-1); - } -#ifdef MPT_DEBUG - mpt_print_header(mpt, "RAID Volume Header Page", - &mpt->mpt_raidvol_page0.Header); -#endif /* MPT_DEBUG */ - - /* retrieve raid volume page using retrieved headers */ - rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_raidvol_page0.Header); - if (rv) { - mpt_prt(mpt, "Could not retrieve RAID Volume Page 0"); - return (-1); - } - - /* retrieve raid physical disk header */ - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_PHYSDISK, 0, - 0, &mpt->mpt_raidphys_page0.Header); - if (rv) { - mpt_prt(mpt, "Could not retrieve RAID Phys Disk Page 0 Header"); - return (-1); - } -#ifdef MPT_DEBUG - mpt_print_header(mpt, "RAID Volume Physical Disk Page", - &mpt->mpt_raidphys_page0.Header); -#endif /* MPT_DEBUG */ - - /* retrieve raid physical disk page using retrieved headers */ - rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_raidphys_page0.Header); - if (rv) { - mpt_prt(mpt, "Could not retrieve RAID Phys Disk Page 0"); - return (-1); - } - -#ifdef MPT_DEBUG - int i; - if (mpt_debug > 10) { - mpt_prt(mpt, "RAID Volume Page 0 data: %x %x %x %x %x" - "%x %x %x %x", - mpt->mpt_raidvol_page0.VolumeType, - mpt->mpt_raidvol_page0.VolumeIOC, - mpt->mpt_raidvol_page0.VolumeBus, - mpt->mpt_raidvol_page0.VolumeID, - mpt->mpt_raidvol_page0.VolumeStatus, - mpt->mpt_raidvol_page0.VolumeSettings, - mpt->mpt_raidvol_page0.MaxLBA, - mpt->mpt_raidvol_page0.StripeSize, - mpt->mpt_raidvol_page0.NumPhysDisks); - - for (i = 0; i < mpt->mpt_raidvol_page0.NumPhysDisks; i++) { - mpt_prt(mpt, "RAID Volume Page 0 Physical Disk: %x %x", - mpt->mpt_raidvol_page0.PhysDisk[i].PhysDiskNum, - mpt->mpt_raidvol_page0.PhysDisk[i].PhysDiskMap); - } - printf("\n"); - - mpt_prt(mpt, "RAID Phyical Disk Page 0 data: %x %x %x %x %x" - "%x %x %x", - mpt->mpt_raidphys_page0.PhysDiskNum, - mpt->mpt_raidphys_page0.PhysDiskIOC, - mpt->mpt_raidphys_page0.PhysDiskBus, - mpt->mpt_raidphys_page0.PhysDiskID, - mpt->mpt_raidphys_page0.PhysDiskSettings.SepID, - mpt->mpt_raidphys_page0.PhysDiskSettings.SepBus, - mpt->mpt_raidphys_page0.PhysDiskSettings.HotSparePool, - mpt->mpt_raidphys_page0.PhysDiskSettings.PhysDiskSettings); - - for (i = 0; - i < sizeof(mpt->mpt_raidphys_page0.DiskIdentifier); i++) { - printf("%02x ", - mpt->mpt_raidphys_page0.DiskIdentifier[i]); - } - - /* does them all */ - printf("\n"); - mpt_prt(mpt, "RAID Phyical Disk Page 0 data: %s", - mpt->mpt_raidphys_page0.InquiryData.VendorID); - - for (i = 0; - i < sizeof(mpt->mpt_raidphys_page0.InquiryData.Info); i++) { - printf("%02x ", - mpt->mpt_raidphys_page0.InquiryData.Info[i]); - } - - printf("\n"); - mpt_prt(mpt, "RAID Phyical Disk Page 0 data: %x %x %x" - "%x %x %x %x %x %x %x %x", - mpt->mpt_raidphys_page0.PhysDiskStatus.Flags, - mpt->mpt_raidphys_page0.PhysDiskStatus.State, - mpt->mpt_raidphys_page0.MaxLBA, - mpt->mpt_raidphys_page0.ErrorData.ErrorSenseKey, - mpt->mpt_raidphys_page0.ErrorData.ErrorCdbByte, - mpt->mpt_raidphys_page0.ErrorData.ErrorASCQ, - mpt->mpt_raidphys_page0.ErrorData.ErrorASC, - mpt->mpt_raidphys_page0.ErrorData.ErrorCount, - mpt->mpt_raidphys_page0.ErrorData.SmartASCQ, - mpt->mpt_raidphys_page0.ErrorData.SmartASC, - mpt->mpt_raidphys_page0.ErrorData.SmartCount - ); - } -#endif /* MPT_DEBUG */ - - return (0); -} - -/* - * Read SCSI configuration information - */ -int -mpt_read_config_info_spi(struct mpt_softc *mpt) -{ - int rv, i; - - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 0, - 0, &mpt->mpt_port_page0.Header); - if (rv) - return (-1); - - DNPRINTF(10, "%s: SPI Port Page 0 Header: %x %x %x %x\n", - DEVNAME(mpt), - mpt->mpt_port_page0.Header.PageVersion, - mpt->mpt_port_page0.Header.PageLength, - mpt->mpt_port_page0.Header.PageNumber, - mpt->mpt_port_page0.Header.PageType); - - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 1, - 0, &mpt->mpt_port_page1.Header); - if (rv) - return (-1); - - DNPRINTF(10, "%s: SPI Port Page 1 Header: %x %x %x %x\n", - DEVNAME(mpt), - mpt->mpt_port_page1.Header.PageVersion, - mpt->mpt_port_page1.Header.PageLength, - mpt->mpt_port_page1.Header.PageNumber, - mpt->mpt_port_page1.Header.PageType); - - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_PORT, 2, - 0, &mpt->mpt_port_page2.Header); - if (rv) - return (-1); - - DNPRINTF(10, "%s: SPI Port Page 2 Header: %x %x %x %x\n", - DEVNAME(mpt), - mpt->mpt_port_page1.Header.PageVersion, - mpt->mpt_port_page1.Header.PageLength, - mpt->mpt_port_page1.Header.PageNumber, - mpt->mpt_port_page1.Header.PageType); - - for (i = 0; i < 16; i++) { - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, - 0, i, &mpt->mpt_dev_page0[i].Header); - if (rv) { - return (-1); - } - DNPRINTF(10, - "%s: SPI Target %d Device Page 0 Header: %x %x %x %x\n", - DEVNAME(mpt), - i, mpt->mpt_dev_page0[i].Header.PageVersion, - mpt->mpt_dev_page0[i].Header.PageLength, - mpt->mpt_dev_page0[i].Header.PageNumber, - mpt->mpt_dev_page0[i].Header.PageType); - - rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_SCSI_DEVICE, - 1, i, &mpt->mpt_dev_page1[i].Header); - if (rv) { - return (-1); - } - DNPRINTF(10, - "%s: SPI Target %d Device Page 1 Header: %x %x %x %x\n", - DEVNAME(mpt), - i, mpt->mpt_dev_page1[i].Header.PageVersion, - mpt->mpt_dev_page1[i].Header.PageLength, - mpt->mpt_dev_page1[i].Header.PageNumber, - mpt->mpt_dev_page1[i].Header.PageType); - } - - /* - * At this point, we don't *have* to fail. As long as we have - * valid config header information, we can (barely) lurch - * along. - */ - - rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page0.Header); - if (rv) { - mpt_prt(mpt, "failed to read SPI Port Page 0"); - } else - DNPRINTF(10, - "%s: SPI Port Page 0: Capabilities %x PhysicalInterface %x\n", - DEVNAME(mpt), - mpt->mpt_port_page0.Capabilities, - mpt->mpt_port_page0.PhysicalInterface); - - rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header); - if (rv) { - mpt_prt(mpt, "failed to read SPI Port Page 1"); - } else - DNPRINTF(10, - "%s: SPI Port Page 1: Configuration %x OnBusTimerValue %x\n", - DEVNAME(mpt), - mpt->mpt_port_page1.Configuration, - mpt->mpt_port_page1.OnBusTimerValue); - - rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header); - if (rv) { - mpt_prt(mpt, "failed to read SPI Port Page 2"); - } else { - DNPRINTF(10, - "%s: SPI Port Page 2: Flags %x Settings %x\n", - DEVNAME(mpt), - mpt->mpt_port_page2.PortFlags, - mpt->mpt_port_page2.PortSettings); - for (i = 0; i < 16; i++) - DNPRINTF(10, - "%s: SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x\n", - DEVNAME(mpt), - i, mpt->mpt_port_page2.DeviceSettings[i].Timeout, - mpt->mpt_port_page2.DeviceSettings[i].SyncFactor, - mpt->mpt_port_page2.DeviceSettings[i].DeviceFlags); - } - - for (i = 0; i < 16; i++) { - rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page0[i].Header); - if (rv) { - mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 0", i); - continue; - } - DNPRINTF(10, - "%s: SPI Tgt %d Page 0: NParms %x Information %x\n", - DEVNAME(mpt), - i, mpt->mpt_dev_page0[i].NegotiatedParameters, - mpt->mpt_dev_page0[i].Information); - - rv = mpt_read_cfg_page(mpt, i, &mpt->mpt_dev_page1[i].Header); - if (rv) { - mpt_prt(mpt, "cannot read SPI Tgt %d Device Page 1", i); - continue; - } - - DNPRINTF(10, - "%s: SPI Tgt %d Page 1: RParms %x Configuration %x\n", - DEVNAME(mpt), - i, mpt->mpt_dev_page1[i].RequestedParameters, - mpt->mpt_dev_page1[i].Configuration); - } - return (0); -} - -/* - * Validate SPI configuration information. - * - * In particular, validate SPI Port Page 1. - */ -int -mpt_set_initial_config_spi(struct mpt_softc *mpt) -{ - int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id; - - mpt->mpt_disc_enable = 0xff; - mpt->mpt_tag_enable = 0; - - if (mpt->mpt_port_page1.Configuration != pp1val) { - CONFIG_PAGE_SCSI_PORT_1 tmp; - mpt_prt(mpt, - "SPI Port Page 1 Config value bad (%x)- should be %x", - mpt->mpt_port_page1.Configuration, pp1val); - tmp = mpt->mpt_port_page1; - tmp.Configuration = pp1val; - if (mpt_write_cfg_page(mpt, 0, &tmp.Header)) { - return (-1); - } - if (mpt_read_cfg_page(mpt, 0, &tmp.Header)) { - return (-1); - } - if (tmp.Configuration != pp1val) { - mpt_prt(mpt, - "failed to reset SPI Port Page 1 Config value"); - return (-1); - } - mpt->mpt_port_page1 = tmp; - } - - for (i = 0; i < 16; i++) { - CONFIG_PAGE_SCSI_DEVICE_1 tmp; - tmp = mpt->mpt_dev_page1[i]; - tmp.RequestedParameters = 0; - tmp.Configuration = 0; - DNPRINTF(10, - "%s: Set Tgt %d SPI DevicePage 1 values to %x 0 %x\n", - DEVNAME(mpt), - i, tmp.RequestedParameters, tmp.Configuration); - - if (mpt_write_cfg_page(mpt, i, &tmp.Header)) - return (-1); - - if (mpt_read_cfg_page(mpt, i, &tmp.Header)) - return (-1); - - mpt->mpt_dev_page1[i] = tmp; - DNPRINTF(10, - "%s: SPI Tgt %d Page 1: RParm %x Configuration %x\n", - DEVNAME(mpt), - i, - mpt->mpt_dev_page1[i].RequestedParameters, - mpt->mpt_dev_page1[i].Configuration); - } - return (0); -} - -/* - * Enable IOC port - */ -int -mpt_send_port_enable(struct mpt_softc *mpt, int port) -{ - int count; - struct req_entry *req; - MSG_PORT_ENABLE *enable_req; - - req = mpt_get_request(mpt); - - enable_req = req->req_vbuf; - bzero(enable_req, sizeof *enable_req); - - enable_req->Function = MPI_FUNCTION_PORT_ENABLE; - enable_req->MsgContext = req->index | 0x80000000; - enable_req->PortNumber = port; - - mpt_check_doorbell(mpt); - DNPRINTF(10, "%s: enabling port %d\n", DEVNAME(mpt), port); - - mpt_send_cmd(mpt, req); - - count = 0; - do { - DELAY(500); - mpt_intr(mpt); - if (++count == 100000) { - mpt_prt(mpt, "port enable timed out"); - return (-1); - } - } while (req->debug == REQ_ON_CHIP); - mpt_free_request(mpt, req); - return (0); -} - -/* - * Enable/Disable asynchronous event reporting. - * - * NB: this is the first command we send via shared memory - * instead of the handshake register. - */ -int -mpt_send_event_request(struct mpt_softc *mpt, int onoff) -{ - struct req_entry *req; - MSG_EVENT_NOTIFY *enable_req; - - req = mpt_get_request(mpt); - - enable_req = req->req_vbuf; - bzero(enable_req, sizeof *enable_req); - - enable_req->Function = MPI_FUNCTION_EVENT_NOTIFICATION; - enable_req->MsgContext = req->index | 0x80000000; - enable_req->Switch = onoff; - - mpt_check_doorbell(mpt); - DNPRINTF(10, "%s: %sabling async events\n", - DEVNAME(mpt), onoff? "en" : "dis"); - mpt_send_cmd(mpt, req); - - return (0); -} - -/* - * Un-mask the interrupts on the chip. - */ -void -mpt_enable_ints(struct mpt_softc *mpt) -{ - /* Unmask every thing except door bell int */ - mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK); -} - -/* - * Mask the interrupts on the chip. - */ -void -mpt_disable_ints(struct mpt_softc *mpt) -{ - /* Mask all interrupts */ - mpt_write(mpt, MPT_OFFSET_INTR_MASK, - MPT_INTR_REPLY_MASK | MPT_INTR_DB_MASK); -} - -/* (Re)Initialize the chip for use */ -int -mpt_init(struct mpt_softc *mpt, u_int32_t who) -{ - int try; - MSG_IOC_FACTS_REPLY facts; - MSG_PORT_FACTS_REPLY pfp; - u_int32_t pptr; - int val; - - /* Put all request buffers (back) on the free list */ - SLIST_INIT(&mpt->request_free_list); - for (val = 0; val < MPT_MAX_REQUESTS(mpt); val++) { - mpt_init_request(mpt, &mpt->request_pool[val]); - } - - DNPRINTF(10, "%s: doorbell req = %s\n", - DEVNAME(mpt), - mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL))); - - /* - * Start by making sure we're not at FAULT or RESET state - */ - switch (mpt_rd_db(mpt) & MPT_DB_STATE_MASK) { - case MPT_DB_STATE_RESET: - case MPT_DB_STATE_FAULT: - if (mpt_reset(mpt) != MPT_OK) { - return (EIO); - } - default: - break; - } - - for (try = 0; try < MPT_MAX_TRIES; try++) { - /* - * No need to reset if the IOC is already in the READY state. - * - * Force reset if initialization failed previously. - * Note that a hard_reset of the second channel of a '929 - * will stop operation of the first channel. Hopefully, if the - * first channel is ok, the second will not require a hard - * reset. - */ - if ((mpt_rd_db(mpt) & MPT_DB_STATE_MASK) != - MPT_DB_STATE_READY) { - if (mpt_reset(mpt) != MPT_OK) { - DELAY(10000); - continue; - } - } - - if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) { - mpt_prt(mpt, "mpt_get_iocfacts failed"); - continue; - } - - DNPRINTF(10, - "%s: IOCFACTS: GlobalCredits=%d BlockSize=%u " - "Request Frame Size %u\n", - DEVNAME(mpt), facts.GlobalCredits, - facts.BlockSize, facts.RequestFrameSize); - - mpt->mpt_global_credits = facts.GlobalCredits; - mpt->request_frame_size = facts.RequestFrameSize; - - /* save the firmware upload required flag */ - mpt->fw_download_boot = facts.Flags - & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT; - - mpt->fw_image_size = facts.FWImageSize; - - if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) { - mpt_prt(mpt, "mpt_get_portfacts failed"); - continue; - } - - DNPRINTF(10, - "%s: PORTFACTS: Type %x PFlags %x IID %d MaxDev %d\n", - DEVNAME(mpt), - pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID, - pfp.MaxDevices); - - if (pfp.PortType != MPI_PORTFACTS_PORTTYPE_SCSI && - pfp.PortType != MPI_PORTFACTS_PORTTYPE_FC) { - mpt_prt(mpt, "Unsupported Port Type (%x)", - pfp.PortType); - return (ENXIO); - } - if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) { - mpt_prt(mpt, "initiator role unsupported"); - return (ENXIO); - } - if (pfp.PortType == MPI_PORTFACTS_PORTTYPE_FC) { - mpt->is_fc = 1; - } else { - mpt->is_fc = 0; - } - mpt->mpt_ini_id = pfp.PortSCSIID; - - if (mpt_send_ioc_init(mpt, who) != MPT_OK) { - mpt_prt(mpt, "mpt_send_ioc_init failed"); - continue; - } - - DNPRINTF(10, "%s: mpt_send_ioc_init ok\n", DEVNAME(mpt)); - - if (mpt_wait_state(mpt, MPT_DB_STATE_RUNNING) != MPT_OK) { - mpt_prt(mpt, "IOC failed to go to run state"); - continue; - } - - DNPRINTF(10, "%s: IOC now at RUNSTATE\n", DEVNAME(mpt)); - - /* - * Give it reply buffers - * - * Do *not* exceed global credits. - */ - for (val = 0, pptr = mpt->reply_phys; - (pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE); - pptr += MPT_REPLY_SIZE) { - mpt_free_reply(mpt, pptr); - if (++val == mpt->mpt_global_credits - 1) - break; - } - - /* XXX MU correct place the call to fw_upload? */ - if (mpt->upload_fw) { - DNPRINTF(10, "%s: firmware upload required\n", - DEVNAME(mpt)); - - if (mpt_do_upload(mpt)) - /* XXX MP should we panic? */ - mpt_prt(mpt, "firmware upload failure"); - } - else - DNPRINTF(10, "%sfirmware upload not required\n", - DEVNAME(mpt)); - - /* - * Enable asynchronous event reporting - */ - mpt_send_event_request(mpt, 1); - - - /* - * Read set up initial configuration information - * (SPI only for now) - */ - - if (mpt->is_fc == 0) { - if (mpt_read_config_info_spi(mpt)) - return (EIO); - - if (mpt_set_initial_config_spi(mpt)) - return (EIO); - } - - /* - * Read IO Unit pages - */ - if (mpt_read_config_info_iou(mpt)) { - mpt_prt(mpt, "could not retrieve IO Unit pages"); - return (EIO); - } - - /* - * if the vmware flag is set skip page retrival since it does - * not support all of them. - */ - if (mpt->vmware) - DNPRINTF(10, "%s: running in vmware, skipping page " - "retrieval\n", DEVNAME(mpt)); - else { - /* - * Read manufacturing pages - */ - if (mpt_read_config_info_mfg(mpt)) { - mpt_prt(mpt, "could not retrieve manufacturing" - "pages"); - return (EIO); - } - - /* - * Read IOC pages - */ - if (mpt_read_config_info_ioc(mpt)) { - mpt_prt(mpt, "could not retrieve IOC pages"); - return (EIO); - } - mpt->im_support = mpt->mpt_ioc_page2.CapabilitiesFlags & - (MPI_IOCPAGE2_CAP_FLAGS_IS_SUPPORT | - MPI_IOCPAGE2_CAP_FLAGS_IME_SUPPORT | - MPI_IOCPAGE2_CAP_FLAGS_IM_SUPPORT); - - /* - * Read RAID pages if we have IM/IME/IS volumes - */ - if (mpt->mpt_ioc_page2.NumActiveVolumes) { - if (mpt_read_config_info_raid(mpt)) { - mpt_prt(mpt, "could not retrieve RAID" - "pages"); - return (EIO); - } - } - } - - /* - * Now enable the port - */ - if (mpt_send_port_enable(mpt, 0) != MPT_OK) { - mpt_prt(mpt, "failed to enable port 0"); - continue; - } - - DNPRINTF(10, "%s: enabled port 0\n", DEVNAME(mpt)); - - /* Everything worked */ - break; - } - - if (try >= MPT_MAX_TRIES) { - mpt_prt(mpt, "failed to initialize IOC"); - return (EIO); - } - - DNPRINTF(10, "%s: enabling interrupts\n", DEVNAME(mpt)); - - mpt_enable_ints(mpt); - return (0); -} - -/* - * mpt_do_upload - create and send FWUpload request to MPT adapter port. - * - * Returns 0 for success, error for failure - */ -int -mpt_do_upload(struct mpt_softc *mpt) -{ - u_int8_t request[MPT_RQSL(mpt)]; - FWUploadReply_t reply; - FWUpload_t *prequest; - FWUploadReply_t *preply; - FWUploadTCSGE_t *ptcsge = NULL; - SGE_SIMPLE32 *se; - int maxsgl; - int sgeoffset; - int i, error; - uint32_t flags; - - if (mpt->fw_image_size == 0 || mpt->fw != NULL) { - return 0; - } - - /* compute the maximum number of elements in the SG list */ - maxsgl = (MPT_RQSL(mpt) - sizeof(MSG_FW_UPLOAD) + - sizeof(SGE_MPI_UNION) - sizeof(FWUploadTCSGE_t)) - / sizeof(SGE_SIMPLE32); - - error = mpt_alloc_fw_mem(mpt, maxsgl); - if (error) { - mpt_prt(mpt,"mpt_alloc_fw_mem error: %d", error); - return error; - } - - if (mpt->fw_dmap->dm_nsegs > maxsgl) { - mpt_prt(mpt,"nsegs > maxsgl"); - return 1; /* XXX */ - } - - prequest = (FWUpload_t *)&request; - preply = (FWUploadReply_t *)&reply; - - memset(prequest, 0, MPT_RQSL(mpt)); - memset(preply, 0, sizeof(reply)); - - prequest->ImageType = MPI_FW_UPLOAD_ITYPE_FW_IOC_MEM; - prequest->Function = MPI_FUNCTION_FW_UPLOAD; - prequest->MsgContext = 0; - - ptcsge = (FWUploadTCSGE_t *) &prequest->SGL; - ptcsge->Reserved = 0; - ptcsge->ContextSize = 0; - ptcsge->DetailsLength = 12; - ptcsge->Flags = MPI_SGE_FLAGS_TRANSACTION_ELEMENT; - ptcsge->Reserved1 = 0; - ptcsge->ImageOffset = 0; - ptcsge->ImageSize = mpt->fw_image_size; /* XXX MU check endianess */ - - sgeoffset = sizeof(FWUpload_t) - sizeof(SGE_MPI_UNION) + - sizeof(FWUploadTCSGE_t); - - se = (SGE_SIMPLE32 *) &request[sgeoffset]; - - flags = MPI_SGE_FLAGS_SIMPLE_ELEMENT; - - DNPRINTF(20, "%s: assembling SG list (%d entries)\n", - DEVNAME(mpt), mpt->fw_dmap->dm_nsegs); - - for (i = 0; i < mpt->fw_dmap->dm_nsegs; i++, se++) { - if (i == mpt->fw_dmap->dm_nsegs - 1) { - /* XXX MU okay? */ - flags |= MPI_SGE_FLAGS_LAST_ELEMENT | - MPI_SGE_FLAGS_END_OF_BUFFER | - MPI_SGE_FLAGS_END_OF_LIST; - } - - se->Address = mpt->fw_dmap->dm_segs[i].ds_addr; - MPI_pSGE_SET_LENGTH(se, mpt->fw_dmap->dm_segs[i].ds_len); - MPI_pSGE_SET_FLAGS(se, flags); - sgeoffset += sizeof(*se); - } - - DNPRINTF(10, "%s: sending FW Upload request to IOC (size: %d, " - "img size: %d)\n", DEVNAME(mpt), sgeoffset, mpt->fw_image_size); - - if ((error = mpt_send_handshake_cmd(mpt, sgeoffset, prequest)) != 0) { - return(error); - } - - error = mpt_recv_handshake_reply(mpt, sizeof(reply), &reply); - - if (error == 0) { - /* - * Handshake transfer was complete and successfull. - * Check the Reply Frame - */ - int status, transfer_sz; - - status = preply->IOCStatus; - DNPRINTF(20, "%s: fw_upload reply status %d\n", - DEVNAME(mpt), status); - - if (status == MPI_IOCSTATUS_SUCCESS) { - transfer_sz = preply->ActualImageSize; - if (transfer_sz != mpt->fw_image_size) - error = EFAULT; - } - else - error = EFAULT; - } - - if (error == 0) { - mpt->upload_fw = 0; - } - else { - mpt_prt(mpt, "freeing image memory"); - mpt_free_fw_mem(mpt); - mpt->fw = NULL; - } - - return error; -} - -/* - * mpt_downloadboot - DownloadBoot code - * Returns 0 for success, <0 for failure - */ -int -mpt_downloadboot(struct mpt_softc *mpt) -{ - MpiFwHeader_t *fwhdr = NULL; - MpiExtImageHeader_t *exthdr = NULL; - int fw_size; - u_int32_t diag0; -#ifdef MPT_DEBUG - u_int32_t diag1; -#endif - int count = 0; - u_int32_t *ptr = NULL; - u_int32_t nextimg; - u_int32_t load_addr; - u_int32_t diagrw_data; - -#ifdef MPT_DEBUG - diag0 = mpt_read(mpt, MPT_OFFSET_DIAGNOSTIC); - if (mpt->mpt2) - diag1 = mpt_read(mpt->mpt2, MPT_OFFSET_DIAGNOSTIC); - mpt_prt(mpt, "diag0=%08x, diag1=%08x", diag0, diag1); -#endif - mpt_prt(mpt, "fw size 0x%x, ioc FW ptr %p", mpt->fw_image_size, - mpt->fw); - if (mpt->mpt2) - mpt_prt(mpt->mpt2, "ioc FW ptr %p", mpt->mpt2->fw); - - fw_size = mpt->fw_image_size; - - if (fw_size == 0) - return -1; - - mpt_prt(mpt, "FW Image @ %p", mpt->fw); - - if (!mpt->fw) - return -2; - - /* - * Write magic sequence to WriteSequence register - * until enter diagnostic mode - */ - diag0 = mpt_read(mpt, MPT_OFFSET_DIAGNOSTIC); - while ((diag0 & MPI_DIAG_DRWE) == 0) { - mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_1); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_2); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_3); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_4); - mpt_write(mpt, MPT_OFFSET_SEQUENCE, MPT_DIAG_SEQUENCE_5); - - /* wait 100msec */ - DELAY(100); - - count++; - if (count > 20) { - mpt_prt(mpt, "enable diagnostic mode FAILED! (%02xh)", - diag0); - return -EFAULT; - } - - diag0 = mpt_read(mpt, MPT_OFFSET_DIAGNOSTIC); -#ifdef MPT_DEBUG - if (mpt->mpt2) - diag1 = mpt_read(mpt->mpt2, MPT_OFFSET_DIAGNOSTIC); - mpt_prt(mpt, "diag0=%08x, diag1=%08x", diag0, diag1); -#endif - mpt_prt(mpt, "wrote magic DiagWriteEn sequence (%x)", diag0); - } - - /* Set the DiagRwEn and Disable ARM bits */ - diag0 |= (MPI_DIAG_RW_ENABLE | MPI_DIAG_DISABLE_ARM); - mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, diag0); - -#ifdef MPT_DEBUG - if (mpt->mpt2) - diag1 = mpt_read(mpt->mpt2, MPT_OFFSET_DIAGNOSTIC); - mpt_prt(mpt, "diag0=%08x, diag1=%08x", diag0, diag1); -#endif - - fwhdr = (MpiFwHeader_t *) mpt->fw; - ptr = (u_int32_t *) fwhdr; - count = (fwhdr->ImageSize + 3)/4; - nextimg = fwhdr->NextImageHeaderOffset; - - /* - * write the LoadStartAddress to the DiagRw Address Register - * XXX linux is using programmed IO for the RWADDR and RWDATA - */ - mpt_write(mpt, MPT_OFFSET_RWADDR, fwhdr->LoadStartAddress); - - mpt_prt(mpt, "LoadStart addr written 0x%x", fwhdr->LoadStartAddress); - mpt_prt(mpt, "writing file image: 0x%x u32's @ %p", count, ptr); - - while (count--) { - mpt_write(mpt, MPT_OFFSET_RWDATA, *ptr); - ptr++; - } - - while (nextimg) { - ptr = (u_int32_t *) (mpt->fw + nextimg); - exthdr = (MpiExtImageHeader_t *) ptr; - count = (exthdr->ImageSize +3)/4; - nextimg = exthdr->NextImageHeaderOffset; - load_addr = exthdr->LoadStartAddress; - - mpt_prt(mpt, "write ext image: 0x%x u32's @ %p", count, ptr); - - mpt_write(mpt, MPT_OFFSET_RWADDR, load_addr); - - while (count--) { - mpt_write(mpt, MPT_OFFSET_RWDATA, *ptr); - ptr++; - } - } - - /* write the IopResetVectorRegAddr */ - mpt_prt(mpt, "write IopResetVector addr!"); - mpt_write(mpt, MPT_OFFSET_RWADDR, fwhdr->IopResetRegAddr); - - /* write the IopResetVectorValue */ - mpt_prt(mpt, "write IopResetVector value!"); - mpt_write(mpt, MPT_OFFSET_RWDATA, fwhdr->IopResetVectorValue); - - /* - * clear the internal flash bad bit - autoincrementing register, - * so must do two writes. - */ - mpt_write(mpt, MPT_OFFSET_RWADDR, 0x3F000000); - diagrw_data = mpt_read(mpt, MPT_OFFSET_RWDATA); - diagrw_data |= 0x4000000; - mpt_write(mpt, MPT_OFFSET_RWADDR, 0x3F000000); - mpt_write(mpt, MPT_OFFSET_RWDATA, diagrw_data); - - /* clear the RW enable and DISARM bits */ - diag0 = mpt_read(mpt, MPT_OFFSET_DIAGNOSTIC); - diag0 &= ~(MPI_DIAG_DISABLE_ARM | MPI_DIAG_RW_ENABLE | - MPI_DIAG_FLASH_BAD_SIG); - mpt_write(mpt, MPT_OFFSET_DIAGNOSTIC, diag0); - - /* write 0xFF to reset the sequencer */ - mpt_write(mpt, MPT_OFFSET_SEQUENCE, 0xFF); - - return 0; -} |