void mps_print_sasdev0(struct mps_softc *sc, MPI2_CONFIG_PAGE_SAS_DEV_0 *buf) { MPS_PRINTFIELD_START(sc, "SAS Device Page 0"); MPS_PRINTFIELD(sc, buf, Slot, %d); MPS_PRINTFIELD(sc, buf, EnclosureHandle, 0x%x); mps_dprint_field(sc, MPS_INFO, "SASAddress: 0x%jx\n", mps_to_u64(&buf->SASAddress)); MPS_PRINTFIELD(sc, buf, ParentDevHandle, 0x%x); MPS_PRINTFIELD(sc, buf, PhyNum, %d); MPS_PRINTFIELD(sc, buf, AccessStatus, 0x%x); MPS_PRINTFIELD(sc, buf, DevHandle, 0x%x); MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, 0x%x); MPS_PRINTFIELD(sc, buf, ZoneGroup, %d); mps_dprint_field(sc, MPS_INFO, "DeviceInfo: %b,%s\n", buf->DeviceInfo, "\20" "\4SataHost" "\5SmpInit" "\6StpInit" "\7SspInit" "\10SataDev" "\11SmpTarg" "\12StpTarg" "\13SspTarg" "\14Direct" "\15LsiDev" "\16AtapiDev" "\17SepDev", mps_describe_table(mps_sasdev0_devtype, buf->DeviceInfo & 0x03)); MPS_PRINTFIELD(sc, buf, Flags, 0x%x); MPS_PRINTFIELD(sc, buf, PhysicalPort, %d); MPS_PRINTFIELD(sc, buf, MaxPortConnections, %d); mps_dprint_field(sc, MPS_INFO, "DeviceName: 0x%jx\n", mps_to_u64(&buf->DeviceName)); MPS_PRINTFIELD(sc, buf, PortGroups, %d); MPS_PRINTFIELD(sc, buf, DmaGroup, %d); MPS_PRINTFIELD(sc, buf, ControlGroup, %d); }
static void print_sgl(char *buf, int offset, int numframes) { MPI2_SGE_SIMPLE64 *sge; MPI2_SGE_CHAIN_UNION *sgc; MPI2_REQUEST_HEADER *req; u_int i = 0, flags; char *frame, tmpbuf[128]; req = (MPI2_REQUEST_HEADER *)buf; frame = (char *)buf; sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4]; printf("SGL for command\n"); hexdump(frame, MPS_FRAME_LEN, NULL, 0); while (frame != NULL) { flags = sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT; bzero(tmpbuf, sizeof(tmpbuf)); mps_parse_flags(flags, SGL_FLAGS, tmpbuf, sizeof(tmpbuf)); printf("seg%d flags=%x %s len= 0x%06x addr=0x%016jx\n", i, flags, tmpbuf, sge->FlagsLength & 0xffffff, mps_to_u64(&sge->Address)); if (flags & (MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_END_OF_BUFFER)) break; sge++; i++; if (flags & MPI2_SGE_FLAGS_LAST_ELEMENT) { sgc = (MPI2_SGE_CHAIN_UNION *)sge; if ((sgc->Flags & MPI2_SGE_FLAGS_CHAIN_ELEMENT) == 0) { printf("Invalid chain element\n"); break; } bzero(tmpbuf, sizeof(tmpbuf)); mps_parse_flags(sgc->Flags, SGL_FLAGS, tmpbuf, sizeof(tmpbuf)); if (sgc->Flags & MPI2_SGE_FLAGS_64_BIT_ADDRESSING) printf("chain64 flags=0x%x %s len=0x%x " "Offset=0x%x addr=0x%016jx\n", sgc->Flags, tmpbuf, sgc->Length, sgc->NextChainOffset, mps_to_u64(&sgc->u.Address64)); else printf("chain32 flags=0x%x %s len=0x%x " "Offset=0x%x addr=0x%08x\n", sgc->Flags, tmpbuf, sgc->Length, sgc->NextChainOffset, sgc->u.Address32); if (--numframes <= 0) break; frame += MPS_FRAME_LEN; sge = (MPI2_SGE_SIMPLE64 *)frame; hexdump(frame, MPS_FRAME_LEN, NULL, 0); } } }
void mps_print_sgl(struct mps_softc *sc, struct mps_command *cm, int offset) { MPI2_SGE_SIMPLE64 *sge; MPI2_SGE_CHAIN32 *sgc; MPI2_REQUEST_HEADER *req; struct mps_chain *chain = NULL; char *frame; u_int i = 0, flags; req = (MPI2_REQUEST_HEADER *)cm->cm_req; frame = (char *)cm->cm_req; sge = (MPI2_SGE_SIMPLE64 *)&frame[offset * 4]; printf("SGL for command %p\n", cm); while (frame != NULL) { flags = sge->FlagsLength >> MPI2_SGE_FLAGS_SHIFT; printf("seg%d flags=0x%x len=0x%x addr=0x%jx\n", i, flags, sge->FlagsLength & 0xffffff, mps_to_u64(&sge->Address)); if (flags & (MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_END_OF_BUFFER)) break; sge++; i++; if (flags & MPI2_SGE_FLAGS_LAST_ELEMENT) { sgc = (MPI2_SGE_CHAIN32 *)sge; printf("chain flags=0x%x len=0x%x Offset=0x%x " "Address=0x%x\n", sgc->Flags, sgc->Length, sgc->NextChainOffset, sgc->Address); if (chain == NULL) chain = TAILQ_FIRST(&cm->cm_chain_list); else chain = TAILQ_NEXT(chain, chain_link); frame = (char *)chain->chain; sge = (MPI2_SGE_SIMPLE64 *)frame; hexdump(frame, 128, NULL, 0); } } }
void mps_print_evt_sas(struct mps_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event) { mps_print_event(sc, event); switch(event->Event) { case MPI2_EVENT_SAS_DISCOVERY: { MPI2_EVENT_DATA_SAS_DISCOVERY *data; data = (MPI2_EVENT_DATA_SAS_DISCOVERY *)&event->EventData; mps_dprint_field(sc, MPS_EVENT, "Flags: %b\n", data->Flags, "\20" "\1InProgress" "\2DeviceChange"); mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n", mps_describe_table(mps_sasdisc_reason, data->ReasonCode)); MPS_EVENTFIELD(sc, data, PhysicalPort, %d); mps_dprint_field(sc, MPS_EVENT, "DiscoveryStatus: %b\n", data->DiscoveryStatus, "\20" "\1Loop" "\2UnaddressableDev" "\3DupSasAddr" "\5SmpTimeout" "\6ExpRouteFull" "\7RouteIndexError" "\10SmpFailed" "\11SmpCrcError" "\12SubSubLink" "\13TableTableLink" "\14UnsupDevice" "\15TableSubLink" "\16MultiDomain" "\17MultiSub" "\20MultiSubSub" "\34DownstreamInit" "\35MaxPhys" "\36MaxTargs" "\37MaxExpanders" "\40MaxEnclosures"); break; } case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: { MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *data; MPI2_EVENT_SAS_TOPO_PHY_ENTRY *phy; int i, phynum; data = (MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST *) &event->EventData; MPS_EVENTFIELD(sc, data, EnclosureHandle, 0x%x); MPS_EVENTFIELD(sc, data, ExpanderDevHandle, 0x%x); MPS_EVENTFIELD(sc, data, NumPhys, %d); MPS_EVENTFIELD(sc, data, NumEntries, %d); MPS_EVENTFIELD(sc, data, StartPhyNum, %d); mps_dprint_field(sc, MPS_EVENT, "ExpStatus: %s (0x%x)\n", mps_describe_table(mps_sastopo_exp, data->ExpStatus), data->ExpStatus); MPS_EVENTFIELD(sc, data, PhysicalPort, %d); for (i = 0; i < data->NumEntries; i++) { phy = &data->PHY[i]; phynum = data->StartPhyNum + i; mps_dprint_field(sc, MPS_EVENT, "PHY[%d].AttachedDevHandle: 0x%04x\n", phynum, phy->AttachedDevHandle); mps_dprint_field(sc, MPS_EVENT, "PHY[%d].LinkRate: %s (0x%x)\n", phynum, mps_describe_table(mps_linkrate_names, (phy->LinkRate >> 4) & 0xf), phy->LinkRate); mps_dprint_field(sc,MPS_EVENT,"PHY[%d].PhyStatus: %s\n", phynum, mps_describe_table(mps_phystatus_names, phy->PhyStatus)); } break; } case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: { MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE *data; data = (MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE *) &event->EventData; MPS_EVENTFIELD(sc, data, EnclosureHandle, 0x%x); mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n", mps_describe_table(mps_sastopo_exp, data->ReasonCode)); MPS_EVENTFIELD(sc, data, PhysicalPort, %d); MPS_EVENTFIELD(sc, data, NumSlots, %d); MPS_EVENTFIELD(sc, data, StartSlot, %d); MPS_EVENTFIELD(sc, data, PhyBits, 0x%x); break; } case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: { MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *data; data = (MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE *) &event->EventData; MPS_EVENTFIELD(sc, data, TaskTag, 0x%x); mps_dprint_field(sc, MPS_EVENT, "ReasonCode: %s\n", mps_describe_table(mps_sasdev_reason, data->ReasonCode)); MPS_EVENTFIELD(sc, data, ASC, 0x%x); MPS_EVENTFIELD(sc, data, ASCQ, 0x%x); MPS_EVENTFIELD(sc, data, DevHandle, 0x%x); mps_dprint_field(sc, MPS_EVENT, "SASAddress: 0x%jx\n", mps_to_u64(&data->SASAddress)); } default: break; } }
static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ char devstring[80]; struct mpssas_softc *sassc; struct mpssas_target *targ; Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t config_page; uint64_t sas_address, sata_sas_address; uint64_t parent_sas_address = 0; u16 ioc_pg8_flags = le16toh(sc->ioc_pg8.Flags); u32 device_info, parent_devinfo = 0; unsigned int id; int ret; int error = 0; sassc = sc->sassc; mpssas_startup_increment(sassc); if ((mps_config_get_sas_device_pg0(sc, &mpi_reply, &config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { kprintf("%s: error reading SAS device page0\n", __func__); error = ENXIO; goto out; } device_info = le32toh(config_page.DeviceInfo); if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) && (config_page.ParentDevHandle != 0)) { Mpi2ConfigReply_t tmp_mpi_reply; Mpi2SasDevicePage0_t parent_config_page; if ((mps_config_get_sas_device_pg0(sc, &tmp_mpi_reply, &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, le16toh(config_page.ParentDevHandle)))) { kprintf("%s: error reading SAS device %#x page0\n", __func__, le16toh(config_page.ParentDevHandle)); } else { parent_sas_address = parent_config_page.SASAddress.High; parent_sas_address = (parent_sas_address << 32) | parent_config_page.SASAddress.Low; parent_devinfo = le32toh(parent_config_page.DeviceInfo); } } /* TODO Check proper endianess */ sas_address = config_page.SASAddress.High; sas_address = (sas_address << 32) | config_page.SASAddress.Low; if ((ioc_pg8_flags & MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE) == MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING) { if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { ret = mpssas_get_sas_address_for_sata_disk(sc, &sata_sas_address, handle, device_info); if (!ret) id = mps_mapping_get_sas_id(sc, sata_sas_address, handle); else id = mps_mapping_get_sas_id(sc, sas_address, handle); } else id = mps_mapping_get_sas_id(sc, sas_address, handle); } else id = mps_mapping_get_sas_id(sc, sas_address, handle); if (id == MPS_MAP_BAD_ID) { kprintf("failure at %s:%d/%s()! Could not get ID for device " "with handle 0x%04x\n", __FILE__, __LINE__, __func__, handle); error = ENXIO; goto out; } mps_vprintf(sc, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; targ->devinfo = device_info; targ->devname = le32toh(config_page.DeviceName.High); targ->devname = (targ->devname << 32) | le32toh(config_page.DeviceName.Low); targ->encl_handle = le16toh(config_page.EnclosureHandle); targ->encl_slot = le16toh(config_page.Slot); targ->handle = handle; targ->parent_handle = le16toh(config_page.ParentDevHandle); targ->sasaddr = mps_to_u64(&config_page.SASAddress); targ->parent_sasaddr = le64toh(parent_sas_address); targ->parent_devinfo = parent_devinfo; targ->tid = id; targ->linkrate = (linkrate>>4); targ->flags = 0; TAILQ_INIT(&targ->commands); TAILQ_INIT(&targ->timedout_commands); SLIST_INIT(&targ->luns); mps_describe_devinfo(targ->devinfo, devstring, 80); mps_vprintf(sc, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring, mps_describe_table(mps_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); if ((sassc->flags & MPSSAS_IN_STARTUP) == 0) mpssas_rescan_target(sc, targ); mps_vprintf(sc, "Target id 0x%x added\n", targ->tid); out: mpssas_startup_decrement(sassc); return (error); }
static int mpssas_add_device(struct mps_softc *sc, u16 handle, u8 linkrate){ char devstring[80]; struct mpssas_softc *sassc; struct mpssas_target *targ; Mpi2ConfigReply_t mpi_reply; Mpi2SasDevicePage0_t config_page; uint64_t sas_address; uint64_t parent_sas_address = 0; u32 device_info, parent_devinfo = 0; unsigned int id; int ret = 1, error = 0, i; struct mpssas_lun *lun; u8 is_SATA_SSD = 0; struct mps_command *cm; sassc = sc->sassc; mpssas_startup_increment(sassc); if ((mps_config_get_sas_device_pg0(sc, &mpi_reply, &config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { printf("%s: error reading SAS device page0\n", __func__); error = ENXIO; goto out; } device_info = le32toh(config_page.DeviceInfo); if (((device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) == 0) && (le16toh(config_page.ParentDevHandle) != 0)) { Mpi2ConfigReply_t tmp_mpi_reply; Mpi2SasDevicePage0_t parent_config_page; if ((mps_config_get_sas_device_pg0(sc, &tmp_mpi_reply, &parent_config_page, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, le16toh(config_page.ParentDevHandle)))) { printf("%s: error reading SAS device %#x page0\n", __func__, le16toh(config_page.ParentDevHandle)); } else { parent_sas_address = parent_config_page.SASAddress.High; parent_sas_address = (parent_sas_address << 32) | parent_config_page.SASAddress.Low; parent_devinfo = le32toh(parent_config_page.DeviceInfo); } } /* TODO Check proper endianess */ sas_address = config_page.SASAddress.High; sas_address = (sas_address << 32) | config_page.SASAddress.Low; /* * Always get SATA Identify information because this is used to * determine if Start/Stop Unit should be sent to the drive when the * system is shutdown. */ if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) { ret = mpssas_get_sas_address_for_sata_disk(sc, &sas_address, handle, device_info, &is_SATA_SSD); if (ret) { mps_dprint(sc, MPS_INFO, "%s: failed to get disk type " "(SSD or HDD) for SATA device with handle 0x%04x\n", __func__, handle); } else { mps_dprint(sc, MPS_INFO, "SAS Address from SATA " "device = %jx\n", sas_address); } } id = mps_mapping_get_sas_id(sc, sas_address, handle); if (id == MPS_MAP_BAD_ID) { printf("failure at %s:%d/%s()! Could not get ID for device " "with handle 0x%04x\n", __FILE__, __LINE__, __func__, handle); error = ENXIO; goto out; } if (mpssas_check_id(sassc, id) != 0) { device_printf(sc->mps_dev, "Excluding target id %d\n", id); error = ENXIO; goto out; } mps_dprint(sc, MPS_MAPPING, "SAS Address from SAS device page0 = %jx\n", sas_address); targ = &sassc->targets[id]; targ->devinfo = device_info; targ->devname = le32toh(config_page.DeviceName.High); targ->devname = (targ->devname << 32) | le32toh(config_page.DeviceName.Low); targ->encl_handle = le16toh(config_page.EnclosureHandle); targ->encl_slot = le16toh(config_page.Slot); targ->handle = handle; targ->parent_handle = le16toh(config_page.ParentDevHandle); targ->sasaddr = mps_to_u64(&config_page.SASAddress); targ->parent_sasaddr = le64toh(parent_sas_address); targ->parent_devinfo = parent_devinfo; targ->tid = id; targ->linkrate = (linkrate>>4); targ->flags = 0; if (is_SATA_SSD) { targ->flags = MPS_TARGET_IS_SATA_SSD; } TAILQ_INIT(&targ->commands); TAILQ_INIT(&targ->timedout_commands); while(!SLIST_EMPTY(&targ->luns)) { lun = SLIST_FIRST(&targ->luns); SLIST_REMOVE_HEAD(&targ->luns, lun_link); free(lun, M_MPT2); } SLIST_INIT(&targ->luns); mps_describe_devinfo(targ->devinfo, devstring, 80); mps_dprint(sc, MPS_MAPPING, "Found device <%s> <%s> <0x%04x> <%d/%d>\n", devstring, mps_describe_table(mps_linkrate_names, targ->linkrate), targ->handle, targ->encl_handle, targ->encl_slot); #if __FreeBSD_version < 1000039 if ((sassc->flags & MPSSAS_IN_STARTUP) == 0) #endif mpssas_rescan_target(sc, targ); mps_dprint(sc, MPS_MAPPING, "Target id 0x%x added\n", targ->tid); /* * Check all commands to see if the SATA_ID_TIMEOUT flag has been set. * If so, send a Target Reset TM to the target that was just created. * An Abort Task TM should be used instead of a Target Reset, but that * would be much more difficult because targets have not been fully * discovered yet, and LUN's haven't been setup. So, just reset the * target instead of the LUN. */ for (i = 1; i < sc->num_reqs; i++) { cm = &sc->commands[i]; if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) { targ->timeouts++; cm->cm_state = MPS_CM_STATE_TIMEDOUT; if ((targ->tm = mpssas_alloc_tm(sc)) != NULL) { mps_dprint(sc, MPS_INFO, "%s: sending Target " "Reset for stuck SATA identify command " "(cm = %p)\n", __func__, cm); targ->tm->cm_targ = targ; mpssas_send_reset(sc, targ->tm, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET); } else { mps_dprint(sc, MPS_ERROR, "Failed to allocate " "tm for Target Reset after SATA ID command " "timed out (cm %p)\n", cm); } /* * No need to check for more since the target is * already being reset. */ break; } } out: /* * Free the commands that may not have been freed from the SATA ID call */ for (i = 1; i < sc->num_reqs; i++) { cm = &sc->commands[i]; if (cm->cm_flags & MPS_CM_FLAGS_SATA_ID_TIMEOUT) { mps_free_command(sc, cm); } } mpssas_startup_decrement(sassc); return (error); }