dsgprintk((MYIOC_s_ERR_FMT 
dsgprintk((MYIOC_s_INFO_FMT 
mptscsih_AddSGE(MPT_ADAPTER *ioc, struct scsi_cmnd *SCpnt,		SCSIIORequest_t *pReq, int req_idx){	char 	*psge;	char	*chainSge;	struct scatterlist *sg;	int	 frm_sz;	int	 sges_left, sg_done;	int	 chain_idx = MPT_HOST_NO_CHAIN;	int	 sgeOffset;	int	 numSgeSlots, numSgeThisFrame;	u32	 sgflags, sgdir, thisxfer = 0;	int	 chain_dma_off = 0;	int	 newIndex;	int	 ii;	dma_addr_t v2;	u32	RequestNB;	sgdir = le32_to_cpu(pReq->Control) & MPI_SCSIIO_CONTROL_DATADIRECTION_MASK;	if (sgdir == MPI_SCSIIO_CONTROL_WRITE)  {		sgdir = MPT_TRANSFER_HOST_TO_IOC;	} else {		sgdir = MPT_TRANSFER_IOC_TO_HOST;	}	psge = (char *) &pReq->SGL;	frm_sz = ioc->req_sz;	/* Map the data portion, if any.	 * sges_left  = 0 if no data transfer.	 */	if ( (sges_left = SCpnt->use_sg) ) {		sges_left = pci_map_sg(ioc->pcidev,			       (struct scatterlist *) SCpnt->request_buffer, 			       SCpnt->use_sg,			       SCpnt->sc_data_direction);		if (sges_left == 0)			return FAILED;	} else if (SCpnt->request_bufflen) {		SCpnt->SCp.dma_handle = pci_map_single(ioc->pcidev,				      SCpnt->request_buffer,				      SCpnt->request_bufflen,				      SCpnt->sc_data_direction);		dsgprintk((MYIOC_s_INFO_FMT "SG: non-SG for %p, len=%d\n",				ioc->name, SCpnt, SCpnt->request_bufflen));		mptscsih_add_sge((char *) &pReq->SGL,			0xD1000000|MPT_SGE_FLAGS_ADDRESSING|sgdir|SCpnt->request_bufflen,			SCpnt->SCp.dma_handle);		return SUCCESS;	}	/* Handle the SG case.	 */	sg = (struct scatterlist *) SCpnt->request_buffer;	sg_done  = 0;	sgeOffset = sizeof(SCSIIORequest_t) - sizeof(SGE_IO_UNION);	chainSge = NULL;	/* Prior to entering this loop - the following must be set	 * current MF:  sgeOffset (bytes)	 *              chainSge (Null if original MF is not a chain buffer)	 *              sg_done (num SGE done for this MF)	 */nextSGEset:	numSgeSlots = ((frm_sz - sgeOffset) / (sizeof(u32) + sizeof(dma_addr_t)) );	numSgeThisFrame = (sges_left < numSgeSlots) ? sges_left : numSgeSlots;	sgflags = MPT_SGE_FLAGS_SIMPLE_ELEMENT | MPT_SGE_FLAGS_ADDRESSING | sgdir;	/* Get first (num - 1) SG elements	 * Skip any SG entries with a length of 0	 * NOTE: at finish, sg and psge pointed to NEXT data/location positions	 */	for (ii=0; ii < (numSgeThisFrame-1); ii++) {		thisxfer = sg_dma_len(sg);		if (thisxfer == 0) {			sg ++; /* Get next SG element from the OS */			sg_done++;			continue;		}		v2 = sg_dma_address(sg);		mptscsih_add_sge(psge, sgflags | thisxfer, v2);		sg++;		/* Get next SG element from the OS */		psge += (sizeof(u32) + sizeof(dma_addr_t));		sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));		sg_done++;	}	if (numSgeThisFrame == sges_left) {		/* Add last element, end of buffer and end of list flags.		 */		sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT |				MPT_SGE_FLAGS_END_OF_BUFFER |				MPT_SGE_FLAGS_END_OF_LIST;		/* Add last SGE and set termination flags.		 * Note: Last SGE may have a length of 0 - which should be ok.		 */		thisxfer = sg_dma_len(sg);		v2 = sg_dma_address(sg);		mptscsih_add_sge(psge, sgflags | thisxfer, v2);		/*		sg++;		psge += (sizeof(u32) + sizeof(dma_addr_t));		*/		sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));		sg_done++;		if (chainSge) {			/* The current buffer is a chain buffer,			 * but there is not another one.			 * Update the chain element			 * Offset and Length fields.			 */			mptscsih_add_chain((char *)chainSge, 0, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);		} else {			/* The current buffer is the original MF			 * and there is no Chain buffer.			 */			pReq->ChainOffset = 0;			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;			dsgprintk((MYIOC_s_ERR_FMT 			    "Single Buffer RequestNB=%x, sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));			ioc->RequestNB[req_idx] = RequestNB;		}	} else {		/* At least one chain buffer is needed.		 * Complete the first MF		 *  - last SGE element, set the LastElement bit		 *  - set ChainOffset (words) for orig MF		 *             (OR finish previous MF chain buffer)		 *  - update MFStructPtr ChainIndex		 *  - Populate chain element		 * Also		 * Loop until done.		 */		dsgprintk((MYIOC_s_INFO_FMT "SG: Chain Required! sg done %d\n",				ioc->name, sg_done));		/* Set LAST_ELEMENT flag for last non-chain element		 * in the buffer. Since psge points at the NEXT		 * SGE element, go back one SGE element, update the flags		 * and reset the pointer. (Note: sgflags & thisxfer are already		 * set properly).		 */		if (sg_done) {			u32 *ptmp = (u32 *) (psge - (sizeof(u32) + sizeof(dma_addr_t)));			sgflags = le32_to_cpu(*ptmp);			sgflags |= MPT_SGE_FLAGS_LAST_ELEMENT;			*ptmp = cpu_to_le32(sgflags);		}		if (chainSge) {			/* The current buffer is a chain buffer.			 * chainSge points to the previous Chain Element.			 * Update its chain element Offset and Length (must			 * include chain element size) fields.			 * Old chain element is now complete.			 */			u8 nextChain = (u8) (sgeOffset >> 2);			sgeOffset += (sizeof(u32) + sizeof(dma_addr_t));			mptscsih_add_chain((char *)chainSge, nextChain, sgeOffset, ioc->ChainBufferDMA + chain_dma_off);		} else {			/* The original MF buffer requires a chain buffer -			 * set the offset.			 * Last element in this MF is a chain element.			 */			pReq->ChainOffset = (u8) (sgeOffset >> 2);			RequestNB = (((sgeOffset - 1) >> ioc->NBShiftFactor)  + 1) & 0x03;			dsgprintk((MYIOC_s_ERR_FMT "Chain Buffer Needed, RequestNB=%x sgeOffset=%d\n", ioc->name, RequestNB, sgeOffset));			ioc->RequestNB[req_idx] = RequestNB;		}		sges_left -= sg_done;		/* NOTE: psge points to the beginning of the chain element		 * in current buffer. Get a chain buffer.		 */		dsgprintk((MYIOC_s_INFO_FMT 		    "calling getFreeChainBuffer SCSI cmd=%02x (%p)\n",		    ioc->name, pReq->CDB[0], SCpnt));		if ((mptscsih_getFreeChainBuffer(ioc, &newIndex)) == FAILED)			return FAILED;		/* Update the tracking arrays.		 * If chainSge == NULL, update ReqToChain, else ChainToChain		 */		if (chainSge) {			ioc->ChainToChain[chain_idx] = newIndex;		} else {			ioc->ReqToChain[req_idx] = newIndex;		}		chain_idx = newIndex;		chain_dma_off = ioc->req_sz * chain_idx;		/* Populate the chainSGE for the current buffer.		 * - Set chain buffer pointer to psge and fill		 *   out the Address and Flags fields.		 */		chainSge = (char *) psge;		dsgprintk((KERN_INFO "  Current buff @ %p (index 0x%x)",				psge, req_idx));		/* Start the SGE for the next buffer		 */		psge = (char *) (ioc->ChainBuffer + chain_dma_off);		sgeOffset = 0;		sg_done = 0;		dsgprintk((KERN_INFO "  Chain buff @ %p (index 0x%x)\n",				psge, chain_idx));		/* Start the SGE for the next buffer		 */		goto nextSGEset;	}	return SUCCESS;} /* mptscsih_AddSGE() */
10457	/local/tlutelli/issta_data/temp/c/2005_temp/2005/10457/c6678e0cfb41b029c3600c54b5bb65954de1230a/mptscsih.c/buggy/drivers/message/fusion/mptscsih.c