Пример #1
0
void
mps_print_sasphy0(struct mps_softc *sc, MPI2_CONFIG_PAGE_SAS_PHY_0 *buf)
{
	MPS_PRINTFIELD_START(sc, "SAS PHY Page 0");
	MPS_PRINTFIELD(sc, buf, OwnerDevHandle, 0x%04x);
	MPS_PRINTFIELD(sc, buf, AttachedDevHandle, 0x%04x);
	MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, %d);
	mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo Reason: %s (0x%x)\n",
	    mps_describe_table(mps_phyinfo_reason_names,
	    buf->AttachedPhyInfo & 0xf), buf->AttachedPhyInfo);
	mps_dprint_field(sc, MPS_INFO, "ProgrammedLinkRate: %s (0x%x)\n",
	    mps_describe_table(mps_linkrate_names,
	    (buf->ProgrammedLinkRate >> 4) & 0xf), buf->ProgrammedLinkRate);
	mps_dprint_field(sc, MPS_INFO, "HwLinkRate: %s (0x%x)\n",
	    mps_describe_table(mps_linkrate_names,
	    (buf->HwLinkRate >> 4) & 0xf), buf->HwLinkRate);
	MPS_PRINTFIELD(sc, buf, ChangeCount, %d);
	MPS_PRINTFIELD(sc, buf, Flags, 0x%x);
	mps_dprint_field(sc, MPS_INFO, "PhyInfo Reason: %s (0x%x)\n",
	    mps_describe_table(mps_phyinfo_reason_names,
	    (buf->PhyInfo >> 16) & 0xf), buf->PhyInfo);
	mps_dprint_field(sc, MPS_INFO, "NegotiatedLinkRate: %s (0x%x)\n",
	    mps_describe_table(mps_linkrate_names,
	    buf->NegotiatedLinkRate & 0xf), buf->NegotiatedLinkRate);
}
Пример #2
0
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);
}
Пример #3
0
void
mps_describe_devinfo(uint32_t devinfo, char *string, int len)
{
	snprintf(string, len, "%b,%s", devinfo,
	    "\20" "\4SataHost" "\5SmpInit" "\6StpInit" "\7SspInit"
	    "\10SataDev" "\11SmpTarg" "\12StpTarg" "\13SspTarg" "\14Direct"
	    "\15LsiDev" "\16AtapiDev" "\17SepDev",
	    mps_describe_table(mps_sasdev0_devtype, devinfo & 0x03));
}
Пример #4
0
void
mps_print_event(struct mps_softc *sc, MPI2_EVENT_NOTIFICATION_REPLY *event)
{

	MPS_EVENTFIELD_START(sc, "EventReply");
	MPS_EVENTFIELD(sc, event, EventDataLength, %d);
	MPS_EVENTFIELD(sc, event, AckRequired, %d);
	mps_dprint_field(sc, MPS_EVENT, "Event: %s (0x%x)\n",
	    mps_describe_table(mps_event_names, event->Event), event->Event);
	MPS_EVENTFIELD(sc, event, EventContext, 0x%x);
}
Пример #5
0
void
mps_print_expander1(struct mps_softc *sc, MPI2_CONFIG_PAGE_EXPANDER_1 *buf)
{
	MPS_PRINTFIELD_START(sc, "SAS Expander Page 1 #%d", buf->Phy);
	MPS_PRINTFIELD(sc, buf, PhysicalPort, %d);
	MPS_PRINTFIELD(sc, buf, NumPhys, %d);
	MPS_PRINTFIELD(sc, buf, Phy, %d);
	MPS_PRINTFIELD(sc, buf, NumTableEntriesProgrammed, %d);
	mps_dprint_field(sc, MPS_INFO, "ProgrammedLinkRate: %s (0x%x)\n",
	    mps_describe_table(mps_linkrate_names,
	    (buf->ProgrammedLinkRate >> 4) & 0xf), buf->ProgrammedLinkRate);
	mps_dprint_field(sc, MPS_INFO, "HwLinkRate: %s (0x%x)\n",
	    mps_describe_table(mps_linkrate_names,
	    (buf->HwLinkRate >> 4) & 0xf), buf->HwLinkRate);
	MPS_PRINTFIELD(sc, buf, AttachedDevHandle, 0x%04x);
	mps_dprint_field(sc, MPS_INFO, "PhyInfo Reason: %s (0x%x)\n",
	    mps_describe_table(mps_phyinfo_reason_names,
	    (buf->PhyInfo >> 16) & 0xf), buf->PhyInfo);
	mps_dprint_field(sc, MPS_INFO, "AttachedDeviceInfo: %b,%s\n",
	    buf->AttachedDeviceInfo, "\20" "\4SATAhost" "\5SMPinit" "\6STPinit"
	    "\7SSPinit" "\10SATAdev" "\11SMPtarg" "\12STPtarg" "\13SSPtarg"
	    "\14Direct" "\15LSIdev" "\16ATAPIdev" "\17SEPdev",
	    mps_describe_table(mps_sasdev0_devtype,
	    buf->AttachedDeviceInfo & 0x03));
	MPS_PRINTFIELD(sc, buf, ExpanderDevHandle, 0x%04x);
	MPS_PRINTFIELD(sc, buf, ChangeCount, %d);
	mps_dprint_field(sc, MPS_INFO, "NegotiatedLinkRate: %s (0x%x)\n",
	    mps_describe_table(mps_linkrate_names,
	    buf->NegotiatedLinkRate & 0xf), buf->NegotiatedLinkRate);
	MPS_PRINTFIELD(sc, buf, PhyIdentifier, %d);
	MPS_PRINTFIELD(sc, buf, AttachedPhyIdentifier, %d);
	MPS_PRINTFIELD(sc, buf, DiscoveryInfo, 0x%x);
	MPS_PRINTFIELD(sc, buf, AttachedPhyInfo, 0x%x);
	mps_dprint_field(sc, MPS_INFO, "AttachedPhyInfo Reason: %s (0x%x)\n",
	    mps_describe_table(mps_phyinfo_reason_names,
	    buf->AttachedPhyInfo & 0xf), buf->AttachedPhyInfo);
	MPS_PRINTFIELD(sc, buf, ZoneGroup, %d);
	MPS_PRINTFIELD(sc, buf, SelfConfigStatus, 0x%x);
}
Пример #6
0
void
mps_print_iocfacts(struct mps_softc *sc, MPI2_IOC_FACTS_REPLY *facts)
{

	MPS_PRINTFIELD_START(sc, "IOCFacts");
	MPS_PRINTFIELD(sc, facts, MsgVersion, 0x%x);
	MPS_PRINTFIELD(sc, facts, HeaderVersion, 0x%x);
	MPS_PRINTFIELD(sc, facts, IOCNumber, %d);
	MPS_PRINTFIELD(sc, facts, IOCExceptions, 0x%x);
	MPS_PRINTFIELD(sc, facts, MaxChainDepth, %d);
	mps_dprint_field(sc, MPS_INFO, "WhoInit: %s\n",
	    mps_describe_table(mps_whoinit_names, facts->WhoInit));
	MPS_PRINTFIELD(sc, facts, NumberOfPorts, %d);
	MPS_PRINTFIELD(sc, facts, RequestCredit, %d);
	MPS_PRINTFIELD(sc, facts, ProductID, 0x%x);
	mps_dprint_field(sc, MPS_INFO, "IOCCapabilities: %b\n",
	    facts->IOCCapabilities, "\20" "\3ScsiTaskFull" "\4DiagTrace"
	    "\5SnapBuf" "\6ExtBuf" "\7EEDP" "\10BiDirTarg" "\11Multicast"
	    "\14TransRetry" "\15IR" "\16EventReplay" "\17RaidAccel"
	    "\20MSIXIndex" "\21HostDisc");
	mps_dprint_field(sc, MPS_INFO, "FWVersion= %d-%d-%d-%d\n",
	    facts->FWVersion.Struct.Major,
	    facts->FWVersion.Struct.Minor,
	    facts->FWVersion.Struct.Unit,
	    facts->FWVersion.Struct.Dev);
	MPS_PRINTFIELD(sc, facts, IOCRequestFrameSize, %d);
	MPS_PRINTFIELD(sc, facts, MaxInitiators, %d);
	MPS_PRINTFIELD(sc, facts, MaxTargets, %d);
	MPS_PRINTFIELD(sc, facts, MaxSasExpanders, %d);
	MPS_PRINTFIELD(sc, facts, MaxEnclosures, %d);
	mps_dprint_field(sc, MPS_INFO, "ProtocolFlags: %b\n",
	    facts->ProtocolFlags, "\20" "\1ScsiTarg" "\2ScsiInit");
	MPS_PRINTFIELD(sc, facts, HighPriorityCredit, %d);
	MPS_PRINTFIELD(sc, facts, MaxReplyDescriptorPostQueueDepth, %d);
	MPS_PRINTFIELD(sc, facts, ReplyFrameSize, %d);
	MPS_PRINTFIELD(sc, facts, MaxVolumes, %d);
	MPS_PRINTFIELD(sc, facts, MaxDevHandle, %d);
	MPS_PRINTFIELD(sc, facts, MaxPersistentEntries, %d);
}
Пример #7
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;
	}
}
Пример #8
0
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);

}
Пример #9
0
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);
	
}