summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/mpt/mpt.c527
-rw-r--r--sys/dev/mpt/mpt.h55
-rw-r--r--sys/dev/mpt/mpt_cam.c23
-rw-r--r--sys/dev/mpt/mpt_debug.c8
-rw-r--r--sys/dev/mpt/mpt_raid.c61
5 files changed, 389 insertions, 285 deletions
diff --git a/sys/dev/mpt/mpt.c b/sys/dev/mpt/mpt.c
index 48c6baa..cf5c3f5 100644
--- a/sys/dev/mpt/mpt.c
+++ b/sys/dev/mpt/mpt.c
@@ -128,7 +128,7 @@ static void mpt_send_event_ack(struct mpt_softc *mpt, request_t *ack_req,
static int mpt_send_event_request(struct mpt_softc *mpt, int onoff);
static int mpt_soft_reset(struct mpt_softc *mpt);
static void mpt_hard_reset(struct mpt_softc *mpt);
-static int mpt_configure_ioc(struct mpt_softc *mpt);
+static int mpt_configure_ioc(struct mpt_softc *mpt, int, int);
static int mpt_enable_ioc(struct mpt_softc *mpt, int);
/************************* Personality Module Support *************************/
@@ -1484,25 +1484,27 @@ mpt_get_iocfacts(struct mpt_softc *mpt, MSG_IOC_FACTS_REPLY *freplp)
f_req.Function = MPI_FUNCTION_IOC_FACTS;
f_req.MsgContext = htole32(MPT_REPLY_HANDLER_HANDSHAKE);
error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
- if (error)
+ if (error) {
return(error);
+ }
error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
return (error);
}
static int
-mpt_get_portfacts(struct mpt_softc *mpt, MSG_PORT_FACTS_REPLY *freplp)
+mpt_get_portfacts(struct mpt_softc *mpt, U8 port, MSG_PORT_FACTS_REPLY *freplp)
{
MSG_PORT_FACTS f_req;
int error;
- /* XXX: Only getting PORT FACTS for Port 0 */
memset(&f_req, 0, sizeof f_req);
f_req.Function = MPI_FUNCTION_PORT_FACTS;
+ f_req.PortNumber = port;
f_req.MsgContext = htole32(MPT_REPLY_HANDLER_HANDSHAKE);
error = mpt_send_handshake_cmd(mpt, sizeof f_req, &f_req);
- if (error)
+ if (error) {
return(error);
+ }
error = mpt_recv_handshake_reply(mpt, sizeof (*freplp), freplp);
return (error);
}
@@ -1523,8 +1525,8 @@ mpt_send_ioc_init(struct mpt_softc *mpt, uint32_t who)
memset(&init, 0, sizeof init);
init.WhoInit = who;
init.Function = MPI_FUNCTION_IOC_INIT;
- init.MaxDevices = mpt->mpt_max_devices;
- init.MaxBuses = 1;
+ init.MaxDevices = 0; /* at least 256 devices per bus */
+ init.MaxBuses = 16; /* at least 16 busses */
init.MsgVersion = htole16(MPI_VERSION);
init.HeaderVersion = htole16(MPI_HEADER_VERSION);
@@ -1759,17 +1761,10 @@ mpt_read_config_info_ioc(struct mpt_softc *mpt)
return (rv);
}
-#if __FreeBSD_version >= 500000
- mpt_lprt(mpt, MPT_PRT_DEBUG, "IOC Page 2 Header: ver %x, len %zx, "
- "num %x, type %x\n", hdr.PageVersion,
- hdr.PageLength * sizeof(uint32_t),
- hdr.PageNumber, hdr.PageType);
-#else
- mpt_lprt(mpt, MPT_PRT_DEBUG, "IOC Page 2 Header: ver %x, len %z, "
- "num %x, type %x\n", hdr.PageVersion,
- hdr.PageLength * sizeof(uint32_t),
- hdr.PageNumber, hdr.PageType);
-#endif
+ mpt_lprt(mpt, MPT_PRT_DEBUG,
+ "IOC Page 2 Header: Version %x len %x PageNumber %x PageType %x\n",
+ hdr.PageVersion, hdr.PageLength << 2,
+ hdr.PageNumber, hdr.PageType);
len = hdr.PageLength * sizeof(uint32_t);
mpt->ioc_page2 = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
@@ -1786,6 +1781,7 @@ mpt_read_config_info_ioc(struct mpt_softc *mpt)
mpt_raid_free_mem(mpt);
return (EIO);
}
+ mpt2host_config_page_ioc2(mpt->ioc_page2);
if (mpt->ioc_page2->CapabilitiesFlags != 0) {
uint32_t mask;
@@ -2107,11 +2103,8 @@ int
mpt_core_attach(struct mpt_softc *mpt)
{
int val;
- int error;
-
LIST_INIT(&mpt->ack_frames);
-
/* Put all request buffers on the free list */
TAILQ_INIT(&mpt->request_pending_list);
TAILQ_INIT(&mpt->request_free_list);
@@ -2121,24 +2114,17 @@ mpt_core_attach(struct mpt_softc *mpt)
req->state = REQ_STATE_ALLOCATED;
mpt_free_request(mpt, req);
}
-
for (val = 0; val < MPT_MAX_LUNS; val++) {
STAILQ_INIT(&mpt->trt[val].atios);
STAILQ_INIT(&mpt->trt[val].inots);
}
STAILQ_INIT(&mpt->trt_wildcard.atios);
STAILQ_INIT(&mpt->trt_wildcard.inots);
-
mpt->scsi_tgt_handler_id = MPT_HANDLER_ID_NONE;
-
mpt_sysctl_attach(mpt);
-
mpt_lprt(mpt, MPT_PRT_DEBUG, "doorbell req = %s\n",
mpt_ioc_diag(mpt_read(mpt, MPT_OFFSET_DOORBELL)));
-
- error = mpt_configure_ioc(mpt);
-
- return (error);
+ return (mpt_configure_ioc(mpt, 0, 0));
}
int
@@ -2197,6 +2183,9 @@ mpt_core_shutdown(struct mpt_softc *mpt)
void
mpt_core_detach(struct mpt_softc *mpt)
{
+ /*
+ * XXX: FREE MEMORY
+ */
mpt_disable_ints(mpt);
}
@@ -2337,226 +2326,229 @@ mpt_download_fw(struct mpt_softc *mpt)
* once at instance startup.
*/
static int
-mpt_configure_ioc(struct mpt_softc *mpt)
+mpt_configure_ioc(struct mpt_softc *mpt, int tn, int needreset)
{
- MSG_PORT_FACTS_REPLY pfp;
- MSG_IOC_FACTS_REPLY facts;
- int try;
- int needreset;
- uint32_t max_chain_depth;
+ PTR_MSG_PORT_FACTS_REPLY pfp;
+ int error, port;
+ size_t len;
- needreset = 0;
- for (try = 0; try < MPT_MAX_TRYS; try++) {
+ if (tn == MPT_MAX_TRYS) {
+ return (-1);
+ }
- /*
- * No need to reset if the IOC is already in the READY state.
- *
- * Force reset if initialization failed previously.
- * Note that a hard_reset of the second channel of a '929
- * will stop operation of the first channel. Hopefully, if the
- * first channel is ok, the second will not require a hard
- * reset.
- */
- if (needreset || MPT_STATE(mpt_rd_db(mpt)) !=
- MPT_DB_STATE_READY) {
- if (mpt_reset(mpt, FALSE) != MPT_OK) {
- continue;
- }
+ /*
+ * No need to reset if the IOC is already in the READY state.
+ *
+ * Force reset if initialization failed previously.
+ * Note that a hard_reset of the second channel of a '929
+ * will stop operation of the first channel. Hopefully, if the
+ * first channel is ok, the second will not require a hard
+ * reset.
+ */
+ if (needreset || MPT_STATE(mpt_rd_db(mpt)) != MPT_DB_STATE_READY) {
+ if (mpt_reset(mpt, FALSE) != MPT_OK) {
+ return (mpt_configure_ioc(mpt, tn++, 1));
}
needreset = 0;
+ }
- if (mpt_get_iocfacts(mpt, &facts) != MPT_OK) {
- mpt_prt(mpt, "mpt_get_iocfacts failed\n");
- needreset = 1;
- continue;
- }
-
- mpt->mpt_global_credits = le16toh(facts.GlobalCredits);
- mpt->request_frame_size = le16toh(facts.RequestFrameSize);
- mpt->ioc_facts_flags = facts.Flags;
- mpt_prt(mpt, "MPI Version=%d.%d.%d.%d\n",
- le16toh(facts.MsgVersion) >> 8,
- le16toh(facts.MsgVersion) & 0xFF,
- le16toh(facts.HeaderVersion) >> 8,
- le16toh(facts.HeaderVersion) & 0xFF);
-
- /*
- * Now that we know request frame size, we can calculate
- * the actual (reasonable) segment limit for read/write I/O.
- *
- * This limit is constrained by:
- *
- * + The size of each area we allocate per command (and how
- * many chain segments we can fit into it).
- * + The total number of areas we've set up.
- * + The actual chain depth the card will allow.
- *
- * The first area's segment count is limited by the I/O request
- * at the head of it. We cannot allocate realistically more
- * than MPT_MAX_REQUESTS areas. Therefore, to account for both
- * conditions, we'll just start out with MPT_MAX_REQUESTS-2.
- *
- */
- max_chain_depth = facts.MaxChainDepth;
-
- /* total number of request areas we (can) allocate */
- mpt->max_seg_cnt = MPT_MAX_REQUESTS(mpt) - 2;
+ if (mpt_get_iocfacts(mpt, &mpt->ioc_facts) != MPT_OK) {
+ mpt_prt(mpt, "mpt_get_iocfacts failed\n");
+ return (mpt_configure_ioc(mpt, tn++, 1));
+ }
+ mpt2host_iocfacts_reply(&mpt->ioc_facts);
- /* converted to the number of chain areas possible */
- mpt->max_seg_cnt *= MPT_NRFM(mpt);
+ mpt_prt(mpt, "MPI Version=%d.%d.%d.%d\n",
+ mpt->ioc_facts.MsgVersion >> 8,
+ mpt->ioc_facts.MsgVersion & 0xFF,
+ mpt->ioc_facts.HeaderVersion >> 8,
+ mpt->ioc_facts.HeaderVersion & 0xFF);
- /* limited by the number of chain areas the card will support */
- if (mpt->max_seg_cnt > max_chain_depth) {
- mpt_lprt(mpt, MPT_PRT_DEBUG,
- "chain depth limited to %u (from %u)\n",
- max_chain_depth, mpt->max_seg_cnt);
- mpt->max_seg_cnt = max_chain_depth;
- }
+ /*
+ * Now that we know request frame size, we can calculate
+ * the actual (reasonable) segment limit for read/write I/O.
+ *
+ * This limit is constrained by:
+ *
+ * + The size of each area we allocate per command (and how
+ * many chain segments we can fit into it).
+ * + The total number of areas we've set up.
+ * + The actual chain depth the card will allow.
+ *
+ * The first area's segment count is limited by the I/O request
+ * at the head of it. We cannot allocate realistically more
+ * than MPT_MAX_REQUESTS areas. Therefore, to account for both
+ * conditions, we'll just start out with MPT_MAX_REQUESTS-2.
+ *
+ */
+ /* total number of request areas we (can) allocate */
+ mpt->max_seg_cnt = MPT_MAX_REQUESTS(mpt) - 2;
- /* converted to the number of simple sges in chain segments. */
- mpt->max_seg_cnt *= (MPT_NSGL(mpt) - 1);
+ /* converted to the number of chain areas possible */
+ mpt->max_seg_cnt *= MPT_NRFM(mpt);
+ /* limited by the number of chain areas the card will support */
+ if (mpt->max_seg_cnt > mpt->ioc_facts.MaxChainDepth) {
mpt_lprt(mpt, MPT_PRT_DEBUG,
- "Maximum Segment Count: %u\n", mpt->max_seg_cnt);
- mpt_lprt(mpt, MPT_PRT_DEBUG,
- "MsgLength=%u IOCNumber = %d\n",
- facts.MsgLength, facts.IOCNumber);
- mpt_lprt(mpt, MPT_PRT_DEBUG,
- "IOCFACTS: GlobalCredits=%d BlockSize=%u bytes "
- "Request Frame Size %u bytes Max Chain Depth %u\n",
- mpt->mpt_global_credits, facts.BlockSize,
- mpt->request_frame_size << 2, max_chain_depth);
- mpt_lprt(mpt, MPT_PRT_DEBUG,
- "IOCFACTS: Num Ports %d, FWImageSize %d, "
- "Flags=%#x\n", facts.NumberOfPorts,
- le32toh(facts.FWImageSize), facts.Flags);
+ "chain depth limited to %u (from %u)\n",
+ mpt->ioc_facts.MaxChainDepth, mpt->max_seg_cnt);
+ mpt->max_seg_cnt = mpt->ioc_facts.MaxChainDepth;
+ }
+
+ /* converted to the number of simple sges in chain segments. */
+ mpt->max_seg_cnt *= (MPT_NSGL(mpt) - 1);
+
+ mpt_lprt(mpt, MPT_PRT_DEBUG, "Maximum Segment Count: %u\n",
+ mpt->max_seg_cnt);
+ mpt_lprt(mpt, MPT_PRT_DEBUG, "MsgLength=%u IOCNumber = %d\n",
+ mpt->ioc_facts.MsgLength, mpt->ioc_facts.IOCNumber);
+ mpt_lprt(mpt, MPT_PRT_DEBUG,
+ "IOCFACTS: GlobalCredits=%d BlockSize=%u bytes "
+ "Request Frame Size %u bytes Max Chain Depth %u\n",
+ mpt->ioc_facts.GlobalCredits, mpt->ioc_facts.BlockSize,
+ mpt->ioc_facts.RequestFrameSize << 2,
+ mpt->ioc_facts.MaxChainDepth);
+ mpt_lprt(mpt, MPT_PRT_DEBUG, "IOCFACTS: Num Ports %d, FWImageSize %d, "
+ "Flags=%#x\n", mpt->ioc_facts.NumberOfPorts,
+ mpt->ioc_facts.FWImageSize, mpt->ioc_facts.Flags);
+
+ len = mpt->ioc_facts.NumberOfPorts * sizeof (MSG_PORT_FACTS_REPLY);
+ mpt->port_facts = malloc(len, M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (mpt->port_facts == NULL) {
+ mpt_prt(mpt, "unable to allocate memory for port facts\n");
+ return (ENOMEM);
+ }
- if ((facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) != 0) {
- struct mpt_map_info mi;
- int error;
+ if ((mpt->ioc_facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT) &&
+ (mpt->fw_uploaded == 0)) {
+ struct mpt_map_info mi;
- /*
- * In some configurations, the IOC's firmware is
- * stored in a shared piece of system NVRAM that
- * is only accessable via the BIOS. In this
- * case, the firmware keeps a copy of firmware in
- * RAM until the OS driver retrieves it. Once
- * retrieved, we are responsible for re-downloading
- * the firmware after any hard-reset.
- */
- mpt->fw_image_size = le32toh(facts.FWImageSize);
- error = mpt_dma_tag_create(mpt, mpt->parent_dmat,
- /*alignment*/1, /*boundary*/0,
- /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
- /*highaddr*/BUS_SPACE_MAXADDR, /*filter*/NULL,
- /*filterarg*/NULL, mpt->fw_image_size,
- /*nsegments*/1, /*maxsegsz*/mpt->fw_image_size,
- /*flags*/0, &mpt->fw_dmat);
- if (error != 0) {
- mpt_prt(mpt, "cannot create fw dma tag\n");
- return (ENOMEM);
- }
- error = bus_dmamem_alloc(mpt->fw_dmat,
- (void **)&mpt->fw_image, BUS_DMA_NOWAIT,
- &mpt->fw_dmap);
- if (error != 0) {
- mpt_prt(mpt, "cannot allocate fw mem.\n");
- bus_dma_tag_destroy(mpt->fw_dmat);
- return (ENOMEM);
- }
- mi.mpt = mpt;
- mi.error = 0;
- bus_dmamap_load(mpt->fw_dmat, mpt->fw_dmap,
- mpt->fw_image, mpt->fw_image_size, mpt_map_rquest,
- &mi, 0);
- mpt->fw_phys = mi.phys;
-
- error = mpt_upload_fw(mpt);
- if (error != 0) {
- mpt_prt(mpt, "fw upload failed.\n");
- bus_dmamap_unload(mpt->fw_dmat, mpt->fw_dmap);
- bus_dmamem_free(mpt->fw_dmat, mpt->fw_image,
- mpt->fw_dmap);
- bus_dma_tag_destroy(mpt->fw_dmat);
- mpt->fw_image = NULL;
- return (EIO);
- }
+ /*
+ * In some configurations, the IOC's firmware is
+ * stored in a shared piece of system NVRAM that
+ * is only accessable via the BIOS. In this
+ * case, the firmware keeps a copy of firmware in
+ * RAM until the OS driver retrieves it. Once
+ * retrieved, we are responsible for re-downloading
+ * the firmware after any hard-reset.
+ */
+ mpt->fw_image_size = mpt->ioc_facts.FWImageSize;
+ error = mpt_dma_tag_create(mpt, mpt->parent_dmat, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ mpt->fw_image_size, 1, mpt->fw_image_size, 0,
+ &mpt->fw_dmat);
+ if (error != 0) {
+ mpt_prt(mpt, "cannot create firmwarew dma tag\n");
+ return (ENOMEM);
}
-
- if (mpt_get_portfacts(mpt, &pfp) != MPT_OK) {
- mpt_prt(mpt, "mpt_get_portfacts failed\n");
- needreset = 1;
- continue;
+ error = bus_dmamem_alloc(mpt->fw_dmat,
+ (void **)&mpt->fw_image, BUS_DMA_NOWAIT, &mpt->fw_dmap);
+ if (error != 0) {
+ mpt_prt(mpt, "cannot allocate firmware memory\n");
+ bus_dma_tag_destroy(mpt->fw_dmat);
+ return (ENOMEM);
+ }
+ mi.mpt = mpt;
+ mi.error = 0;
+ bus_dmamap_load(mpt->fw_dmat, mpt->fw_dmap,
+ mpt->fw_image, mpt->fw_image_size, mpt_map_rquest, &mi, 0);
+ mpt->fw_phys = mi.phys;
+
+ error = mpt_upload_fw(mpt);
+ if (error != 0) {
+ mpt_prt(mpt, "firmware upload failed.\n");
+ bus_dmamap_unload(mpt->fw_dmat, mpt->fw_dmap);
+ bus_dmamem_free(mpt->fw_dmat, mpt->fw_image,
+ mpt->fw_dmap);
+ bus_dma_tag_destroy(mpt->fw_dmat);
+ mpt->fw_image = NULL;
+ return (EIO);
}
+ mpt->fw_uploaded = 1;
+ }
- mpt_lprt(mpt, MPT_PRT_DEBUG,
- "PORTFACTS: Type %x PFlags %x IID %d MaxDev %d\n",
- pfp.PortType, pfp.ProtocolFlags, pfp.PortSCSIID,
- pfp.MaxDevices);
-
- mpt->mpt_port_type = pfp.PortType;
- mpt->mpt_proto_flags = le16toh(pfp.ProtocolFlags);
- if (pfp.PortType != MPI_PORTFACTS_PORTTYPE_SCSI &&
- pfp.PortType != MPI_PORTFACTS_PORTTYPE_SAS &&
- pfp.PortType != MPI_PORTFACTS_PORTTYPE_FC) {
- mpt_prt(mpt, "Unsupported Port Type (%x)\n",
- pfp.PortType);
- return (ENXIO);
+ for (port = 0; port < mpt->ioc_facts.NumberOfPorts; port++) {
+ pfp = &mpt->port_facts[port];
+ error = mpt_get_portfacts(mpt, 0, pfp);
+ if (error != MPT_OK) {
+ mpt_prt(mpt,
+ "mpt_get_portfacts on port %d failed\n", port);
+ free(mpt->port_facts, M_DEVBUF);
+ mpt->port_facts = NULL;
+ return (mpt_configure_ioc(mpt, tn++, 1));
}
- mpt->mpt_max_tgtcmds = le16toh(pfp.MaxPostedCmdBuffers);
-
- if (pfp.PortType == MPI_PORTFACTS_PORTTYPE_FC) {
- mpt->is_fc = 1;
- mpt->is_sas = 0;
- mpt->is_spi = 0;
- } else if (pfp.PortType == MPI_PORTFACTS_PORTTYPE_SAS) {
- mpt->is_fc = 0;
- mpt->is_sas = 1;
- mpt->is_spi = 0;
+ mpt2host_portfacts_reply(pfp);
+
+ if (port > 0) {
+ error = MPT_PRT_INFO;
} else {
- mpt->is_fc = 0;
- mpt->is_sas = 0;
- mpt->is_spi = 1;
+ error = MPT_PRT_DEBUG;
}
- mpt->mpt_ini_id = pfp.PortSCSIID;
- mpt->mpt_max_devices = pfp.MaxDevices;
+ mpt_lprt(mpt, error,
+ "PORTFACTS[%d]: Type %x PFlags %x IID %d MaxDev %d\n",
+ port, pfp->PortType, pfp->ProtocolFlags, pfp->PortSCSIID,
+ pfp->MaxDevices);
- /*
- * Set our role with what this port supports.
- *
- * Note this might be changed later in different modules
- * if this is different from what is wanted.
- */
- mpt->role = MPT_ROLE_NONE;
- if (mpt->mpt_proto_flags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
- mpt->role |= MPT_ROLE_INITIATOR;
- }
- if (mpt->mpt_proto_flags & MPI_PORTFACTS_PROTOCOL_TARGET) {
- mpt->role |= MPT_ROLE_TARGET;
- }
- if (mpt_enable_ioc(mpt, 0) != MPT_OK) {
- mpt_prt(mpt, "unable to initialize IOC\n");
- return (ENXIO);
- }
+ }
- /*
- * Read IOC configuration information.
- *
- * We need this to determine whether or not we have certain
- * settings for Integrated Mirroring (e.g.).
- */
- mpt_read_config_info_ioc(mpt);
+ /*
+ * XXX: Not yet supporting more than port 0
+ */
+ pfp = &mpt->port_facts[0];
+ if (pfp->PortType == MPI_PORTFACTS_PORTTYPE_FC) {
+ mpt->is_fc = 1;
+ mpt->is_sas = 0;
+ mpt->is_spi = 0;
+ } else if (pfp->PortType == MPI_PORTFACTS_PORTTYPE_SAS) {
+ mpt->is_fc = 0;
+ mpt->is_sas = 1;
+ mpt->is_spi = 0;
+ } else if (pfp->PortType == MPI_PORTFACTS_PORTTYPE_SCSI) {
+ mpt->is_fc = 0;
+ mpt->is_sas = 0;
+ mpt->is_spi = 1;
+ } else if (pfp->PortType == MPI_PORTFACTS_PORTTYPE_ISCSI) {
+ mpt_prt(mpt, "iSCSI not supported yet\n");
+ return (ENXIO);
+ } else if (pfp->PortType == MPI_PORTFACTS_PORTTYPE_INACTIVE) {
+ mpt_prt(mpt, "Inactive Port\n");
+ return (ENXIO);
+ } else {
+ mpt_prt(mpt, "unknown Port Type %#x\n", pfp->PortType);
+ return (ENXIO);
+ }
- /* Everything worked */
- break;
+ /*
+ * Set our role with what this port supports.
+ *
+ * Note this might be changed later in different modules
+ * if this is different from what is wanted.
+ */
+ mpt->role = MPT_ROLE_NONE;
+ if (pfp->ProtocolFlags & MPI_PORTFACTS_PROTOCOL_INITIATOR) {
+ mpt->role |= MPT_ROLE_INITIATOR;
+ }
+ if (pfp->ProtocolFlags & MPI_PORTFACTS_PROTOCOL_TARGET) {
+ mpt->role |= MPT_ROLE_TARGET;
}
- if (try >= MPT_MAX_TRYS) {
- mpt_prt(mpt, "failed to initialize IOC");
- return (EIO);
+ /*
+ * Enable the IOC
+ */
+ if (mpt_enable_ioc(mpt, 0) != MPT_OK) {
+ mpt_prt(mpt, "unable to initialize IOC\n");
+ return (ENXIO);
}
+ /*
+ * Read IOC configuration information.
+ *
+ * We need this to determine whether or not we have certain
+ * settings for Integrated Mirroring (e.g.).
+ */
+ mpt_read_config_info_ioc(mpt);
+
return (0);
}
@@ -2588,7 +2580,7 @@ mpt_enable_ioc(struct mpt_softc *mpt, int portenable)
(pptr + MPT_REPLY_SIZE) < (mpt->reply_phys + PAGE_SIZE);
pptr += MPT_REPLY_SIZE) {
mpt_free_reply(mpt, pptr);
- if (++val == mpt->mpt_global_credits - 1)
+ if (++val == mpt->ioc_facts.GlobalCredits - 1)
break;
}
@@ -2610,3 +2602,92 @@ mpt_enable_ioc(struct mpt_softc *mpt, int portenable)
}
return (MPT_OK);
}
+
+/*
+ * Endian Conversion Functions- only used on Big Endian machines
+ */
+#if _BYTE_ORDER == _BIG_ENDIAN
+void
+mpt2host_sge_simple_union(SGE_SIMPLE_UNION *sge)
+{
+ MPT_2_HOST32(sge, FlagsLength);
+ MPT_2_HOST64(sge, u.Address64);
+};
+
+void
+mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *rp)
+{
+ MPT_2_HOST16(rp, MsgVersion);
+ MPT_2_HOST16(rp, HeaderVersion);
+ MPT_2_HOST32(rp, MsgContext);
+ MPT_2_HOST16(rp, IOCExceptions);
+ MPT_2_HOST16(rp, IOCStatus);
+ MPT_2_HOST32(rp, IOCLogInfo);
+ MPT_2_HOST16(rp, ReplyQueueDepth);
+ MPT_2_HOST16(rp, RequestFrameSize);
+ MPT_2_HOST16(rp, Reserved_0101_FWVersion);
+ MPT_2_HOST16(rp, ProductID);
+ MPT_2_HOST32(rp, CurrentHostMfaHighAddr);
+ MPT_2_HOST16(rp, GlobalCredits);
+ MPT_2_HOST32(rp, CurrentSenseBufferHighAddr);
+ MPT_2_HOST16(rp, CurReplyFrameSize);
+ MPT_2_HOST32(rp, FWImageSize);
+ MPT_2_HOST32(rp, IOCCapabilities);
+ MPT_2_HOST32(rp, FWVersion.Word);
+ MPT_2_HOST16(rp, HighPriorityQueueDepth);
+ MPT_2_HOST16(rp, Reserved2);
+ mpt2host_sge_simple_union(&rp->HostPageBufferSGE);
+ MPT_2_HOST32(rp, ReplyFifoHostSignalingAddr);
+}
+
+void
+mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *pfp)
+{
+ MPT_2_HOST16(pfp, Reserved);
+ MPT_2_HOST16(pfp, Reserved1);
+ MPT_2_HOST32(pfp, MsgContext);
+ MPT_2_HOST16(pfp, Reserved2);
+ MPT_2_HOST16(pfp, IOCStatus);
+ MPT_2_HOST32(pfp, IOCLogInfo);
+ MPT_2_HOST16(pfp, MaxDevices);
+ MPT_2_HOST16(pfp, PortSCSIID);
+ MPT_2_HOST16(pfp, ProtocolFlags);
+ MPT_2_HOST16(pfp, MaxPostedCmdBuffers);
+ MPT_2_HOST16(pfp, MaxPersistentIDs);
+ MPT_2_HOST16(pfp, MaxLanBuckets);
+ MPT_2_HOST16(pfp, Reserved4);
+ MPT_2_HOST32(pfp, Reserved5);
+}
+void
+mpt2host_config_page_ioc2(CONFIG_PAGE_IOC_2 *ioc2)
+{
+ int i;
+ ioc2->CapabilitiesFlags = htole32(ioc2->CapabilitiesFlags);
+ for (i = 0; i < MPI_IOC_PAGE_2_RAID_VOLUME_MAX; i++) {
+ MPT_2_HOST16(ioc2->RaidVolume[i].Reserved3);
+ }
+}
+
+void
+mpt2host_config_page_raid_vol_0(CONFIG_PAGE_RAID_VOL_0 *volp)
+{
+ int i;
+ MPT_2_HOST16(volp, VolumeStatus.Reserved);
+ MPT_2_HOST16(volp, VolumeSettings.Settings);
+ MPT_2_HOST32(volp, MaxLBA);
+ MPT_2_HOST32(volp, Reserved1);
+ MPT_2_HOST32(volp, StripeSize);
+ MPT_2_HOST32(volp, Reserved2);
+ MPT_2_HOST32(volp, Reserved3);
+ for (i = 0; i < MPI_RAID_VOL_PAGE_0_PHYSDISK_MAX; i++) {
+ MPT_2_HOST16(volpd, PhysDisk[i].Reserved);
+ }
+}
+
+void
+mpt2host_mpi_raid_vol_indicator(MPI_RAID_VOL_INDICATOR *vi)
+{
+ MPT_2_HOST16(vi, TotalBlocks);
+ MPT_2_HOST16(vi, BlocksRemaining);
+}
+#endif
diff --git a/sys/dev/mpt/mpt.h b/sys/dev/mpt/mpt.h
index 790f036..7e81fe4 100644
--- a/sys/dev/mpt/mpt.h
+++ b/sys/dev/mpt/mpt.h
@@ -155,6 +155,9 @@
/* XXX For mpt_debug.c */
#include <dev/mpt/mpilib/mpi_init.h>
+#define MPT_S64_2_SCALAR(y) ((((int64_t)y.High) << 32) | (y.Low))
+#define MPT_U64_2_SCALAR(y) ((((uint64_t)y.High) << 32) | (y.Low))
+
/****************************** Misc Definitions ******************************/
#define MPT_OK (0)
#define MPT_FAIL (0x10000)
@@ -272,15 +275,29 @@ void mpt_map_rquest(void *, bus_dma_segment_t *, int, int);
#endif
/********************************** Endianess *********************************/
-static __inline uint64_t
-u64toh(U64 s)
-{
- uint64_t result;
-
- result = le32toh(s.Low);
- result |= ((uint64_t)le32toh(s.High)) << 32;
- return (result);
-}
+#define MPT_2_HOST64(ptr, tag) ptr->tag = le64toh(ptr->tag)
+#define MPT_2_HOST32(ptr, tag) ptr->tag = le32toh(ptr->tag)
+#define MPT_2_HOST16(ptr, tag) ptr->tag = le16toh(ptr->tag)
+
+#define HOST_2_MPT64(ptr, tag) ptr->tag = htole64(ptr->tag)
+#define HOST_2_MPT32(ptr, tag) ptr->tag = htole32(ptr->tag)
+#define HOST_2_MPT16(ptr, tag) ptr->tag = htole16(ptr->tag)
+
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#define mpt2host_sge_simple_union(x) do { ; } while (0)
+#define mpt2host_iocfacts_reply(x) do { ; } while (0)
+#define mpt2host_portfacts_reply(x) do { ; } while (0)
+#define mpt2host_config_page_ioc2(x) do { ; } while (0)
+#define mpt2host_config_page_raid_vol_0(x) do { ; } while (0)
+#define mpt2host_mpi_raid_vol_indicator(x) do { ; } while (0)
+#else
+void mpt2host_sge_simple_union(SGE_SIMPLE_UNION *);
+void mpt2host_iocfacts_reply(MSG_IOC_FACTS_REPLY *);
+void mpt2host_portfacts_reply(MSG_PORT_FACTS_REPLY *);
+void mpt2host_config_page_ioc2(CONFIG_PAGE_IOC_2 *);
+void mpt2host_config_page_raid_vol_0(CONFIG_PAGE_RAID_VOL_0 *);
+void mpt2host_mpi_raid_vol_indicator(MPI_RAID_VOL_INDICATOR *);
+#endif
/**************************** MPI Transaction State ***************************/
typedef enum {
@@ -495,8 +512,10 @@ struct mpt_softc {
#endif
uint32_t mpt_pers_mask;
uint32_t
+ : 8,
unit : 8,
- : 2,
+ : 1,
+ fw_uploaded : 1,
msi_enable : 1,
twildcard : 1,
tenabled : 1,
@@ -520,20 +539,14 @@ struct mpt_softc {
/*
* IOC Facts
*/
- uint16_t mpt_global_credits;
- uint16_t request_frame_size;
- uint16_t mpt_max_devices;
- uint8_t mpt_max_buses;
- uint8_t ioc_facts_flags;
+ MSG_IOC_FACTS_REPLY ioc_facts;
/*
* Port Facts
- * XXX - Add multi-port support!.
*/
- uint16_t mpt_ini_id;
- uint16_t mpt_port_type;
- uint16_t mpt_proto_flags;
- uint16_t mpt_max_tgtcmds;
+ MSG_PORT_FACTS_REPLY * port_facts;
+#define mpt_ini_id port_facts[0].PortSCSIID
+#define mpt_max_tgtcmds port_facts[0].MaxPostedCmdBuffers
/*
* Device Configuration Information
@@ -930,7 +943,7 @@ mpt_complete_request_chain(struct mpt_softc *, struct req_queue *, u_int);
/************************** Scatter Gather Managment **************************/
/* MPT_RQSL- size of request frame, in bytes */
-#define MPT_RQSL(mpt) (mpt->request_frame_size << 2)
+#define MPT_RQSL(mpt) (mpt->ioc_facts.RequestFrameSize << 2)
/* MPT_NSGL- how many SG entries can fit in a request frame size */
#define MPT_NSGL(mpt) (MPT_RQSL(mpt) / sizeof (SGE_IO_UNION))
diff --git a/sys/dev/mpt/mpt_cam.c b/sys/dev/mpt/mpt_cam.c
index b380fc5..a51402a 100644
--- a/sys/dev/mpt/mpt_cam.c
+++ b/sys/dev/mpt/mpt_cam.c
@@ -211,8 +211,8 @@ mpt_cam_attach(struct mpt_softc *mpt)
int error;
TAILQ_INIT(&mpt->request_timeout_list);
- maxq = (mpt->mpt_global_credits < MPT_MAX_REQUESTS(mpt))?
- mpt->mpt_global_credits : MPT_MAX_REQUESTS(mpt);
+ maxq = (mpt->ioc_facts.GlobalCredits < MPT_MAX_REQUESTS(mpt))?
+ mpt->ioc_facts.GlobalCredits : MPT_MAX_REQUESTS(mpt);
handler.reply_handler = mpt_scsi_reply_handler;
error = mpt_register_handler(mpt, MPT_HANDLER_REPLY, handler,
@@ -3089,8 +3089,9 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
break;
}
case XPT_GET_TRAN_SETTINGS:
+ {
cts = &ccb->cts;
- cts->protocol = PROTO_SCSI;
+ struct ccb_trans_settings_scsi *scsi;
if (mpt->is_fc) {
struct ccb_trans_settings_fc *fc =
&cts->xport_specific.fc;
@@ -3108,13 +3109,21 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
cts->transport_version = 0;
sas->valid = CTS_SAS_VALID_SPEED;
sas->bitrate = 300000;
- } else if (mpt_get_spi_settings(mpt, cts) != 0) {
- mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
+ } else {
+ if (mpt_get_spi_settings(mpt, cts) != 0) {
+ mpt_set_ccb_status(ccb, CAM_REQ_CMP_ERR);
+ } else {
+ mpt_set_ccb_status(ccb, CAM_REQ_CMP);
+ }
break;
}
+ cts->protocol = PROTO_SCSI;
+ scsi = &cts->proto_specific.scsi;
+ scsi->valid = CTS_SCSI_VALID_TQ;
+ scsi->flags = CTS_SCSI_FLAGS_TAG_ENB;
mpt_set_ccb_status(ccb, CAM_REQ_CMP);
break;
-
+ }
case XPT_CALC_GEOMETRY:
{
struct ccb_calc_geometry *ccg;
@@ -3136,7 +3145,7 @@ mpt_action(struct cam_sim *sim, union ccb *ccb)
cpi->version_num = 1;
cpi->target_sprt = 0;
cpi->hba_eng_cnt = 0;
- cpi->max_target = mpt->mpt_max_devices - 1;
+ cpi->max_target = mpt->port_facts[0].MaxDevices - 1;
/*
* FC cards report MAX_DEVICES of 512, but
* the MSG_SCSI_IO_REQUEST target id field
diff --git a/sys/dev/mpt/mpt_debug.c b/sys/dev/mpt/mpt_debug.c
index 53b0c26..fd723cb 100644
--- a/sys/dev/mpt/mpt_debug.c
+++ b/sys/dev/mpt/mpt_debug.c
@@ -819,7 +819,7 @@ void
mpt_dump_request(struct mpt_softc *mpt, request_t *req)
{
uint32_t *pReq = req->req_vbuf;
- int offset;
+ int o;
#if __FreeBSD_version >= 500000
mpt_prt(mpt, "Send Request %d (%jx):",
req->index, (uintmax_t) req->req_pbuf);
@@ -827,12 +827,12 @@ mpt_dump_request(struct mpt_softc *mpt, request_t *req)
mpt_prt(mpt, "Send Request %d (%llx):",
req->index, (unsigned long long) req->req_pbuf);
#endif
- for (offset = 0; offset < mpt->request_frame_size; offset++) {
- if ((offset & 0x7) == 0) {
+ for (o = 0; o < mpt->ioc_facts.RequestFrameSize; o++) {
+ if ((o & 0x7) == 0) {
mpt_prtc(mpt, "\n");
mpt_prt(mpt, " ");
}
- mpt_prtc(mpt, " %08x", pReq[offset]);
+ mpt_prtc(mpt, " %08x", pReq[o]);
}
mpt_prtc(mpt, "\n");
}
diff --git a/sys/dev/mpt/mpt_raid.c b/sys/dev/mpt/mpt_raid.c
index 216428b..624baaf 100644
--- a/sys/dev/mpt/mpt_raid.c
+++ b/sys/dev/mpt/mpt_raid.c
@@ -1229,7 +1229,7 @@ mpt_refresh_raid_disk(struct mpt_softc *mpt, struct mpt_raid_disk *mpt_disk,
static void
mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
- CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol)
+ CONFIG_PAGE_IOC_2_RAID_VOL *ioc_vol)
{
CONFIG_PAGE_RAID_VOL_0 *vol_pg;
struct mpt_raid_action_result *ar;
@@ -1239,31 +1239,31 @@ mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
vol_pg = mpt_vol->config_page;
mpt_vol->flags &= ~MPT_RVF_UP2DATE;
- rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME,
- /*PageNumber*/0, ioc_vol->VolumePageNumber,
- &vol_pg->Header, /*sleep_ok*/TRUE,
- /*timeout_ms*/5000);
+
+ rv = mpt_read_cfg_header(mpt, MPI_CONFIG_PAGETYPE_RAID_VOLUME, 0,
+ ioc_vol->VolumePageNumber, &vol_pg->Header, TRUE, 5000);
if (rv != 0) {
- mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_vol: "
- "Failed to read RAID Vol Hdr(%d)\n",
- ioc_vol->VolumePageNumber);
+ mpt_vol_prt(mpt, mpt_vol,
+ "mpt_refresh_raid_vol: Failed to read RAID Vol Hdr(%d)\n",
+ ioc_vol->VolumePageNumber);
return;
}
+
rv = mpt_read_cur_cfg_page(mpt, ioc_vol->VolumePageNumber,
- &vol_pg->Header, mpt->raid_page0_len,
- /*sleep_ok*/TRUE, /*timeout_ms*/5000);
+ &vol_pg->Header, mpt->raid_page0_len, TRUE, 5000);
if (rv != 0) {
- mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_vol: "
- "Failed to read RAID Vol Page(%d)\n",
- ioc_vol->VolumePageNumber);
+ mpt_vol_prt(mpt, mpt_vol,
+ "mpt_refresh_raid_vol: Failed to read RAID Vol Page(%d)\n",
+ ioc_vol->VolumePageNumber);
return;
}
+ mpt2host_config_page_raid_vol_0(vol_pg);
+
mpt_vol->flags |= MPT_RVF_ACTIVE;
/* Update disk entry array data. */
for (i = 0; i < vol_pg->NumPhysDisks; i++) {
struct mpt_raid_disk *mpt_disk;
-
mpt_disk = mpt->raid_disks + vol_pg->PhysDisk[i].PhysDiskNum;
mpt_disk->volume = mpt_vol;
mpt_disk->member_number = vol_pg->PhysDisk[i].PhysDiskMap;
@@ -1276,19 +1276,18 @@ mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
& MPI_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) == 0)
return;
- req = mpt_get_request(mpt, /*sleep_ok*/TRUE);
+ req = mpt_get_request(mpt, TRUE);
if (req == NULL) {
mpt_vol_prt(mpt, mpt_vol,
- "mpt_refresh_raid_vol: Get request failed!\n");
+ "mpt_refresh_raid_vol: Get request failed!\n");
return;
}
- rv = mpt_issue_raid_req(mpt, mpt_vol, /*disk*/NULL, req,
- MPI_RAID_ACTION_INDICATOR_STRUCT,
- /*ActionWord*/0, /*addr*/0, /*len*/0,
- /*write*/FALSE, /*wait*/TRUE);
+ rv = mpt_issue_raid_req(mpt, mpt_vol, NULL, req,
+ MPI_RAID_ACTION_INDICATOR_STRUCT, 0, 0, 0, FALSE, TRUE);
if (rv == ETIMEDOUT) {
- mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_vol: "
- "Progress indicator fetch timedout!\n");
+ mpt_vol_prt(mpt, mpt_vol,
+ "mpt_refresh_raid_vol: Progress Indicator fetch timeout\n");
+ mpt_free_request(mpt, req);
return;
}
@@ -1299,9 +1298,10 @@ mpt_refresh_raid_vol(struct mpt_softc *mpt, struct mpt_raid_volume *mpt_vol,
memcpy(&mpt_vol->sync_progress,
&ar->action_data.indicator_struct,
sizeof(mpt_vol->sync_progress));
+ mpt2host_mpi_raid_vol_indicator(&mpt_vol->sync_progress);
} else {
- mpt_vol_prt(mpt, mpt_vol, "mpt_refresh_raid_vol: "
- "Progress indicator fetch failed!\n");
+ mpt_vol_prt(mpt, mpt_vol,
+ "mpt_refresh_raid_vol: Progress indicator fetch failed!\n");
}
mpt_free_request(mpt, req);
}
@@ -1414,8 +1414,9 @@ mpt_refresh_raid_data(struct mpt_softc *mpt)
mpt_vol = &mpt->raid_volumes[i];
- if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0)
+ if ((mpt_vol->flags & MPT_RVF_ACTIVE) == 0) {
continue;
+ }
vol_pg = mpt_vol->config_page;
if ((mpt_vol->flags & (MPT_RVF_REFERENCED|MPT_RVF_ANNOUNCED))
@@ -1426,7 +1427,6 @@ mpt_refresh_raid_data(struct mpt_softc *mpt)
}
if ((mpt_vol->flags & MPT_RVF_ANNOUNCED) == 0) {
-
mpt_announce_vol(mpt, mpt_vol);
mpt_vol->flags |= MPT_RVF_ANNOUNCED;
}
@@ -1440,11 +1440,12 @@ mpt_refresh_raid_data(struct mpt_softc *mpt)
mpt_vol->flags |= MPT_RVF_UP2DATE;
mpt_vol_prt(mpt, mpt_vol, "%s - %s\n",
- mpt_vol_type(mpt_vol), mpt_vol_state(mpt_vol));
+ mpt_vol_type(mpt_vol), mpt_vol_state(mpt_vol));
mpt_verify_mwce(mpt, mpt_vol);
- if (vol_pg->VolumeStatus.Flags == 0)
+ if (vol_pg->VolumeStatus.Flags == 0) {
continue;
+ }
mpt_vol_prt(mpt, mpt_vol, "Status (");
for (m = 1; m <= 0x80; m <<= 1) {
@@ -1473,8 +1474,8 @@ mpt_refresh_raid_data(struct mpt_softc *mpt)
mpt_verify_resync_rate(mpt, mpt_vol);
- left = u64toh(mpt_vol->sync_progress.BlocksRemaining);
- total = u64toh(mpt_vol->sync_progress.TotalBlocks);
+ left = MPT_U64_2_SCALAR(mpt_vol->sync_progress.BlocksRemaining);
+ total = MPT_U64_2_SCALAR(mpt_vol->sync_progress.TotalBlocks);
if (vol_pg->ResyncRate != 0) {
prio = ((u_int)vol_pg->ResyncRate * 100000) / 0xFF;
OpenPOWER on IntegriCloud