scsi_to_pci_dma_dir(Cmnd->sc_data_direction)); 
Cmnd->sc_data_direction); 
static ULONG build_SEST_sgList(     struct pci_dev *pcidev,    ULONG *SESTalPairStart,  // the 3 len/address buffers in SEST    Scsi_Cmnd *Cmnd,    ULONG *sgPairs,     PSGPAGES *sgPages_head)  // link list of TL Ext. S/G pages from O/S Pool    {  ULONG i, AllocatedPages=0; // Tach Ext. S/G page allocations  ULONG* alPair = SESTalPairStart;  ULONG* ext_sg_page_phys_addr_place = NULL;  int PairCount;  unsigned long ulBuff, contigaddr;  ULONG total_data_len=0; // (in bytes)  ULONG bytes_to_go = Cmnd->request_bufflen; // total xfer (S/G sum)  ULONG thisMappingLen;  struct scatterlist *sgl = NULL;  // S/G list (Linux format)  int sg_count, totalsgs;   dma_addr_t busaddr;  unsigned long thislen, offset;  PSGPAGES *sgpage = sgPages_head;  PSGPAGES prev_page = NULL;# define WE_HAVE_SG_LIST (sgl != (unsigned long) NULL)  contigaddr = (unsigned long) NULL;  if( !Cmnd->use_sg )  // no S/G list?  {	if (bytes_to_go <= TL_MAX_SG_ELEM_LEN)	{    		*sgPairs = 1;	// use "local" S/G pair in SEST entry				// (for now, ignore address bits above #31)		*alPair++ = bytes_to_go; // bits 18-0, length		if (bytes_to_go != 0) {			contigaddr = ulBuff = pci_map_single(pcidev, 				Cmnd->request_buffer, 				Cmnd->request_bufflen,				scsi_to_pci_dma_dir(Cmnd->sc_data_direction));			// printk("ms %p ", ulBuff);		}		else {			// No data transfer, (e.g.: Test Unit Ready)			// printk("btg=0 ");			*sgPairs = 0;			memset(alPair, 0, sizeof(*alPair));			return 0;		}#		if BITS_PER_LONG > 32    			if( ulBuff >>32 ) {      				printk("FATAL! Tachyon DMA address %p "					"exceeds 32 bits\n", (void*)ulBuff );      				return 0;    			}#		endif    		*alPair = (ULONG)ulBuff;          		return bytes_to_go;	} 	else	// We have a single large (too big) contiguous buffer.	{	// We will have to break it up.  We'll use the scatter		// gather code way below, but use contigaddr instead		// of sg_dma_addr(). (this is a very rare case).		unsigned long btg;		contigaddr = pci_map_single(pcidev, Cmnd->request_buffer, 				Cmnd->request_bufflen,				scsi_to_pci_dma_dir(Cmnd->sc_data_direction));		// printk("contigaddr = %p, len = %d\n", 		//	(void *) contigaddr, bytes_to_go);		totalsgs = 0;		for (btg = bytes_to_go; btg > 0; ) {			btg -= ( btg > TL_MAX_SG_ELEM_LEN ? 				TL_MAX_SG_ELEM_LEN : btg );			totalsgs++;		}		sgl = NULL;		*sgPairs = totalsgs;	}  }  else  // we do have a scatter gather list  {	// [TBD - update for Linux to support > 32 bits addressing]	// since the format for local & extended S/G lists is different,	// check if S/G pairs exceeds 3.	// *sgPairs = Cmnd->use_sg; Nope, that's wrong. 	sgl = (struct scatterlist*)Cmnd->request_buffer;  	sg_count = pci_map_sg(pcidev, sgl, Cmnd->use_sg, 		scsi_to_pci_dma_dir(Cmnd->sc_data_direction));  	if( sg_count <= 3 ) {	// we need to be careful here that no individual mapping	// is too large, and if any is, that breaking it up	// doesn't push us over 3 sgs, or, if it does, that we	// handle that case.  Tachyon can take 0x7FFFF bits for length,	// but sg structure uses "unsigned int", on the face of it, 	// up to 0xFFFFFFFF or even more.		int i;		unsigned long thislen;		totalsgs = 0;		for (i=0;i<sg_count;i++) {      			thislen = sg_dma_len(&sgl[i]);			while (thislen >= TL_MAX_SG_ELEM_LEN) {				totalsgs++;				thislen -= TL_MAX_SG_ELEM_LEN;			}			if (thislen > 0) totalsgs++;		}		*sgPairs = totalsgs;  	} else totalsgs = 999; // as a first estimate, definitely >3, 			      	// if (totalsgs != sg_count) 	//	printk("totalsgs = %d, sgcount=%d\n",totalsgs,sg_count);  }  if( totalsgs <= 3 ) // can (must) use "local" SEST list  {    while( bytes_to_go)    {      offset = 0L;      if ( WE_HAVE_SG_LIST ) 	thisMappingLen = sg_dma_len(sgl);      else					// or contiguous buffer?	thisMappingLen = bytes_to_go;      while (thisMappingLen > 0)      {  	thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? 		TL_MAX_SG_ELEM_LEN : thisMappingLen;	bytes_to_go = bytes_to_go - thislen;	// we have L/A pair; L = thislen, A = physicalAddress	// load into SEST...	total_data_len += thislen;	*alPair = thislen; // bits 18-0, length	alPair++;	if ( WE_HAVE_SG_LIST ) 		ulBuff = sg_dma_address(sgl) + offset;	else		ulBuff = contigaddr + offset;	offset += thislen;#	if BITS_PER_LONG > 32		if( ulBuff >>32 ) {        		printk("cqpfcTS: 2Tach DMA address %p > 32 bits\n", 				(void*)ulBuff );		    printk("%s = %p, offset = %ld\n", 			WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr",			WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr,				offset);        		return 0;      		}#	endif        *alPair++ = (ULONG)ulBuff; // lower 32 bits (31-0)	thisMappingLen -= thislen;      }      if ( WE_HAVE_SG_LIST ) ++sgl;  // next S/G pair	else if (bytes_to_go != 0) printk("BTG not zero!\n");#     ifdef DBG_SEST_SGLIST	printk("L=%d ", thisMappingLen);	printk("btg=%d ", bytes_to_go);#     endif    }    // printk("i:%d\n", *sgPairs);  }  else    // more than 3 pairs requires Extended S/G page (Pool Allocation)  {    // clear out SEST DWORDs (local S/G addr) C-F (A-B set in following logic)    for( i=2; i<6; i++)      alPair[i] = 0;    PairCount = TL_EXT_SG_PAGE_COUNT;    // forces initial page allocation    totalsgs = 0;    while( bytes_to_go )    {      // Per SEST format, we can support 524287 byte lengths per      // S/G pair.  Typical user buffers are 4k, and very rarely      // exceed 12k due to fragmentation of physical memory pages.      // However, on certain O/S system (not "user") buffers (on platforms       // with huge memories), it's possible to exceed this      // length in a single S/G address/len mapping, so we have to handle      // that.      offset = 0L;      if ( WE_HAVE_SG_LIST ) 	thisMappingLen = sg_dma_len(sgl);      else	thisMappingLen = bytes_to_go;      while (thisMappingLen > 0)      {	thislen = thisMappingLen > TL_MAX_SG_ELEM_LEN ? 		TL_MAX_SG_ELEM_LEN : thisMappingLen;	// printk("%d/%d/%d\n", thislen, thisMappingLen, bytes_to_go);        	// should we load into "this" extended S/G page, or allocate	// new page?	if( PairCount >= TL_EXT_SG_PAGE_COUNT )	{	  // Now, we have to map the previous page, (triggering buffer bounce)	  // The first time thru the loop, there won't be a previous page.	  if (prev_page != NULL) // is there a prev page? 	  {		// this code is normally kind of hard to trigger, 		// you have to use up more than 256 scatter gather 		// elements to get here.  Cranking down TL_MAX_SG_ELEM_LEN		// to an absurdly low value (128 bytes or so) to artificially		// break i/o's into a zillion pieces is how I tested it. 		busaddr = cpqfc_pci_map_sg_page(pcidev,				ext_sg_page_phys_addr_place,				prev_page->page,        			&prev_page->busaddr,        			&prev_page->maplen,				PairCount);          }           // Allocate the TL Extended S/G list page.  We have          // to allocate twice what we want to ensure required TL alignment          // (Tachlite TL/TS User Man. Rev 6.0, p 168)          // We store the original allocated PVOID so we can free later	  *sgpage = kmalloc( sizeof(SGPAGES), GFP_ATOMIC);	  if ( ! *sgpage )          {		printk("cpqfc: Allocation failed @ %d S/G page allocations\n",			AllocatedPages);		total_data_len = 0;  // failure!! Ext. S/G is All-or-none affair	        // unmap the previous mappings, if any.	        cpqfc_undo_SEST_mappings(pcidev, contigaddr, 			Cmnd->request_bufflen,			scsi_to_pci_dma_dir(Cmnd->sc_data_direction),  			sgl, Cmnd->use_sg, sgPages_head, AllocatedPages+1);		// FIXME: testing shows that if we get here, 		// it's bad news.  (this has been this way for a long 		// time though, AFAIK.  Not that that excuses it.)		return 0; // give up (and probably hang the system)          }                               // clear out memory we just allocated	  memset( (*sgpage)->page,0,TL_EXT_SG_PAGE_BYTELEN*2);	  (*sgpage)->next = NULL;	  (*sgpage)->busaddr = (dma_addr_t) NULL;	  (*sgpage)->maplen = 0L;      	  // align the memory - TL requires sizeof() Ext. S/G page alignment.	  // We doubled the actual required size so we could mask off LSBs 	  // to get desired offset 	  ulBuff = (unsigned long) (*sgpage)->page;	  ulBuff += TL_EXT_SG_PAGE_BYTELEN;	  ulBuff &= ~(TL_EXT_SG_PAGE_BYTELEN -1);	  // set pointer, in SEST if first Ext. S/G page, or in last pair	  // of linked Ext. S/G pages... (Only 32-bit PVOIDs, so just 	  // load lower 32 bits)	  // NOTE: the Len field must be '0' if this is the first Ext. S/G	  // pointer in SEST, and not 0 otherwise (we know thislen != 0).	  *alPair = (alPair != SESTalPairStart) ? thislen : 0;#	  ifdef DBG_SEST_SGLIST        	printk("PairCount %d @%p even %Xh, ", 			PairCount, alPair, *alPair);#	  endif	  // Save the place where we need to store the physical	  // address of this scatter gather page which we get when we map it	  // (and mapping we can do only after we fill it in.)	  alPair++;  // next DWORD, will contain phys addr of the ext page	  ext_sg_page_phys_addr_place = alPair;	  // Now, set alPair = the virtual addr of the (Extended) S/G page	  // which will accept the Len/ PhysicalAddress pairs	  alPair = (ULONG *) ulBuff;	  AllocatedPages++;	  if (AllocatedPages >= ap_hi_water)	  {		// This message should rarely, if ever, come out.		// Previously (cpqfc version <= 2.0.5) the driver would		// just puke if more than 4 SG pages were used, and nobody		// ever complained about that.  This only comes out if 		// more than 8 pages are used.		printk(KERN_WARNING		"cpqfc: Possible danger.  %d scatter gather pages used.\n"			"cpqfc: detected seemingly extreme memory "			"fragmentation or huge data transfers.\n", 			AllocatedPages);		ap_hi_water = AllocatedPages+1;	  }			  PairCount = 1;  // starting new Ext. S/G page	  prev_page = (*sgpage);  // remember this page, for next time thru	  sgpage = &((*sgpage)->next);	}  // end of new TL Ext. S/G page allocation	*alPair = thislen; // bits 18-0, length (range check above)      #	ifdef DBG_SEST_SGLIST	  printk("PairCount %d @%p, even %Xh, ", PairCount, alPair, *alPair);#	endif	alPair++;    // next DWORD, physical address 	if ( WE_HAVE_SG_LIST ) 		ulBuff = sg_dma_address(sgl) + offset;	else		ulBuff = contigaddr + offset;	offset += thislen;#	if BITS_PER_LONG > 32          if( ulBuff >>32 )	  {	    printk("cqpfcTS: 1Tach DMA address %p > 32 bits\n", (void*)ulBuff );	    printk("%s = %p, offset = %ld\n", 		WE_HAVE_SG_LIST ? "ulBuff" : "contigaddr",		WE_HAVE_SG_LIST ? (void *) ulBuff : (void *) contigaddr,			offset);	    return 0;	  }#	endif	*alPair = (ULONG) ulBuff; // lower 32 bits (31-0)#       ifdef DBG_SEST_SGLIST        printk("odd %Xh\n", *alPair);#       endif	alPair++;    // next DWORD, next address/length pair                                           	PairCount++; // next Length/Address pair	// if (PairCount > pc_hi_water)	// {		// printk("pc hi = %d ", PairCount);		// pc_hi_water = PairCount;	// }	bytes_to_go -= thislen;	total_data_len += thislen;  	thisMappingLen -= thislen;	totalsgs++;      } // while (thisMappingLen > 0)      if ( WE_HAVE_SG_LIST ) sgl++;  // next S/G pair    } // while (bytes_to_go)    // printk("Totalsgs=%d\n", totalsgs);    *sgPairs = totalsgs;    // PCI map (and bounce) the last (and usually only) extended SG page    busaddr = cpqfc_pci_map_sg_page(pcidev,		ext_sg_page_phys_addr_place,		prev_page->page, 		&prev_page->busaddr, 		&prev_page->maplen,		PairCount);  }  return total_data_len;}
4520	/local/tlutelli/issta_data/temp/c/2005_temp/2005/4520/be7db055dd7261522557046370f49160728e3847/cpqfcTSworker.c/clean/drivers/scsi/cpqfcTSworker.c