summaryrefslogtreecommitdiffstats
path: root/sys/dev/mpt
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2002-08-20 23:04:08 +0000
committermjacob <mjacob@FreeBSD.org>2002-08-20 23:04:08 +0000
commit725cb72df39820df1b14daad7996dc7b4a8dfd90 (patch)
tree5c5d2a5103fb47cc1d2f8cbfdbb36538695a037d /sys/dev/mpt
parenta79225f8d012279922811f7bbd81e29b24fd07a4 (diff)
downloadFreeBSD-src-725cb72df39820df1b14daad7996dc7b4a8dfd90.zip
FreeBSD-src-725cb72df39820df1b14daad7996dc7b4a8dfd90.tar.gz
A chunk of cleanup, both stylistic and substantive.
We now also read configuration information for the SCSI cards- this allows us to try and say what the speed settings now are. Start, but not yet complete, the process of reorgs && #defines so that we can backport to RELENG_4 pretty soon.
Diffstat (limited to 'sys/dev/mpt')
-rw-r--r--sys/dev/mpt/mpt.c575
-rw-r--r--sys/dev/mpt/mpt.h44
-rw-r--r--sys/dev/mpt/mpt_debug.c4
-rw-r--r--sys/dev/mpt/mpt_freebsd.c339
-rw-r--r--sys/dev/mpt/mpt_freebsd.h279
-rw-r--r--sys/dev/mpt/mpt_pci.c110
6 files changed, 1021 insertions, 330 deletions
diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c
index ebdc222..445f884 100644
--- a/sys/dev/mpt/mpt.c
+++ b/sys/dev/mpt/mpt.c
@@ -31,7 +31,7 @@
*/
#include <dev/mpt/mpt_freebsd.h>
-#include <dev/mpt/mpt.h>
+
#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_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_send_port_enable(struct mpt_softc *mpt, int port)
+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 feb541e..2ec76e3 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);
-
-
-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);
+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(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 c43a557..8027295 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 <dev/mpt/mpt.h>
+#include <dev/mpt/mpt_freebsd.h>
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 5fb6115..4380724 100644
--- a/sys/dev/mpt/mpt_freebsd.c
+++ b/sys/dev/mpt/mpt_freebsd.c
@@ -31,20 +31,13 @@
*/
#include <dev/mpt/mpt_freebsd.h>
-#include <dev/mpt/mpt.h>
-#include <machine/stdarg.h>
-#include <sys/signal.h>
-#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;
- req = ccb->ccb_h.ccb_req_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 216853a..b3260c1 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 <sys/ioccom.h>
-#ifdef _KERNEL
+/* #define RELENG_4 1 */
+
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/endian.h>
#include <sys/kernel.h>
#include <sys/queue.h>
+#ifdef RELENG_4
+#include <sys/malloc.h>
+#else
+#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mutex.h>
+#include <sys/condvar.h>
+#endif
#include <sys/proc.h>
#include <sys/bus.h>
@@ -58,9 +65,50 @@
#include <cam/cam_debug.h>
#include <cam/scsi/scsi_all.h>
#include <cam/scsi/scsi_message.h>
+
#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;
+
+ /*
+ * Port Facts
+ */
+ u_int16_t mpt_ini_id;
+
+
+ /*
+ * 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;
- bus_dma_tag_t buffer_dmat; /* DMA tag for mapping data buffers */
+ struct cam_sim * sim;
+ struct cam_path * path;
- 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 */
+ u_int32_t sequence; /* Sequence Number */
+ u_int32_t timeouts; /* timeout count */
+ u_int32_t success; /* successes afer timeout */
- request_t requests[MPT_MAX_REQUESTS];
- SLIST_HEAD(req_queue, req_entry) request_free_list;
+ /* Opposing port in a 929 or 1030, or NULL */
+ struct mpt_softc * mpt2;
- struct cam_sim *sim;
- struct cam_path *path;
+} mpt_softc_t;
- u_int32_t sequence; /* Sequence Number */
- u_int32_t timeouts; /* timeout count */
- u_int32_t success; /* timeout successes afer timeout */
+#include <dev/mpt/mpt.h>
- /* Opposing port in a 929, or NULL */
- struct mpt_softc *mpt2;
- /* Saved values for the PCI configuration registers */
- struct mpt_pci_cfg pci_cfg;
-};
+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 *);
+
+#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);
+ }
+}
-/* mpt_pci.c declarations */
-void mpt_set_config_regs(struct mpt_softc *mpt);
+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 7af1bc9..6012eb4 100644
--- a/sys/dev/mpt/mpt_pci.c
+++ b/sys/dev/mpt/mpt_pci.c
@@ -34,11 +34,9 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
-#include <sys/malloc.h>
-#include <sys/mbuf.h>
#include <sys/module.h>
+#include <sys/bus.h>
+
#include <pci/pcireg.h>
#include <pci/pcivar.h>
@@ -47,8 +45,8 @@
#include <machine/bus.h>
#include <machine/resource.h>
#include <sys/rman.h>
+#include <sys/malloc.h>
-#include <dev/mpt/mpt.h>
#include <dev/mpt/mpt_freebsd.h>
#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 @@ bad:
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);
+}
OpenPOWER on IntegriCloud