diff options
-rw-r--r-- | sys/dev/mpt/mpt.c | 527 | ||||
-rw-r--r-- | sys/dev/mpt/mpt.h | 55 | ||||
-rw-r--r-- | sys/dev/mpt/mpt_cam.c | 23 | ||||
-rw-r--r-- | sys/dev/mpt/mpt_debug.c | 8 | ||||
-rw-r--r-- | sys/dev/mpt/mpt_raid.c | 61 |
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; |