/*
******************************************************************************
*
* This routine calculates the arm, span and block for the specified stripe and
* reference in stripe.
*
* Inputs :
*
*    ld   - Logical drive number
*    stripRow        - Stripe number
*    stripRef    - Reference in stripe
*
* Outputs :
*
*    span          - Span number
*    block         - Absolute Block number in the physical disk
*/
u8 MR_GetPhyParams(struct megasas_instance *instance, u32 ld, u64 stripRow,
		u16 stripRef, struct IO_REQUEST_INFO *io_info,
		struct RAID_CONTEXT *pRAID_Context,
		struct MR_FW_RAID_MAP_ALL *map)
{
	struct MR_LD_RAID  *raid = MR_LdRaidGet(ld, map);
	u32         pd, arRef;
	u8          physArm, span;
	u64         row;
	u8	    retval = TRUE;
	u8          do_invader = 0;
	u64	    *pdBlock = &io_info->pdBlock;
	u16	    *pDevHandle = &io_info->devHandle;

	if ((instance->pdev->device == PCI_DEVICE_ID_LSI_INVADER ||
		instance->pdev->device == PCI_DEVICE_ID_LSI_FURY))
		do_invader = 1;

	row =  mega_div64_32(stripRow, raid->rowDataSize);

	if (raid->level == 6) {
		/* logical arm within row */
		u32 logArm =  mega_mod64(stripRow, raid->rowDataSize);
		u32 rowMod, armQ, arm;

		if (raid->rowSize == 0)
			return FALSE;
		/* get logical row mod */
		rowMod = mega_mod64(row, raid->rowSize);
		armQ = raid->rowSize-1-rowMod; /* index of Q drive */
		arm = armQ+1+logArm; /* data always logically follows Q */
		if (arm >= raid->rowSize) /* handle wrap condition */
			arm -= raid->rowSize;
		physArm = (u8)arm;
	} else  {
		if (raid->modFactor == 0)
			return FALSE;
		physArm = MR_LdDataArmGet(ld,  mega_mod64(stripRow,
							  raid->modFactor),
					  map);
	}

	if (raid->spanDepth == 1) {
		span = 0;
		*pdBlock = row << raid->stripeShift;
	} else {
		span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map);
		if (span == SPAN_INVALID)
			return FALSE;
	}

	/* Get the array on which this span is present */
	arRef       = MR_LdSpanArrayGet(ld, span, map);
	pd          = MR_ArPdGet(arRef, physArm, map); /* Get the pd */

	if (pd != MR_PD_INVALID)
		/* Get dev handle from Pd. */
		*pDevHandle = MR_PdDevHandleGet(pd, map);
	else {
		*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
		if ((raid->level >= 5) &&
			(!do_invader  || (do_invader &&
			(raid->regTypeReqOnRead != REGION_TYPE_UNUSED))))
			pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
		else if (raid->level == 1) {
			/* Get alternate Pd. */
			pd = MR_ArPdGet(arRef, physArm + 1, map);
			if (pd != MR_PD_INVALID)
				/* Get dev handle from Pd */
				*pDevHandle = MR_PdDevHandleGet(pd, map);
		}
	}

	*pdBlock += stripRef + le64_to_cpu(MR_LdSpanPtrGet(ld, span, map)->startBlk);
	pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
		physArm;
	return retval;
}
예제 #2
0
/*
 * *************************************************************
 *
 * This routine calculates the arm, span and block for
 * the specified stripe and reference in stripe.
 *
 * Inputs :
 *
 *    ld   - Logical drive number
 *    stripRow        - Stripe number
 *    stripRef    - Reference in stripe
 *
 * Outputs :
 *
 *    span          - Span number
 *    block         - Absolute Block number in the physical disk
 */
U8
MR_GetPhyParams(struct mrsas_instance *instance, U32 ld, U64 stripRow,
    U16 stripRef, U64 *pdBlock, U16 *pDevHandle,
    MPI2_SCSI_IO_VENDOR_UNIQUE *pRAID_Context, MR_FW_RAID_MAP_ALL *map)
{
	MR_LD_RAID	*raid = MR_LdRaidGet(ld, map);
	U32		pd, arRef;
	U8		physArm, span;
	U64		row;
	int		error_code = 0;
	U8		retval = TRUE;
	U32		rowMod;
	U32		armQ;
	U32		arm;
	U16		devid = instance->device_id;

	ASSERT(raid->rowDataSize != 0);

	row = (stripRow / raid->rowDataSize);

	if (raid->level == 6) {
		U32 logArm =  (stripRow % (raid->rowDataSize));

		if (raid->rowSize == 0) {
			return (FALSE);
		}
		rowMod = (row % (raid->rowSize));
		armQ = raid->rowSize-1-rowMod;
		arm = armQ + 1 + logArm;
		if (arm >= raid->rowSize)
			arm -= raid->rowSize;
		physArm = (U8)arm;
	} else {
		if (raid->modFactor == 0)
			return (FALSE);
		physArm = MR_LdDataArmGet(ld,
		    (stripRow % (raid->modFactor)), map);
	}
	if (raid->spanDepth == 1) {
		span = 0;
		*pdBlock = row << raid->stripeShift;
	} else
		span = (U8)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code);

	if (error_code == 1)
		return (FALSE);

	/* Get the array on which this span is present. */
	arRef		= MR_LdSpanArrayGet(ld, span, map);
	/* Get the Pd. */
	pd		= MR_ArPdGet(arRef, physArm, map);
	/* Get dev handle from Pd. */
	if (pd != MR_PD_INVALID) {
		*pDevHandle	= MR_PdDevHandleGet(pd, map);
	} else {
		*pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */
		if ((raid->level >= 5) &&
		    ((devid != PCI_DEVICE_ID_LSI_INVADER) ||
		    ((devid == PCI_DEVICE_ID_LSI_INVADER ||
		    (devid == PCI_DEVICE_ID_LSI_FURY)) &&
		    raid->regTypeReqOnRead != REGION_TYPE_UNUSED))) {
			pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE;
		} else if (raid->level == 1) {
			/* Get Alternate Pd. */
			pd = MR_ArPdGet(arRef, physArm + 1, map);
			/* Get dev handle from Pd. */
			if (pd != MR_PD_INVALID)
				*pDevHandle = MR_PdDevHandleGet(pd, map);
		}
	}

	*pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk;

	pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) |
	    physArm;

	return (retval);
}