diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c index ebdc222565d7..445f884f6cd7 100644 --- a/sys/dev/mpt/mpt.c +++ b/sys/dev/mpt/mpt.c @@ -31,7 +31,7 @@ */ #include -#include + #define MPT_MAX_TRYS 3 #define MPT_MAX_WAIT 300000 @@ -39,24 +39,24 @@ static int maxwait_ack = 0; static int maxwait_int = 0; static int maxwait_state = 0; -static __inline u_int32_t mpt_rd_db(struct mpt_softc *mpt); -static __inline u_int32_t mpt_rd_intr(struct mpt_softc *mpt); +static __inline u_int32_t mpt_rd_db(mpt_softc_t *mpt); +static __inline u_int32_t mpt_rd_intr(mpt_softc_t *mpt); static __inline u_int32_t -mpt_rd_db(struct mpt_softc *mpt) +mpt_rd_db(mpt_softc_t *mpt) { return mpt_read(mpt, MPT_OFFSET_DOORBELL); } static __inline u_int32_t -mpt_rd_intr(struct mpt_softc *mpt) +mpt_rd_intr(mpt_softc_t *mpt) { return mpt_read(mpt, MPT_OFFSET_INTR_STATUS); } /* Busy wait for a door bell to be read by IOC */ static int -mpt_wait_db_ack(struct mpt_softc *mpt) +mpt_wait_db_ack(mpt_softc_t *mpt) { int i; for (i=0; i < MPT_MAX_WAIT; i++) { @@ -72,7 +72,7 @@ mpt_wait_db_ack(struct mpt_softc *mpt) /* Busy wait for a door bell interrupt */ static int -mpt_wait_db_int(struct mpt_softc *mpt) +mpt_wait_db_int(mpt_softc_t *mpt) { int i; for (i=0; i < MPT_MAX_WAIT; i++) { @@ -87,7 +87,7 @@ mpt_wait_db_int(struct mpt_softc *mpt) /* Wait for IOC to transition to a give state */ void -mpt_check_doorbell(struct mpt_softc *mpt) +mpt_check_doorbell(mpt_softc_t *mpt) { u_int32_t db = mpt_rd_db(mpt); if (MPT_STATE(db) != MPT_DB_STATE_RUNNING) { @@ -98,7 +98,7 @@ mpt_check_doorbell(struct mpt_softc *mpt) /* Wait for IOC to transition to a give state */ static int -mpt_wait_state(struct mpt_softc *mpt, enum DB_STATE_BITS state) +mpt_wait_state(mpt_softc_t *mpt, enum DB_STATE_BITS state) { int i; @@ -116,7 +116,7 @@ mpt_wait_state(struct mpt_softc *mpt, enum DB_STATE_BITS state) /* Issue the reset COMMAND to the IOC */ int -mpt_soft_reset(struct mpt_softc *mpt) +mpt_soft_reset(mpt_softc_t *mpt) { if (mpt->verbose) { device_printf(mpt->dev,"soft reset\n"); @@ -160,7 +160,7 @@ mpt_soft_reset(struct mpt_softc *mpt) * processors in the chip. */ void -mpt_hard_reset(struct mpt_softc *mpt) +mpt_hard_reset(mpt_softc_t *mpt) { /* This extra read comes for the Linux source * released by LSI. It's function is undocumented! @@ -204,7 +204,7 @@ mpt_hard_reset(struct mpt_softc *mpt) * fouls up the PCI configuration registers. */ int -mpt_reset(struct mpt_softc *mpt) +mpt_reset(mpt_softc_t *mpt) { int ret; @@ -225,7 +225,7 @@ mpt_reset(struct mpt_softc *mpt) /* Return a command buffer to the free queue */ void -mpt_free_request(struct mpt_softc *mpt, request_t *req) +mpt_free_request(mpt_softc_t *mpt, request_t *req) { if (req == NULL || req != &mpt->requests[req->index]) { panic("mpt_free_request bad req ptr\n"); @@ -238,7 +238,7 @@ mpt_free_request(struct mpt_softc *mpt, request_t *req) /* Get a command buffer from the free queue */ request_t * -mpt_get_request(struct mpt_softc *mpt) +mpt_get_request(mpt_softc_t *mpt) { request_t *req; req = SLIST_FIRST(&mpt->request_free_list); @@ -257,7 +257,7 @@ mpt_get_request(struct mpt_softc *mpt) /* Pass the command to the IOC */ void -mpt_send_cmd(struct mpt_softc *mpt, request_t *req) +mpt_send_cmd(mpt_softc_t *mpt, request_t *req) { req->sequence = mpt->sequence++; if (mpt->verbose > 1) { @@ -285,14 +285,14 @@ mpt_send_cmd(struct mpt_softc *mpt, request_t *req) * finished processing it. */ void -mpt_free_reply(struct mpt_softc *mpt, u_int32_t ptr) +mpt_free_reply(mpt_softc_t *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) +mpt_pop_reply_queue(mpt_softc_t *mpt) { return mpt_read(mpt, MPT_OFFSET_REPLY_Q); } @@ -304,7 +304,7 @@ mpt_pop_reply_queue(struct mpt_softc *mpt) * commands such as device/bus reset as specified by LSI. */ int -mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd) +mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd) { int i; u_int32_t data, *data32; @@ -365,7 +365,7 @@ mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd) /* Get the response from the handshake register */ int -mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply) +mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply) { int left, reply_left; u_int16_t *data16; @@ -436,9 +436,8 @@ mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply) return (0); } -/* Get API statistics from the chip */ static int -mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp) +mpt_get_iocfacts(mpt_softc_t *mpt, MSG_IOC_FACTS_REPLY *freplp) { MSG_IOC_FACTS f_req; int error; @@ -453,6 +452,23 @@ mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp) return (error); } +static int +mpt_get_portfacts(mpt_softc_t *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. @@ -460,7 +476,7 @@ mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp) * frames from the IOC that we will be allocating. */ static int -mpt_send_ioc_init(struct mpt_softc *mpt, u_int32_t who) +mpt_send_ioc_init(mpt_softc_t *mpt, u_int32_t who) { int error = 0; MSG_IOC_INIT init; @@ -486,9 +502,446 @@ mpt_send_ioc_init(struct mpt_softc *mpt, u_int32_t who) return (error); } -/* Send the port enable to allow the IOC to join the FC loop */ + +/* + * Utiltity routine to read configuration headers and pages + */ + static int -mpt_send_port_enable(struct mpt_softc *mpt, int port) +mpt_read_cfg_header(mpt_softc_t *, int, int, int, fCONFIG_PAGE_HEADER *); +static int +mpt_read_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *); +static int +mpt_write_cfg_page(mpt_softc_t *, int, fCONFIG_PAGE_HEADER *); + +static int +mpt_read_cfg_header(mpt_softc_t *mpt, int PageType, int PageNumber, + int PageAddress, fCONFIG_PAGE_HEADER *rslt) +{ + int count; + request_t *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) { + device_printf(mpt->dev, "read_cfg_header timed out\n"); + 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) { + device_printf(mpt->dev, + "mpt_read_cfg_header: Config Info Status %x\n", + reply->IOCStatus); + return (-1); + } + bcopy(&reply->Header, rslt, sizeof (fCONFIG_PAGE_HEADER)); + mpt_free_reply(mpt, (req->sequence << 1)); + mpt_free_request(mpt, req); + return (0); +} + +#define CFG_DATA_OFF 40 + +static int +mpt_read_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr) +{ + int count; + request_t *req; + SGE_SIMPLE32 *se; + MSG_CONFIG *cfgp; + size_t amt; + MSG_CONFIG_REPLY *reply; + + req = mpt_get_request(mpt); + + cfgp = req->req_vbuf; + amt = (cfgp->Header.PageLength * sizeof (uint32_t)); + bzero(cfgp, sizeof *cfgp); + cfgp->Action = MPI_CONFIG_ACTION_PAGE_READ_CURRENT; + cfgp->Function = MPI_FUNCTION_CONFIG; + cfgp->Header = *hdr; + 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) { + device_printf(mpt->dev, "read_cfg_page timed out\n"); + 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) { + device_printf(mpt->dev, + "mpt_read_cfg_page: Config Info Status %x\n", + reply->IOCStatus); + return (-1); + } + mpt_free_reply(mpt, (req->sequence << 1)); + bus_dmamap_sync(mpt->request_dmat, mpt->request_dmap, + BUS_DMASYNC_POSTREAD); + if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && + cfgp->Header.PageNumber == 0) { + amt = sizeof (fCONFIG_PAGE_SCSI_PORT_0); + } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && + cfgp->Header.PageNumber == 1) { + amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1); + } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && + cfgp->Header.PageNumber == 2) { + amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2); + } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && + cfgp->Header.PageNumber == 0) { + amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0); + } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && + cfgp->Header.PageNumber == 1) { + amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1); + } + bcopy(((caddr_t)req->req_vbuf)+CFG_DATA_OFF, hdr, amt); + mpt_free_request(mpt, req); + return (0); +} + +static int +mpt_write_cfg_page(mpt_softc_t *mpt, int PageAddress, fCONFIG_PAGE_HEADER *hdr) +{ + int count, hdr_attr; + request_t *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) { + device_printf(mpt->dev, "page type 0x%x not changeable\n", + hdr->PageType & MPI_CONFIG_PAGETYPE_MASK); + return (-1); + } + hdr->PageType &= MPI_CONFIG_PAGETYPE_MASK; + + amt = (cfgp->Header.PageLength * sizeof (uint32_t)); + cfgp->Action = MPI_CONFIG_ACTION_PAGE_WRITE_CURRENT; + cfgp->Function = MPI_FUNCTION_CONFIG; + cfgp->Header = *hdr; + 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 (fCONFIG_PAGE_SCSI_PORT_0); + } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && + cfgp->Header.PageNumber == 1) { + amt = sizeof (fCONFIG_PAGE_SCSI_PORT_1); + } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_PORT && + cfgp->Header.PageNumber == 2) { + amt = sizeof (fCONFIG_PAGE_SCSI_PORT_2); + } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && + cfgp->Header.PageNumber == 0) { + amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_0); + } else if (cfgp->Header.PageType == MPI_CONFIG_PAGETYPE_SCSI_DEVICE && + cfgp->Header.PageNumber == 1) { + amt = sizeof (fCONFIG_PAGE_SCSI_DEVICE_1); + } + bcopy(hdr, ((caddr_t)req->req_vbuf)+CFG_DATA_OFF, amt); + + mpt_check_doorbell(mpt); + mpt_send_cmd(mpt, req); + count = 0; + do { + DELAY(500); + mpt_intr(mpt); + if (++count == 1000) { + hdr->PageType |= hdr_attr; + device_printf(mpt->dev, + "mpt_write_cfg_page timed out\n"); + 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) { + device_printf(mpt->dev, + "mpt_write_cfg_page: Config Info Status %x\n", + reply->IOCStatus); + return (-1); + } + mpt_free_reply(mpt, (req->sequence << 1)); + + /* + * Restore stripped out attributes + */ + hdr->PageType |= hdr_attr; + mpt_free_request(mpt, req); + return (0); +} + +/* + * Read SCSI configuration information + */ +static int +mpt_read_config_info_spi(mpt_softc_t *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); + } + if (mpt->verbose > 1) { + device_printf(mpt->dev, "SPI Port Page 0 Header: %x %x %x %x\n", + 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); + } + if (mpt->verbose > 1) { + device_printf(mpt->dev, "SPI Port Page 1 Header: %x %x %x %x\n", + 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); + } + + if (mpt->verbose > 1) { + device_printf(mpt->dev, "SPI Port Page 2 Header: %x %x %x %x\n", + 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); + } + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Target %d Device Page 0 Header: %x %x %x %x\n", + 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); + } + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Target %d Device Page 1 Header: %x %x %x %x\n", + 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) { + device_printf(mpt->dev, "failed to read SPI Port Page 0\n"); + } else if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Port Page 0: Capabilities %x PhysicalInterface %x\n", + mpt->mpt_port_page0.Capabilities, + mpt->mpt_port_page0.PhysicalInterface); + } + + rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page1.Header); + if (rv) { + device_printf(mpt->dev, "failed to read SPI Port Page 1\n"); + } else if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Port Page 1: Configuration %x OnBusTimerValue %x\n", + mpt->mpt_port_page1.Configuration, + mpt->mpt_port_page1.OnBusTimerValue); + } + + rv = mpt_read_cfg_page(mpt, 0, &mpt->mpt_port_page2.Header); + if (rv) { + device_printf(mpt->dev, "failed to read SPI Port Page 2\n"); + } else if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Port Page 2: Flags %x Settings %x\n", + mpt->mpt_port_page2.PortFlags, + mpt->mpt_port_page2.PortSettings); + for (i = 0; i < 16; i++) { + device_printf(mpt->dev, + "SPI Port Page 2 Tgt %d: timo %x SF %x Flags %x\n", + 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) { + device_printf(mpt->dev, + "cannot read SPI Tgt %d Device Page 0\n", i); + continue; + } + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Tgt %d Page 0: NParms %x Information %x\n", + 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) { + device_printf(mpt->dev, + "cannot read SPI Tgt %d Device Page 1\n", i); + continue; + } + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Tgt %d Page 1: RParms %x Configuration %x\n", + 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. + */ +static int +mpt_set_initial_config_spi(mpt_softc_t *mpt) +{ + int i, pp1val = ((1 << mpt->mpt_ini_id) << 16) | mpt->mpt_ini_id; + + if (mpt->mpt_port_page1.Configuration != pp1val) { + fCONFIG_PAGE_SCSI_PORT_1 tmp; + device_printf(mpt->dev, + "SPI Port Page 1 Config value bad (%x)- should be %x\n", + 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) { + device_printf(mpt->dev, + "failed to reset SPI Port Page 1 Config value\n"); + return (-1); + } + mpt->mpt_port_page1 = tmp; + } + +#if 1 + i = i; +#else + for (i = 0; i < 16; i++) { + fCONFIG_PAGE_SCSI_DEVICE_1 tmp; + tmp = mpt->mpt_dev_page1[i]; + tmp.RequestedParameters = 0; + tmp.Configuration = 0; + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "Set Tgt %d SPI DevicePage 1 values to %x 0 %x\n", + 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; + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "SPI Tgt %d Page 1: RParm %x Configuration %x\n", i, + mpt->mpt_dev_page1[i].RequestedParameters, + mpt->mpt_dev_page1[i].Configuration); + } + } +#endif + return (0); +} + +/* + * Enable IOC port + */ +static int +mpt_send_port_enable(mpt_softc_t *mpt, int port) { int count; request_t *req; @@ -529,7 +982,7 @@ mpt_send_port_enable(struct mpt_softc *mpt, int port) * instead of the handshake register. */ static int -mpt_send_event_request(struct mpt_softc *mpt, int onoff) +mpt_send_event_request(mpt_softc_t *mpt, int onoff) { request_t *req; MSG_EVENT_NOTIFY *enable_req; @@ -557,7 +1010,7 @@ mpt_send_event_request(struct mpt_softc *mpt, int onoff) * Un-mask the interupts on the chip. */ void -mpt_enable_ints(struct mpt_softc *mpt) +mpt_enable_ints(mpt_softc_t *mpt) { /* Unmask every thing except door bell int */ mpt_write(mpt, MPT_OFFSET_INTR_MASK, MPT_INTR_DB_MASK); @@ -567,7 +1020,7 @@ mpt_enable_ints(struct mpt_softc *mpt) * Mask the interupts on the chip. */ void -mpt_disable_ints(struct mpt_softc *mpt) +mpt_disable_ints(mpt_softc_t *mpt) { /* Mask all interrupts */ mpt_write(mpt, MPT_OFFSET_INTR_MASK, @@ -576,10 +1029,11 @@ mpt_disable_ints(struct mpt_softc *mpt) /* (Re)Initialize the chip for use */ int -mpt_init(struct mpt_softc *mpt, u_int32_t who) +mpt_init(mpt_softc_t *mpt, u_int32_t who) { int try; MSG_IOC_FACTS_REPLY facts; + MSG_PORT_FACTS_REPLY pfp; u_int32_t pptr; int val; @@ -629,20 +1083,51 @@ mpt_init(struct mpt_softc *mpt, u_int32_t who) if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) { device_printf(mpt->dev, "mpt_get_iocfacts failed\n"); continue; - } else if (mpt->verbose > 1) { + } + + if (mpt->verbose > 1) { device_printf(mpt->dev, "mpt_get_iocfacts: GlobalCredits=%d BlockSize=%u " "Request Frame Size %u\n", facts.GlobalCredits, facts.BlockSize, facts.RequestFrameSize); } mpt->mpt_global_credits = facts.GlobalCredits; - mpt->blk_size = facts.BlockSize; mpt->request_frame_size = facts.RequestFrameSize; + if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) { + device_printf(mpt->dev, "mpt_get_portfacts failed\n"); + continue; + } + + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "mpt_get_portfacts: Type %x PFlags %x IID %d\n", + pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID); + } + + if (pfp.PortType != MPI_PORTFACTS_PORTTYPE_SCSI && + pfp.PortType != MPI_PORTFACTS_PORTTYPE_FC) { + device_printf(mpt->dev, "Unsupported Port Type (%x)\n", + pfp.PortType); + return (ENXIO); + } + if (!(pfp.ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR)) { + device_printf(mpt->dev, "initiator role unsupported\n"); + 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) { device_printf(mpt->dev, "mpt_send_ioc_init failed\n"); continue; - } else if (mpt->verbose > 1) { + } + + if (mpt->verbose > 1) { device_printf(mpt->dev, "mpt_send_ioc_init ok\n"); } @@ -650,7 +1135,8 @@ mpt_init(struct mpt_softc *mpt, u_int32_t who) device_printf(mpt->dev, "IOC failed to go to run state\n"); continue; - } else if (mpt->verbose > 1) { + } + if (mpt->verbose > 1) { device_printf(mpt->dev, "IOC now at RUNSTATE\n"); } @@ -667,12 +1153,35 @@ mpt_init(struct mpt_softc *mpt, u_int32_t who) break; } + /* + * 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); + } + } + + /* + * Now enable the port + */ if (mpt_send_port_enable(mpt, 0) != MPT_OK) { device_printf(mpt->dev, "failed to enable port 0\n"); continue; - } else if (mpt->verbose > 1) { + } + + if (mpt->verbose > 1) { device_printf(mpt->dev, "enabled port 0\n"); } diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h index feb541edde21..2ec76e3cac85 100644 --- a/sys/dev/mpt/mpt.h +++ b/sys/dev/mpt/mpt.h @@ -145,33 +145,24 @@ enum _MPT_DIAG_BITS { #define MPT_CONTEXT_REPLY (0x80000000) #define MPT_CONTEXT_MASK (~0xE0000000) -#include "dev/mpt/mpilib/mpi_type.h" -#include "dev/mpt/mpilib/mpi.h" -#include "dev/mpt/mpilib/mpi_cnfg.h" -#include "dev/mpt/mpilib/mpi_fc.h" -#include "dev/mpt/mpilib/mpi_init.h" -#include "dev/mpt/mpilib/mpi_ioc.h" -#include "dev/mpt/mpilib/mpi_lan.h" -#include "dev/mpt/mpilib/mpi_targ.h" - #ifdef _KERNEL -int mpt_soft_reset(struct mpt_softc *mpt); -void mpt_hard_reset(struct mpt_softc *mpt); -int mpt_recv_handshake_reply(struct mpt_softc *mpt, size_t reply_len, void *reply); +int mpt_soft_reset(mpt_softc_t *mpt); +void mpt_hard_reset(mpt_softc_t *mpt); +int mpt_recv_handshake_reply(mpt_softc_t *mpt, size_t reply_len, void *reply); -void mpt_send_cmd(struct mpt_softc *mpt, request_t *req); -void mpt_free_reply(struct mpt_softc *mpt, u_int32_t ptr); -void mpt_enable_ints(struct mpt_softc *mpt); -void mpt_disable_ints(struct mpt_softc *mpt); -u_int32_t mpt_pop_reply_queue(struct mpt_softc *mpt); -int mpt_init(struct mpt_softc *mpt, u_int32_t who); -int mpt_reset(struct mpt_softc *mpt); -int mpt_send_handshake_cmd(struct mpt_softc *mpt, size_t len, void *cmd); -request_t * mpt_get_request(struct mpt_softc *mpt); -void mpt_free_request(struct mpt_softc *mpt, request_t *req); +void mpt_send_cmd(mpt_softc_t *mpt, request_t *req); +void mpt_free_reply(mpt_softc_t *mpt, u_int32_t ptr); +void mpt_enable_ints(mpt_softc_t *mpt); +void mpt_disable_ints(mpt_softc_t *mpt); +u_int32_t mpt_pop_reply_queue(mpt_softc_t *mpt); +int mpt_init(mpt_softc_t *mpt, u_int32_t who); +int mpt_reset(mpt_softc_t *mpt); +int mpt_send_handshake_cmd(mpt_softc_t *mpt, size_t len, void *cmd); +request_t * mpt_get_request(mpt_softc_t *mpt); +void mpt_free_request(mpt_softc_t *mpt, request_t *req); int mpt_intr(void *dummy); -void mpt_check_doorbell(struct mpt_softc* mpt); +void mpt_check_doorbell(mpt_softc_t * mpt); /* mpt_debug.c functions */ void mpt_print_reply(void *vmsg); @@ -182,6 +173,5 @@ char *mpt_req_state(enum mpt_req_state state); void mpt_print_scsi_io_request(MSG_SCSI_IO_REQUEST *msg); void mpt_print_config_request(void *vmsg); void mpt_print_request(void *vmsg); -#endif /* _KERNEL */ - +#endif #endif /* _MPT_H_ */ diff --git a/sys/dev/mpt/mpt_debug.c b/sys/dev/mpt/mpt_debug.c index c43a557ead2b..8027295862ce 100644 --- a/sys/dev/mpt/mpt_debug.c +++ b/sys/dev/mpt/mpt_debug.c @@ -30,7 +30,7 @@ * Additional Copyright (c) 2002 by Matthew Jacob under same license. */ -#include +#include struct Error_Map { int Error_Code; @@ -324,7 +324,7 @@ mpt_print_ioc_facts(MSG_IOC_FACTS_REPLY *msg) printf("\tFlags %d\n", msg->Flags); printf("\tReplyQueueDepth %d\n", msg->ReplyQueueDepth); printf("\tReqFrameSize 0x%04x\n", msg->RequestFrameSize); - printf("\tFW Version 0x%04x\n", msg->FWVersion); + printf("\tFW Version 0x%08x\n", msg->FWVersion.Word); printf("\tProduct ID 0x%04x\n", msg->ProductID); printf("\tCredits 0x%04x\n", msg->GlobalCredits); printf("\tPorts %d\n", msg->NumberOfPorts); diff --git a/sys/dev/mpt/mpt_freebsd.c b/sys/dev/mpt/mpt_freebsd.c index 5fb611531cb8..4380724079e4 100644 --- a/sys/dev/mpt/mpt_freebsd.c +++ b/sys/dev/mpt/mpt_freebsd.c @@ -31,20 +31,13 @@ */ #include -#include -#include -#include -#if 0 -static void mpt_cam_async(void *, u_int32_t, struct cam_path *, void *); -static void mpt_intr_enable(void *); -#endif static void mpt_poll(struct cam_sim *); static timeout_t mpttimeout; static void mpt_action(struct cam_sim *, union ccb *); void -mpt_cam_attach(struct mpt_softc *mpt) +mpt_cam_attach(mpt_softc_t *mpt) { struct cam_devq *devq; struct cam_sim *sim; @@ -52,7 +45,7 @@ mpt_cam_attach(struct mpt_softc *mpt) mpt->bus = 0; maxq = (mpt->mpt_global_credits < MPT_MAX_REQUESTS)? - mpt->mpt_global_credits : MPT_MAX_REQUESTS; + mpt->mpt_global_credits : MPT_MAX_REQUESTS; /* @@ -74,19 +67,10 @@ mpt_cam_attach(struct mpt_softc *mpt) return; } -#if 0 - mpt->mpt_osinfo.ehook.ich_func = mpt_intr_enable; - mpt->mpt_osinfo.ehook.ich_arg = mpt; - if (config_intrhook_establish(&mpt->mpt_osinfo.ehook) != 0) { - device_printf(mpt->dev, - "could not establish interrupt enable hook\n"); - cam_sim_free(sim, TRUE); - return; - } -#endif + /* + * Register exactly the bus. + */ - /* Register exactly one bus */ - /* (Duals look like two cards to us) */ if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { cam_sim_free(sim, TRUE); return; @@ -98,22 +82,11 @@ mpt_cam_attach(struct mpt_softc *mpt) cam_sim_free(sim, TRUE); return; } - -#if 0 /* GJA Don't think we care about lost devices */ - struct ccb_setasync csa; - - xpt_setup_ccb(&csa.ccb_h, mpt->path, 5); - csa.ccb_h.func_code = XPT_SASYNC_CB; - csa.event_enable = AC_LOST_DEVICE; - csa.callback = mpt_cam_async; - csa.callback_arg = sim; - xpt_action((union ccb *)&csa); -#endif mpt->sim = sim; } void -mpt_cam_detach(struct mpt_softc *mpt) +mpt_cam_detach(mpt_softc_t *mpt) { if (mpt->sim != NULL) { xpt_free_path(mpt->path); @@ -123,59 +96,16 @@ mpt_cam_detach(struct mpt_softc *mpt) } } -#if 0 -/* Sample routine for processing async events from CAM */ -static void -mpt_cam_async(void *cbarg, u_int32_t code, struct cam_path *path, void *arg) -{ - struct cam_sim *sim; - struct mpt_softc *mpt; - - sim = (struct cam_sim *)cbarg; - mpt = (struct mpt_softc *) cam_sim_softc(sim); - switch (code) { -#if 0 /* GJA */ - case AC_LOST_DEVICE: - if (IS_SCSI(mpt)) { - u_int16_t oflags, nflags; - sdparam *sdp = mpt->mpt_param; - int rvf, tgt; - - tgt = xpt_path_target_id(path); - rvf = ISP_FW_REVX(mpt->mpt_fwrev); - ISP_LOCK(mpt); - sdp += cam_sim_bus(sim); - mpt->mpt_update |= (1 << cam_sim_bus(sim)); - nflags = DPARM_SAFE_DFLT; - if (rvf >= ISP_FW_REV(7, 55, 0) || - (ISP_FW_REV(4, 55, 0) <= rvf && - (rvf < ISP_FW_REV(5, 0, 0)))) { - nflags |= DPARM_NARROW | DPARM_ASYNC; - } - oflags = sdp->mpt_devparam[tgt].dev_flags; - sdp->mpt_devparam[tgt].dev_flags = nflags; - sdp->mpt_devparam[tgt].dev_update = 1; - (void) mpt_control(mpt, ISPCTL_UPDATE_PARAMS, NULL); - sdp->mpt_devparam[tgt].dev_flags = oflags; - ISP_UNLOCK(mpt); - } - break; -#endif /* 0 GJA */ - default: - device_printf(mpt->dev, - "mpt Async Code 0x%x\n", code); - break; - } -} -#endif - /* This routine is used after a system crash to dump core onto the * swap device. */ static void mpt_poll(struct cam_sim *sim) { - mpt_intr((struct mpt_softc *) cam_sim_softc(sim)); + mpt_softc_t *mpt = (mpt_softc_t *) cam_sim_softc(sim); + MPT_LOCK(mpt); + mpt_intr(mpt); + MPT_UNLOCK(mpt); } /* @@ -186,16 +116,17 @@ static void mpttimeout(void *arg) { request_t *req; - union ccb *ccb = arg; - struct mpt_softc *mpt; + union ccb *ccb = arg; + mpt_softc_t *mpt; mpt = ccb->ccb_h.ccb_mpt_ptr; + MPT_LOCK(mpt); + req = ccb->ccb_h.ccb_req_ptr; - mpt->timeouts++; - - device_printf(mpt->dev, "time out on request index = 0x%02x sequence = 0x%08x\n", - req->index, req->sequence); + device_printf(mpt->dev, + "time out on request index = 0x%02x sequence = 0x%08x\n", + req->index, req->sequence); mpt_check_doorbell(mpt); device_printf(mpt->dev, "Status %08X; Mask %08X; Doorbell %08X\n", mpt_read(mpt, MPT_OFFSET_INTR_STATUS), @@ -212,7 +143,9 @@ mpttimeout(void *arg) req->ccb = NULL; ccb->ccb_h.status = CAM_CMD_TIMEOUT; ccb->ccb_h.status |= CAM_RELEASE_SIMQ; + MPTLOCK_2_CAMLOCK(mpt); xpt_done(ccb); + CAMLOCK_2_MPTLOCK(mpt); } /* @@ -225,10 +158,9 @@ mpttimeout(void *arg) static void mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) { - int s; request_t *req; union ccb *ccb; - struct mpt_softc *mpt; + mpt_softc_t *mpt; MSG_SCSI_IO_REQUEST *mpt_req; SGE_SIMPLE32 *se; @@ -258,7 +190,9 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) ccb->ccb_h.status |= CAM_RELEASE_SIMQ; ccb->ccb_h.status &= ~CAM_SIM_QUEUED; xpt_done(ccb); + CAMLOCK_2_MPTLOCK(mpt); mpt_free_request(mpt, req); + MPTLOCK_2_CAMLOCK(mpt); return; } @@ -389,18 +323,18 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) MPI_SGE_FLAGS_SIMPLE_ELEMENT | MPI_SGE_FLAGS_END_OF_LIST)); } - s = splcam(); /* * Last time we need to check if this CCB needs to be aborted. */ if (ccb->ccb_h.status != CAM_REQ_INPROG) { if (nseg && (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) == 0) bus_dmamap_unload(mpt->buffer_dmat, req->dmap); + CAMLOCK_2_MPTLOCK(mpt); mpt_free_request(mpt, req); + MPTLOCK_2_CAMLOCK(mpt); ccb->ccb_h.status |= CAM_RELEASE_SIMQ; ccb->ccb_h.status &= ~CAM_SIM_QUEUED; xpt_done(ccb); - splx(s); return; } @@ -412,13 +346,11 @@ mpt_execute_req(void *arg, bus_dma_segment_t *dm_segs, int nseg, int error) } else { callout_handle_init(&ccb->ccb_h.timeout_ch); } - if (mpt->verbose > 1) mpt_print_scsi_io_request(mpt_req); - + CAMLOCK_2_MPTLOCK(mpt); mpt_send_cmd(mpt, req); - - splx(s); + MPTLOCK_2_CAMLOCK(mpt); } /* Convert a CAM SCSI I/O ccb into a MPT request to pass the FC Chip */ @@ -436,9 +368,12 @@ mpt_start(union ccb *ccb) mpt = ccb->ccb_h.ccb_mpt_ptr; /* Get a request structure off the free list */ + CAMLOCK_2_MPTLOCK(mpt); if ((req = mpt_get_request(mpt)) == NULL) { + MPTLOCK_2_CAMLOCK(mpt); return (CAM_REQUEUE_REQ); } + MPTLOCK_2_CAMLOCK(mpt); /* Link the ccb and the request structure so we can find */ /* the other knowing either the request or the ccb */ @@ -580,7 +515,7 @@ mpt_bus_reset(union ccb *ccb) { int error; request_t *req; - struct mpt_softc *mpt; + mpt_softc_t *mpt; MSG_SCSI_TASK_MGMT *reset_req; /* Get the pointer for the physical adapter */ @@ -630,7 +565,7 @@ mpt_bus_reset(union ccb *ccb) * Process an asynchronous event from the IOC. */ void -mpt_notify(struct mpt_softc *mpt, void *vmsg) +mpt_notify(mpt_softc_t *mpt, void *vmsg, u_int32_t reply) { MSG_DEFAULT_REPLY *dmsg = vmsg; @@ -759,6 +694,7 @@ mpt_notify(struct mpt_softc *mpt, void *vmsg) default: device_printf(mpt->dev, "Unknown event %X\n", msg->Event); } + mpt_free_reply(mpt, (reply << 1)); } else if (dmsg->Function == MPI_FUNCTION_PORT_ENABLE) { MSG_PORT_ENABLE_REPLY *msg = vmsg; int index = msg->MsgContext & ~0x80000000; @@ -770,6 +706,17 @@ mpt_notify(struct mpt_softc *mpt, void *vmsg) request_t *req = &mpt->requests[index]; req->debug = REQ_DONE; } + mpt_free_reply(mpt, (reply << 1)); + } else if (dmsg->Function == MPI_FUNCTION_CONFIG) { + MSG_CONFIG_REPLY *msg = vmsg; + int index = msg->MsgContext & ~0x80000000; + if (index >= 0 && index < MPT_MAX_REQUESTS) { + request_t *req = &mpt->requests[index]; + req->debug = REQ_DONE; + req->sequence = reply; + } else { + mpt_free_reply(mpt, (reply << 1)); + } } else { device_printf(mpt->dev, "unknown mpt_notify: %x\n", dmsg->Function); @@ -777,7 +724,7 @@ mpt_notify(struct mpt_softc *mpt, void *vmsg) } void -mpt_done(struct mpt_softc *mpt, u_int32_t reply) +mpt_done(mpt_softc_t *mpt, u_int32_t reply) { int index; request_t *req; @@ -817,8 +764,7 @@ mpt_done(struct mpt_softc *mpt, u_int32_t reply) /* to process it then free it */ if ((index & 0x80000000) != 0) { if (mpt_reply != NULL) { - mpt_notify(mpt, mpt_reply); - mpt_free_reply(mpt, (reply << 1)); + mpt_notify(mpt, mpt_reply, reply); } else { device_printf(mpt->dev, "mpt_done: index 0x%x, NULL reply\n", index); @@ -1016,7 +962,9 @@ mpt_done(struct mpt_softc *mpt, u_int32_t reply) if ((mpt_reply->MsgFlags & 0x80) == 0) ccb->ccb_h.status |= CAM_RELEASE_SIMQ; ccb->ccb_h.status &= ~CAM_SIM_QUEUED; + MPTLOCK_2_CAMLOCK(mpt); xpt_done(ccb); + CAMLOCK_2_MPTLOCK(mpt); done: /* If IOC done with this request free it up */ @@ -1032,12 +980,12 @@ static void mpt_action(struct cam_sim *sim, union ccb *ccb) { int tgt, error; - struct mpt_softc *mpt; + mpt_softc_t *mpt; struct ccb_trans_settings *cts; CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("mpt_action\n")); - mpt = (struct mpt_softc *)cam_sim_softc(sim); + mpt = (mpt_softc_t *)cam_sim_softc(sim); ccb->ccb_h.ccb_mpt_ptr = mpt; @@ -1045,16 +993,15 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) case XPT_RESET_BUS: if (mpt->verbose > 1) device_printf(mpt->dev, "XPT_RESET_BUS\n"); + CAMLOCK_2_MPTLOCK(mpt); error = mpt_bus_reset(ccb); + MPTLOCK_2_CAMLOCK(mpt); switch (error) { case CAM_REQ_INPROG: ccb->ccb_h.status |= CAM_SIM_QUEUED; break; case CAM_REQUEUE_REQ: - /* if (mpt->mpt_osinfo.simqfrozen == 0) */ - { - xpt_freeze_simq(sim, 1); - } + xpt_freeze_simq(sim, 1); ccb->ccb_h.status = CAM_REQUEUE_REQ; xpt_done(ccb); break; @@ -1090,20 +1037,14 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) } ccb->csio.scsi_status = SCSI_STATUS_OK; - /* XXX GJA MPT_LOCK(mpt); */ error = mpt_start(ccb); - /* XXX GJA MPT_UNLOCK(mpt); */ switch (error) { case CAM_REQ_INPROG: ccb->ccb_h.status |= CAM_SIM_QUEUED; break; case CAM_REQUEUE_REQ: - /* if (mpt->mpt_osinfo.simqfrozen == 0) */ - { - xpt_freeze_simq(sim, 1); - } - /* mpt->mpt_osinfo.simqfrozen |= SIMQFRZ_RESOURCE; */ + xpt_freeze_simq(sim, 1); ccb->ccb_h.status = CAM_REQUEUE_REQ; xpt_done(ccb); break; @@ -1114,21 +1055,36 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) break; default: - device_printf(mpt->dev, "What's this? 0x%x at %d in file %s\n", - error, __LINE__, __FILE__); ccb->ccb_h.status = CAM_REQ_CMP_ERR; xpt_done(ccb); } break; case XPT_ABORT: - /* Probably ought to impliment this but no one actualy */ - /* uses it for anything worthwile. XXX GJA */ + /* + * XXX: Need to implement + */ ccb->ccb_h.status = CAM_UA_ABORT; xpt_done(ccb); break; - + +#ifdef CAM_NEW_TRAN_CODE +#define IS_CURRENT_SETTINGS(c) (c->type == CTS_TYPE_CURRENT_SETTINGS) +#else +#define IS_CURRENT_SETTINGS(c) (c->flags & CCB_TRANS_CURRENT_SETTINGS) +#endif +#define DP_DISC 0x1 +#define DP_TQING 0x2 +#define DP_WIDE 0x4 + case XPT_SET_TRAN_SETTINGS: /* Nexus Settings */ + cts = &ccb->cts; + if (!IS_CURRENT_SETTINGS(cts)) { + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; + } + /* XXX: need to implement */ ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -1136,19 +1092,136 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) case XPT_GET_TRAN_SETTINGS: cts = &ccb->cts; tgt = cts->ccb_h.target_id; - /* - * a lot of normal SCSI things don't make sense. - */ - cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB; - cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; - /* - * How do you measure the width of a high - * speed serial bus? Well, in bytes. - * - * Offset and period make no sense, though, so we set - * (above) a 'base' transfer speed to be gigabit. - */ - cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + if (mpt->is_fc) { +#ifndef CAM_NEW_TRAN_CODE + /* + * a lot of normal SCSI things don't make sense. + */ + cts->flags = CCB_TRANS_TAG_ENB | CCB_TRANS_DISC_ENB; + cts->valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; + /* + * How do you measure the width of a high + * speed serial bus? Well, in bytes. + * + * Offset and period make no sense, though, so we set + * (above) a 'base' transfer speed to be gigabit. + */ + cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; +#else + struct ccb_trans_settings_fc *fc = + &cts->xport_specific.fc; + + cts->protocol = PROTO_SCSI; + cts->protocol_version = SCSI_REV_2; + cts->transport = XPORT_FC; + cts->transport_version = 0; + + fc->valid = CTS_FC_VALID_SPEED; + fc->bitrate = 100000; /* XXX: Need for 2Gb/s */ + /* XXX: need a port database for each target */ +#endif + } else { +#ifdef CAM_NEW_TRAN_CODE + struct ccb_trans_settings_scsi *scsi = + &cts->proto_specific.scsi; + struct ccb_trans_settings_spi *spi = + &cts->xport_specific.spi; +#endif + u_int8_t dval, pval, oval; + + if (IS_CURRENT_SETTINGS(cts)) { + dval = 0; + if (mpt->mpt_dev_page0[tgt]. + NegotiatedParameters & + MPI_SCSIDEVPAGE0_NP_WIDE) + dval |= DP_WIDE; + + if (mpt->mpt_port_page2.DeviceSettings[tgt]. + DeviceFlags & + MPI_SCSIPORTPAGE2_DEVICE_DISCONNECT_ENABLE) + dval |= DP_DISC; + + if (mpt->mpt_port_page2.DeviceSettings[tgt]. + DeviceFlags & + MPI_SCSIPORTPAGE2_DEVICE_TAG_QUEUE_ENABLE) + dval |= DP_TQING; + + oval = (mpt->mpt_dev_page0[tgt]. + NegotiatedParameters >> 16); + pval = (mpt->mpt_dev_page0[tgt]. + NegotiatedParameters >> 8); + } else { + /* + * XXX: Fix wrt NVRAM someday. Attempts + * XXX: to read port page2 device data + * XXX: just returns zero in these areas. + */ + dval = DP_WIDE|DP_DISC|DP_TQING; + oval = (mpt->mpt_port_page0.Capabilities >> 16); + pval = (mpt->mpt_port_page0.Capabilities >> 8); + } +#ifndef CAM_NEW_TRAN_CODE + cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB); + if (dval & DP_DISC) { + cts->flags |= CCB_TRANS_DISC_ENB; + } + if (dval & DP_TQING) { + cts->flags |= CCB_TRANS_TAG_ENB; + } + if (dval & DP_WIDE) { + cts->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + } else { + cts->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + } + cts->valid = CCB_TRANS_BUS_WIDTH_VALID | + CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID; + if (oval) { + cts->sync_period = pval; + cts->sync_offset = oval; + cts->valid |= + CCB_TRANS_SYNC_RATE_VALID | + CCB_TRANS_SYNC_OFFSET_VALID; + } +#else + cts->protocol = PROTO_SCSI; + cts->protocol_version = SCSI_REV_2; + cts->transport = XPORT_SPI; + cts->transport_version = 2; + + scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB; + spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB; + if (dval & DP_DISC) { + spi->flags |= CTS_SPI_FLAGS_DISC_ENB; + } + if (dval & DP_TQING) { + scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB; + } + if (oval && pval) { + spi->sync_offset = oval; + spi->sync_period = pval; + spi->valid |= CTS_SPI_VALID_SYNC_OFFSET; + spi->valid |= CTS_SPI_VALID_SYNC_RATE; + } + spi->valid |= CTS_SPI_VALID_BUS_WIDTH; + if (dval & DP_WIDE) { + spi->bus_width = MSG_EXT_WDTR_BUS_16_BIT; + } else { + spi->bus_width = MSG_EXT_WDTR_BUS_8_BIT; + } + if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) { + scsi->valid = CTS_SCSI_VALID_TQ; + spi->valid |= CTS_SPI_VALID_DISC; + } else { + scsi->valid = 0; + } +#endif + if (mpt->verbose > 1) { + device_printf(mpt->dev, + "GET %s targ %d flags %x off %x per %x\n", + IS_CURRENT_SETTINGS(cts)? "ACTIVE" : + "NVRAM", tgt, dval, oval, pval); + } + } ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); break; @@ -1161,10 +1234,6 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) ccg = &ccb->ccg; if (ccg->block_size == 0) { - device_printf(mpt->dev, "%d.%d XPT_CALC_GEOMETRY block size 0?\n", - ccg->ccb_h.target_id, - ccg->ccb_h.target_lun); - ccb->ccb_h.status = CAM_REQ_INVALID; xpt_done(ccb); break; @@ -1200,7 +1269,7 @@ mpt_action(struct cam_sim *sim, union ccb *ccb) cpi->base_transfer_speed = 100000; cpi->hba_inquiry = PI_TAG_ABLE; } else { - cpi->initiator_id = 7; /* XXX */ + cpi->initiator_id = mpt->mpt_ini_id; cpi->base_transfer_speed = 3300; cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; cpi->hba_misc = 0; diff --git a/sys/dev/mpt/mpt_freebsd.h b/sys/dev/mpt/mpt_freebsd.h index 216853a14a22..b3260c10df1c 100644 --- a/sys/dev/mpt/mpt_freebsd.h +++ b/sys/dev/mpt/mpt_freebsd.h @@ -31,15 +31,22 @@ #ifndef _MPT_FREEBSD_H_ #define _MPT_FREEBSD_H_ -#include -#ifdef _KERNEL +/* #define RELENG_4 1 */ + #include #include +#include #include #include +#ifdef RELENG_4 +#include +#else +#include #include #include +#include +#endif #include #include @@ -58,9 +65,50 @@ #include #include #include + #include "opt_ddb.h" + +#include "dev/mpt/mpilib/mpi_type.h" +#include "dev/mpt/mpilib/mpi.h" +#include "dev/mpt/mpilib/mpi_cnfg.h" +#include "dev/mpt/mpilib/mpi_fc.h" +#include "dev/mpt/mpilib/mpi_init.h" +#include "dev/mpt/mpilib/mpi_ioc.h" +#include "dev/mpt/mpilib/mpi_lan.h" +#include "dev/mpt/mpilib/mpi_targ.h" + + #define INLINE __inline +#ifdef RELENG_4 +#define MPT_IFLAGS INTR_TYPE_CAM +#define MPT_LOCK(mpt) mpt_lockspl(mpt) +#define MPT_UNLOCK(mpt) mpt_unlockspl(mpt) +#define MPTLOCK_2_CAMLOCK MPT_UNLOCK +#define CAMLOCK_2_MPTLOCK(mpt) MPT_LOCK +#define MPT_LOCK_SETUP(mpt) +#define MPT_LOCK_DESTROY(mpt) +#else +#define MPT_IFLAGS INTR_TYPE_CAM | INTR_ENTROPY | INTR_MPSAFE +#define MPT_LOCK_SETUP(mpt) \ + mtx_init(&mpt->mpt_lock, "mpt", NULL, MTX_DEF); \ + mpt->mpt_locksetup = 1 +#define MPT_LOCK_DESTROY(mpt) \ + if (mpt->mpt_locksetup) { \ + mtx_destroy(&mpt->mpt_lock); \ + mpt->mpt_locksetup = 0; \ + } + +#define MPT_LOCK(mpt) mtx_lock(&(mpt)->mpt_lock) +#define MPT_UNLOCK(mpt) mtx_unlock(&(mpt)->mpt_lock) +#define MPTLOCK_2_CAMLOCK(mpt) \ + mtx_unlock(&(mpt)->mpt_lock); mtx_lock(&Giant) +#define CAMLOCK_2_MPTLOCK(mpt) \ + mtx_unlock(&Giant); mtx_lock(&(mpt)->mpt_lock) +#endif + + + /* Max MPT Reply we are willing to accept (must be power of 2) */ #define MPT_REPLY_SIZE 128 @@ -112,17 +160,16 @@ enum mpt_req_state { REQ_FREE, REQ_IN_PROGRESS, REQ_TIMEOUT, REQ_ON_CHIP, REQ_DONE }; typedef struct req_entry { - u_int16_t index; /* Index of this entry */ - union ccb *ccb; /* Request that generated this command */ - void *req_vbuf; /* Virtual Address of Entry */ - void *sense_vbuf; /* Virtual Address of sense data */ - u_int32_t req_pbuf; /* Physical Address of Entry */ - u_int32_t sense_pbuf; /* Physical Address of sense data */ - bus_dmamap_t dmap; /* DMA map for data buffer */ - SLIST_ENTRY(req_entry) link; /* Pointer to next in list */ - enum mpt_req_state debug; /* Debuging */ - u_int32_t sequence; /* Sequence Number */ - + u_int16_t index; /* Index of this entry */ + union ccb *ccb; /* CAM request */ + void *req_vbuf; /* Virtual Address of Entry */ + void *sense_vbuf; /* Virtual Address of sense data */ + u_int32_t req_pbuf; /* Physical Address of Entry */ + u_int32_t sense_pbuf; /* Physical Address of sense data */ + bus_dmamap_t dmap; /* DMA map for data buffer */ + SLIST_ENTRY(req_entry) link; /* Pointer to next in list */ + enum mpt_req_state debug; /* Debugging */ + u_int32_t sequence; /* Sequence Number */ } request_t; @@ -138,98 +185,162 @@ struct mpt_pci_cfg { u_int32_t PMCSR; }; -struct mpt_softc { - device_t dev; - int unit; - struct mtx lock; - - /* Operational flags, set during initialization */ - int verbose; /* print debug messages */ - - struct resource *pci_irq; /* Interrupt map for chip */ - void *ih; /* Interupt handle */ - - /* First Memory Region (Device MEM) */ - struct resource *pci_reg; /* Register map for chip */ - int pci_reg_id; /* Resource ID */ - bus_space_tag_t pci_st; /* Bus tag for registers */ - bus_space_handle_t pci_sh; /* Bus handle for registers */ - vm_offset_t pci_pa; /* Physical Address */ - - /* Second Memory Region (Diagnostic memory window) */ - /* (only used for diagnostic purposes) */ - struct resource *pci_mem; /* Register map for chip */ - int pci_mem_id; /* Resource ID */ - bus_space_tag_t pci_mst; /* Bus tag for registers */ - bus_space_handle_t pci_msh; /* Bus handle for registers */ - - /* DMA Memory for IOCTLs */ - void *ioctl_mem_va; /* Virtual Addr */ - u_int32_t ioctl_mem_pa; /* Physical Addr */ - bus_dmamap_t ioctl_mem_map; /* DMA map for buffer */ - bus_dma_tag_t ioctl_mem_tag; /* DMA tag for memory alloc */ - int open; /* only allow one open at a time */ - - bus_dma_tag_t parent_dmat; /* DMA tag for parent PCI bus */ - - bus_dma_tag_t reply_dmat; /* DMA tag for reply memory */ - bus_dmamap_t reply_dmap; /* DMA map for reply memory */ - char *reply; /* Virtual address of reply memory */ - u_int32_t reply_phys; /* Physical address of reply memory */ - - u_int32_t - : 29, +typedef struct mpt_softc { + device_t dev; +#ifdef RELENG_4 + int mpt_splsaved; + u_int32_t mpt_islocked; +#else + struct mtx mpt_lock; +#endif + u_int32_t : 16, + unit : 8, + verbose : 3, + : 1, + mpt_locksetup : 1, disabled : 1, is_fc : 1, bus : 1; /* FC929/1030 have two busses */ - u_int32_t blk_size; /* Block size transfers to IOC */ - u_int16_t mpt_global_credits; - u_int16_t request_frame_size; + /* + * IOC Facts + */ + u_int16_t mpt_global_credits; + u_int16_t request_frame_size; + u_int8_t mpt_max_devices; + u_int8_t mpt_max_buses; - bus_dma_tag_t buffer_dmat; /* DMA tag for mapping data buffers */ + /* + * Port Facts + */ + u_int16_t mpt_ini_id; - bus_dma_tag_t request_dmat; /* DMA tag for request memroy */ - bus_dmamap_t request_dmap; /* DMA map for request memroy */ - char *request; /* Virtual address of Request memory */ - u_int32_t request_phys; /* Physical address of Request memory */ - request_t requests[MPT_MAX_REQUESTS]; + /* + * Device Configuration Information + */ + union { + struct mpt_spi_cfg { + fCONFIG_PAGE_SCSI_PORT_0 _port_page0; + fCONFIG_PAGE_SCSI_PORT_1 _port_page1; + fCONFIG_PAGE_SCSI_PORT_2 _port_page2; + fCONFIG_PAGE_SCSI_DEVICE_0 _dev_page0[16]; + fCONFIG_PAGE_SCSI_DEVICE_1 _dev_page1[16]; + uint16_t _tagmask; + uint16_t _update_params0; + uint16_t _update_params1; + } spi; +#define mpt_port_page0 cfg.spi._port_page0 +#define mpt_port_page1 cfg.spi._port_page1 +#define mpt_port_page2 cfg.spi._port_page2 +#define mpt_dev_page0 cfg.spi._dev_page0 +#define mpt_dev_page1 cfg.spi._dev_page1 +#define mpt_tagmask cfg.spi._tagmask +#define mpt_update_params0 cfg.spi._update_params0 +#define mpt_update_params1 cfg.spi._update_params1 + struct mpi_fc_cfg { + u_int8_t nada; + } fc; + } cfg; + + /* + * PCI Hardware info + */ + struct resource * pci_irq; /* Interrupt map for chip */ + void * ih; /* Interupt handle */ + struct mpt_pci_cfg pci_cfg; /* saved PCI conf registers */ + + /* + * DMA Mapping Stuff + */ + + struct resource * pci_reg; /* Register map for chip */ + int pci_reg_id; /* Resource ID */ + bus_space_tag_t pci_st; /* Bus tag for registers */ + bus_space_handle_t pci_sh; /* Bus handle for registers */ + vm_offset_t pci_pa; /* Physical Address */ + + bus_dma_tag_t parent_dmat; /* DMA tag for parent PCI bus */ + bus_dma_tag_t reply_dmat; /* DMA tag for reply memory */ + bus_dmamap_t reply_dmap; /* DMA map for reply memory */ + char * reply; /* KVA of reply memory */ + u_int32_t reply_phys; /* BusAddr of reply memory (XXX Wrong) */ + + + bus_dma_tag_t buffer_dmat; /* DMA tag for buffers */ + bus_dma_tag_t request_dmat; /* DMA tag for request memroy */ + bus_dmamap_t request_dmap; /* DMA map for request memroy */ + char * request; /* KVA of Request memory */ + u_int32_t request_phys; /* BusADdr of request memory (XXX WRONG) */ + + + /* + * CAM && Software Management + */ + + request_t requests[MPT_MAX_REQUESTS]; SLIST_HEAD(req_queue, req_entry) request_free_list; - struct cam_sim *sim; - struct cam_path *path; + struct cam_sim * sim; + struct cam_path * path; - u_int32_t sequence; /* Sequence Number */ - u_int32_t timeouts; /* timeout count */ - u_int32_t success; /* timeout successes afer timeout */ + u_int32_t sequence; /* Sequence Number */ + u_int32_t timeouts; /* timeout count */ + u_int32_t success; /* successes afer timeout */ - /* Opposing port in a 929, or NULL */ - struct mpt_softc *mpt2; + /* Opposing port in a 929 or 1030, or NULL */ + struct mpt_softc * mpt2; - /* Saved values for the PCI configuration registers */ - struct mpt_pci_cfg pci_cfg; -}; +} mpt_softc_t; + +#include + + +static INLINE void mpt_write(mpt_softc_t *, size_t, u_int32_t); +static INLINE u_int32_t mpt_read(mpt_softc_t *, int); static INLINE void -mpt_write(struct mpt_softc *mpt, size_t offset, u_int32_t val) +mpt_write(mpt_softc_t *mpt, size_t offset, u_int32_t val) { bus_space_write_4(mpt->pci_st, mpt->pci_sh, offset, val); } static INLINE u_int32_t -mpt_read(struct mpt_softc *mpt, int offset) +mpt_read(mpt_softc_t *mpt, int offset) { - return bus_space_read_4(mpt->pci_st, mpt->pci_sh, offset); + return (bus_space_read_4(mpt->pci_st, mpt->pci_sh, offset)); } -void mpt_cam_attach(struct mpt_softc *mpt); -void mpt_cam_detach(struct mpt_softc *mpt); -void mpt_done(struct mpt_softc *mpt, u_int32_t reply); -void mpt_notify(struct mpt_softc *mpt, void *vmsg); +void mpt_cam_attach(mpt_softc_t *); +void mpt_cam_detach(mpt_softc_t *); +void mpt_done(mpt_softc_t *, u_int32_t); +void mpt_notify(mpt_softc_t *, void *, u_int32_t); +void mpt_set_config_regs(mpt_softc_t *); -/* mpt_pci.c declarations */ -void mpt_set_config_regs(struct mpt_softc *mpt); +#ifdef RELENG_4 +static INLINE void mpt_lockspl(mpt_softc_t *); +static INLINE void mpt_unlockspl(mpt_softc_t *); + +static INLINE void +mpt_lockspl(mpt_softc_t *mpt) +{ + int s = splcam(); + if (mpt->mpt_islocked++ == 0) { + mpt->mpt_splsaved = s; + } else { + splx(s); + } +} + +static INLINE void +mpt_unlockspl(mpt_softc_t *mpt) +{ + if (mpt->mpt_islocked) { + if (--mpt->mpt_islocked == 0) { + splx(mpt->mpt_splsaved); + } + } +} +#endif -#endif /*_KERNEL */ #endif /* _MPT_FREEBSD_H */ diff --git a/sys/dev/mpt/mpt_pci.c b/sys/dev/mpt/mpt_pci.c index 7af1bc9660b7..6012eb45fd1d 100644 --- a/sys/dev/mpt/mpt_pci.c +++ b/sys/dev/mpt/mpt_pci.c @@ -34,11 +34,9 @@ #include #include #include -#include -#include -#include -#include #include +#include + #include #include @@ -47,8 +45,8 @@ #include #include #include +#include -#include #include #ifndef PCI_VENDOR_LSI @@ -74,12 +72,13 @@ static int mpt_probe(device_t); static int mpt_attach(device_t); -static void mpt_free_bus_resources(struct mpt_softc *mpt); +static void mpt_free_bus_resources(mpt_softc_t *mpt); static int mpt_detach(device_t); static int mpt_shutdown(device_t); -static int mpt_dma_mem_alloc(struct mpt_softc *mpt); -static void mpt_dma_mem_free(struct mpt_softc *mpt); -static void mpt_read_config_regs(struct mpt_softc *mpt); +static int mpt_dma_mem_alloc(mpt_softc_t *mpt); +static void mpt_dma_mem_free(mpt_softc_t *mpt); +static void mpt_read_config_regs(mpt_softc_t *mpt); +static void mpt_pci_intr(void *); static device_method_t mpt_methods[] = { /* Device interface */ @@ -91,7 +90,7 @@ static device_method_t mpt_methods[] = { }; static driver_t mpt_driver = { - "mpt", mpt_methods, sizeof (struct mpt_softc) + "mpt", mpt_methods, sizeof (mpt_softc_t) }; static devclass_t mpt_devclass; DRIVER_MODULE(mpt, pci, mpt_driver, mpt_devclass, 0, 0); @@ -101,7 +100,7 @@ int mpt_intr(void *dummy) { u_int32_t reply; - struct mpt_softc *mpt = (struct mpt_softc *)dummy; + mpt_softc_t *mpt = (mpt_softc_t *)dummy; reply = mpt_pop_reply_queue(mpt); while (reply != MPT_REPLY_EMPTY) { @@ -149,7 +148,7 @@ mpt_probe(device_t dev) #ifdef RELENG_4 static void -mpt_set_options(struct mpt_softc *mpt) +mpt_set_options(mpt_softc_t *mpt) { int bitmap; @@ -171,7 +170,7 @@ mpt_set_options(struct mpt_softc *mpt) } #else static void -mpt_set_options(struct mpt_softc *mpt) +mpt_set_options(mpt_softc_t *mpt) { int tval; @@ -194,15 +193,15 @@ mpt_attach(device_t dev) { int iqd; u_int32_t data, cmd; - struct mpt_softc *mpt; + mpt_softc_t *mpt; /* Allocate the softc structure */ - mpt = (struct mpt_softc*) device_get_softc(dev); + mpt = (mpt_softc_t*) device_get_softc(dev); if (mpt == NULL) { device_printf(dev, "cannot allocate softc\n"); return (ENOMEM); } - bzero(mpt, sizeof (struct mpt_softc)); + bzero(mpt, sizeof (mpt_softc_t)); switch ((pci_get_device(dev) & ~1)) { case PCI_PRODUCT_LSI_FC909: case PCI_PRODUCT_LSI_FC929: @@ -243,7 +242,7 @@ mpt_attach(device_t dev) if ((pci_get_device(dev) & ~1) == PCI_PRODUCT_LSI_FC929) { /* Yes; is the previous device the counterpart? */ if (mpt->unit) { - mpt->mpt2 = (struct mpt_softc *) + mpt->mpt2 = (mpt_softc_t *) devclass_get_softc(mpt_devclass, mpt->unit-1); if ((mpt->mpt2->mpt2 == NULL) @@ -285,13 +284,14 @@ mpt_attach(device_t dev) } /* Register the interrupt handler */ - if (bus_setup_intr(dev, mpt->pci_irq, - INTR_TYPE_CAM, (void (*)(void *))mpt_intr, + if (bus_setup_intr(dev, mpt->pci_irq, MPT_IFLAGS, mpt_pci_intr, mpt, &mpt->ih)) { device_printf(dev, "could not setup interrupt\n"); goto bad; } + MPT_LOCK_SETUP(mpt); + /* Disable interrupts at the part */ mpt_disable_ints(mpt); @@ -301,27 +301,35 @@ mpt_attach(device_t dev) goto bad; } - /* Initialize character device */ - /* currently closed */ - mpt->open = 0; + /* + * Save the PCI config register values + * + * Hard resets are known to screw up the BAR for diagnostic + * memory accesses (Mem1). + * + * Using Mem1 is known to make the chip stop responding to + * configuration space transfers, so we need to save it now + */ - /* Save the PCI config register values */ - /* Hard resets are known to screw up the BAR for diagnostic - memory accesses (Mem1). */ - /* Using Mem1 is known to make the chip stop responding to - configuration space transfers, so we need to save it now */ mpt_read_config_regs(mpt); /* Initialize the hardware */ if (mpt->disabled == 0) { - if (mpt_init(mpt, MPT_DB_INIT_HOST) != 0) + MPT_LOCK(mpt); + if (mpt_init(mpt, MPT_DB_INIT_HOST) != 0) { + MPT_UNLOCK(mpt); goto bad; + } - /* Attach to CAM */ + /* + * Attach to CAM + */ + MPTLOCK_2_CAMLOCK(mpt); mpt_cam_attach(mpt); + CAMLOCK_2_MPTLOCK(mpt); + MPT_UNLOCK(mpt); } - /* Done */ return (0); bad: @@ -334,11 +342,11 @@ mpt_attach(device_t dev) return (0); } -/****************************************************************************** +/* * Free bus resources */ static void -mpt_free_bus_resources(struct mpt_softc *mpt) +mpt_free_bus_resources(mpt_softc_t *mpt) { if (mpt->ih) { bus_teardown_intr(mpt->dev, mpt->pci_irq, mpt->ih); @@ -355,23 +363,18 @@ mpt_free_bus_resources(struct mpt_softc *mpt) mpt->pci_reg); mpt->pci_reg = 0; } - if (mpt->pci_mem) { - bus_release_resource(mpt->dev, SYS_RES_MEMORY, mpt->pci_mem_id, - mpt->pci_mem); - mpt->pci_mem = 0; - } - + MPT_LOCK_DESTROY(mpt); } -/****************************************************************************** +/* * Disconnect ourselves from the system. */ static int mpt_detach(device_t dev) { - struct mpt_softc *mpt; - mpt = (struct mpt_softc*) device_get_softc(dev); + mpt_softc_t *mpt; + mpt = (mpt_softc_t*) device_get_softc(dev); device_printf(mpt->dev,"mpt_detach!\n"); @@ -386,14 +389,14 @@ mpt_detach(device_t dev) } -/****************************************************************************** +/* * Disable the hardware */ static int mpt_shutdown(device_t dev) { - struct mpt_softc *mpt; - mpt = (struct mpt_softc*) device_get_softc(dev); + mpt_softc_t *mpt; + mpt = (mpt_softc_t*) device_get_softc(dev); if (mpt) { mpt_reset(mpt); @@ -403,7 +406,7 @@ mpt_shutdown(device_t dev) struct imush { - struct mpt_softc *mpt; + mpt_softc_t *mpt; int error; u_int32_t phys; }; @@ -418,7 +421,7 @@ mpt_map_rquest(void *arg, bus_dma_segment_t *segs, int nseg, int error) static int -mpt_dma_mem_alloc(struct mpt_softc *mpt) +mpt_dma_mem_alloc(mpt_softc_t *mpt) { int i, error; u_char *vptr; @@ -551,7 +554,7 @@ mpt_dma_mem_alloc(struct mpt_softc *mpt) /* Deallocate memory that was allocated by mpt_dma_mem_alloc */ static void -mpt_dma_mem_free(struct mpt_softc *mpt) +mpt_dma_mem_free(mpt_softc_t *mpt) { int i; @@ -581,7 +584,7 @@ mpt_dma_mem_free(struct mpt_softc *mpt) /* Reads modifiable (via PCI transactions) config registers */ static void -mpt_read_config_regs(struct mpt_softc *mpt) +mpt_read_config_regs(mpt_softc_t *mpt) { mpt->pci_cfg.Command = pci_read_config(mpt->dev, PCIR_COMMAND, 2); mpt->pci_cfg.LatencyTimer_LineSize = @@ -598,7 +601,7 @@ mpt_read_config_regs(struct mpt_softc *mpt) /* Sets modifiable config registers */ void -mpt_set_config_regs(struct mpt_softc *mpt) +mpt_set_config_regs(mpt_softc_t *mpt) { u_int32_t val; @@ -636,3 +639,12 @@ mpt_set_config_regs(struct mpt_softc *mpt) pci_write_config(mpt->dev, PCIR_INTLINE, mpt->pci_cfg.IntLine, 1); pci_write_config(mpt->dev, 0x44, mpt->pci_cfg.PMCSR, 4); } + +static void +mpt_pci_intr(void *arg) +{ + mpt_softc_t *mpt = arg; + MPT_LOCK(mpt); + mpt_intr(mpt); + MPT_UNLOCK(mpt); +}