freebsd-dev/sys/dev/pms/freebsd/driver/common/lxutil.c
Tycho Nightingale 41f6c3f0e7 pms(4) should use bus_get_dma_tag() to get parent tag.
Reviewed by:	imp
Sponsored by:	Dell EMC Isilon
2019-02-08 16:05:38 +00:00

787 lines
32 KiB
C

/******************************************************************************
*Copyright (c) 2014 PMC-Sierra, Inc. All rights reserved.
*
*Redistribution and use in source and binary forms, with or without modification, are permitted provided
*that the following conditions are met:
*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
*following disclaimer.
*2. Redistributions in binary form must reproduce the above copyright notice,
*this list of conditions and the following disclaimer in the documentation and/or other materials provided
*with the distribution.
*
*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
******************************************************************************/
/* $FreeBSD$ */
/******************************************************************************
This program is part of PMC-Sierra initiator/target device driver.
The functions here are commonly used by different type of drivers that support
PMC-Sierra storage network initiator hardware.
******************************************************************************/
MALLOC_DEFINE( M_PMC_MMAL, "agtiapi_MemAlloc malloc",
"allocated from agtiapi_MemAlloc as simple malloc case" );
/*****************************************************************************
agtiapi_DelayMSec()
Purpose:
Busy wait for number of mili-seconds
Parameters:
U32 MiliSeconds (IN) Number of mili-seconds to delay
Return:
Note:
*****************************************************************************/
STATIC void agtiapi_DelayMSec( U32 MiliSeconds )
{
DELAY(MiliSeconds * 1000); // DELAY takes in usecs
}
/******************************************************************************
agtiapi_typhAlloc()
Purpose:
Preallocation handling
Allocate DMA memory which will be divided among proper pointers in
agtiapi_MemAlloc() later
Parameters:
ag_card_info_t *thisCardInst (IN)
Return:
AGTIAPI_SUCCESS - success
AGTIAPI_FAIL - fail
******************************************************************************/
STATIC agBOOLEAN agtiapi_typhAlloc( ag_card_info_t *thisCardInst )
{
struct agtiapi_softc *pmsc = thisCardInst->pCard;
int wait = 0;
if( bus_dma_tag_create( bus_get_dma_tag(pmsc->my_dev), // parent
32, // alignment
0, // boundary
BUS_SPACE_MAXADDR, // lowaddr
BUS_SPACE_MAXADDR, // highaddr
NULL, // filter
NULL, // filterarg
pmsc->typhn, // maxsize (size)
1, // number of segments
pmsc->typhn, // maxsegsize
0, // flags
NULL, // lockfunc
NULL, // lockarg
&pmsc->typh_dmat ) ) {
printf( "agtiapi_typhAlloc: Can't create no-cache mem tag\n" );
return AGTIAPI_FAIL;
}
if( bus_dmamem_alloc( pmsc->typh_dmat,
&pmsc->typh_mem,
BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_NOCACHE,
&pmsc->typh_mapp ) ) {
printf( "agtiapi_typhAlloc: Cannot allocate cache mem %d\n",
pmsc->typhn );
return AGTIAPI_FAIL;
}
if ( bus_dmamap_load( pmsc->typh_dmat,
pmsc->typh_mapp,
pmsc->typh_mem,
pmsc->typhn,
agtiapi_MemoryCB, // try reuse of CB for same goal
&pmsc->typh_busaddr,
0 ) || !pmsc->typh_busaddr ) {
for( ; wait < 20; wait++ ) {
if( pmsc->typh_busaddr ) break;
DELAY( 50000 );
}
if( ! pmsc->typh_busaddr ) {
printf( "agtiapi_typhAlloc: cache mem won't load %d\n",
pmsc->typhn );
return AGTIAPI_FAIL;
}
}
pmsc->typhIdx = 0;
pmsc->tyPhsIx = 0;
return AGTIAPI_SUCCESS;
}
/******************************************************************************
agtiapi_InitResource()
Purpose:
Mapping PCI memory space
Allocate and initialize per card based resource
Parameters:
ag_card_info_t *pCardInfo (IN)
Return:
AGTIAPI_SUCCESS - success
AGTIAPI_FAIL - fail
Note:
******************************************************************************/
STATIC agBOOLEAN agtiapi_InitResource( ag_card_info_t *thisCardInst )
{
struct agtiapi_softc *pmsc = thisCardInst->pCard;
device_t devx = thisCardInst->pPCIDev;
//AGTIAPI_PRINTK( "agtiapi_InitResource: begin; pointer values %p / %p \n",
// devx, thisCardInst );
// no IO mapped card implementation, we'll implement memory mapping
if( agtiapi_typhAlloc( thisCardInst ) == AGTIAPI_FAIL ) {
printf( "agtiapi_InitResource: failed call to agtiapi_typhAlloc \n" );
return AGTIAPI_FAIL;
}
AGTIAPI_PRINTK( "agtiapi_InitResource: dma alloc MemSpan %p -- %p\n",
(void*) pmsc->typh_busaddr,
(void*) ( (U32_64)pmsc->typh_busaddr + pmsc->typhn ) );
// logical BARs for SPC:
// bar 0 and 1 - logical BAR0
// bar 2 and 3 - logical BAR1
// bar4 - logical BAR2
// bar5 - logical BAR3
// Skiping the assignments for bar 1 and bar 3 (making bar 0, 2 64-bit):
U32 bar;
U32 lBar = 0; // logicalBar
for (bar = 0; bar < PCI_NUMBER_BARS; bar++) {
if ((bar==1) || (bar==3))
continue;
thisCardInst->pciMemBaseRIDSpc[lBar] = PCIR_BAR(bar);
thisCardInst->pciMemBaseRscSpc[lBar] =
bus_alloc_resource_any( devx,
SYS_RES_MEMORY,
&(thisCardInst->pciMemBaseRIDSpc[lBar]),
RF_ACTIVE );
AGTIAPI_PRINTK( "agtiapi_InitResource: bus_alloc_resource_any rtn %p \n",
thisCardInst->pciMemBaseRscSpc[lBar] );
if ( thisCardInst->pciMemBaseRscSpc[lBar] != NULL ) {
thisCardInst->pciMemVirtAddrSpc[lBar] =
(caddr_t)rman_get_virtual(
thisCardInst->pciMemBaseRscSpc[lBar] );
thisCardInst->pciMemBaseSpc[lBar] =
bus_get_resource_start( devx, SYS_RES_MEMORY,
thisCardInst->pciMemBaseRIDSpc[lBar]);
thisCardInst->pciMemSizeSpc[lBar] =
bus_get_resource_count( devx, SYS_RES_MEMORY,
thisCardInst->pciMemBaseRIDSpc[lBar] );
AGTIAPI_PRINTK( "agtiapi_InitResource: PCI: bar %d, lBar %d "
"VirtAddr=%lx, len=%d\n", bar, lBar,
(long unsigned int)thisCardInst->pciMemVirtAddrSpc[lBar],
thisCardInst->pciMemSizeSpc[lBar] );
}
else {
thisCardInst->pciMemVirtAddrSpc[lBar] = 0;
thisCardInst->pciMemBaseSpc[lBar] = 0;
thisCardInst->pciMemSizeSpc[lBar] = 0;
}
lBar++;
}
thisCardInst->pciMemVirtAddr = thisCardInst->pciMemVirtAddrSpc[0];
thisCardInst->pciMemSize = thisCardInst->pciMemSizeSpc[0];
thisCardInst->pciMemBase = thisCardInst->pciMemBaseSpc[0];
// Allocate all TI data structure required resources.
// tiLoLevelResource
U32 numVal;
ag_resource_info_t *pRscInfo;
pRscInfo = &thisCardInst->tiRscInfo;
pRscInfo->tiLoLevelResource.loLevelOption.pciFunctionNumber =
pci_get_function( devx );
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
int ticksPerSec;
ticksPerSec = tvtohz( &tv );
int uSecPerTick = 1000000/USEC_PER_TICK;
if (pRscInfo->tiLoLevelResource.loLevelMem.count != 0) {
//AGTIAPI_INIT("agtiapi_InitResource: loLevelMem count = %d\n",
// pRscInfo->tiLoLevelResource.loLevelMem.count);
// adjust tick value to meet Linux requirement
pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick = uSecPerTick;
AGTIAPI_PRINTK( "agtiapi_InitResource: "
"pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick"
" 0x%x\n",
pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick );
for( numVal = 0; numVal < pRscInfo->tiLoLevelResource.loLevelMem.count;
numVal++ ) {
if( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength ==
0 ) {
AGTIAPI_PRINTK("agtiapi_InitResource: skip ZERO %d\n", numVal);
continue;
}
// check for 64 bit alignment
if ( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment <
AGTIAPI_64BIT_ALIGN ) {
AGTIAPI_PRINTK("agtiapi_InitResource: set ALIGN %d\n", numVal);
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment =
AGTIAPI_64BIT_ALIGN;
}
if( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
& (BIT(0) | BIT(1))) == TI_DMA_MEM) ||
((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
& (BIT(0) | BIT(1))) == TI_CACHED_DMA_MEM)) {
if ( thisCardInst->dmaIndex >=
sizeof(thisCardInst->tiDmaMem) /
sizeof(thisCardInst->tiDmaMem[0]) ) {
AGTIAPI_PRINTK( "Invalid dmaIndex %d ERROR\n",
thisCardInst->dmaIndex );
return AGTIAPI_FAIL;
}
thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type =
#ifdef CACHED_DMA
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
& (BIT(0) | BIT(1));
#else
TI_DMA_MEM;
#endif
if( agtiapi_MemAlloc( thisCardInst,
&thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr,
&thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaPhysAddr,
&pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr,
&pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].
physAddrUpper,
&pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].
physAddrLower,
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength,
thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type,
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment)
!= AGTIAPI_SUCCESS ) {
return AGTIAPI_FAIL;
}
thisCardInst->tiDmaMem[thisCardInst->dmaIndex].memSize =
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength;
//AGTIAPI_INIT("agtiapi_InitResource: LoMem %d dmaIndex=%d DMA virt"
// " %p, phys 0x%x, length %d align %d\n",
// numVal, pCardInfo->dmaIndex,
// pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr,
// pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].physAddrLower,
// pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength,
// pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment);
thisCardInst->dmaIndex++;
}
else if ( (pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type &
(BIT(0) | BIT(1))) == TI_CACHED_MEM) {
if (thisCardInst->cacheIndex >=
sizeof(thisCardInst->tiCachedMem) /
sizeof(thisCardInst->tiCachedMem[0])) {
AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n",
thisCardInst->cacheIndex );
return AGTIAPI_FAIL;
}
if ( agtiapi_MemAlloc( thisCardInst,
&thisCardInst->tiCachedMem[thisCardInst->cacheIndex],
(vm_paddr_t *)agNULL,
&pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr,
(U32 *)agNULL,
(U32 *)agNULL,
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength,
TI_CACHED_MEM,
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment)
!= AGTIAPI_SUCCESS ) {
return AGTIAPI_FAIL;
}
//AGTIAPI_INIT("agtiapi_InitResource: LoMem %d cacheIndex=%d CACHED "
// "vaddr %p / %p, length %d align %d\n",
// numVal, pCardInfo->cacheIndex,
// pCardInfo->tiCachedMem[pCardInfo->cacheIndex],
// pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr,
// pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength,
// pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment);
thisCardInst->cacheIndex++;
}
else if ( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
& (BIT(0) | BIT(1))) == TI_DMA_MEM_CHIP)) {
// not expecting this case, print warning that should get attention
printf( "RED ALARM: we need a BAR for TI_DMA_MEM_CHIP, ignoring!" );
}
else {
printf( "agtiapi_InitResource: Unknown required memory type %d "
"ERROR!\n",
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type);
return AGTIAPI_FAIL;
}
}
}
// end: TI data structure resources ...
// begin: tiInitiatorResource
if ( pmsc->flags & AGTIAPI_INITIATOR ) {
if ( pRscInfo->tiInitiatorResource.initiatorMem.count != 0 ) {
//AGTIAPI_INIT("agtiapi_InitResource: initiatorMem count = %d\n",
// pRscInfo->tiInitiatorResource.initiatorMem.count);
numVal =
(U32)( pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick
/ uSecPerTick );
if( pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick
% uSecPerTick > 0 )
pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick =
(numVal + 1) * uSecPerTick;
else
pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick =
numVal * uSecPerTick;
for ( numVal = 0;
numVal < pRscInfo->tiInitiatorResource.initiatorMem.count;
numVal++ ) {
// check for 64 bit alignment
if( pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
alignment < AGTIAPI_64BIT_ALIGN ) {
pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
alignment = AGTIAPI_64BIT_ALIGN;
}
if( thisCardInst->cacheIndex >=
sizeof( thisCardInst->tiCachedMem) /
sizeof( thisCardInst->tiCachedMem[0])) {
AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n",
thisCardInst->cacheIndex );
return AGTIAPI_FAIL;
}
// initiator memory is cached, no check is needed
if( agtiapi_MemAlloc( thisCardInst,
(void *)&thisCardInst->tiCachedMem[thisCardInst->cacheIndex],
(vm_paddr_t *)agNULL,
&pRscInfo->tiInitiatorResource.initiatorMem.
tdCachedMem[numVal].virtPtr,
(U32 *)agNULL,
(U32 *)agNULL,
pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
totalLength,
TI_CACHED_MEM,
pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
alignment)
!= AGTIAPI_SUCCESS) {
return AGTIAPI_FAIL;
}
// AGTIAPI_INIT("agtiapi_InitResource: IniMem %d cacheIndex=%d CACHED "
// "vaddr %p / %p, length %d align 0x%x\n",
// numVal,
// pCardInfo->cacheIndex,
// pCardInfo->tiCachedMem[pCardInfo->cacheIndex],
// pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
// virtPtr,
//pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
// totalLength,
// pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
// alignment);
thisCardInst->cacheIndex++;
}
}
}
// end: tiInitiatorResource
// begin: tiTdSharedMem
if (pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength != 0) {
// check for 64 bit alignment
if( pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment <
AGTIAPI_64BIT_ALIGN ) {
pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment = AGTIAPI_64BIT_ALIGN;
}
if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type & (BIT(0) | BIT(1)))
== TI_DMA_MEM ) {
if( thisCardInst->dmaIndex >=
sizeof(thisCardInst->tiDmaMem) / sizeof(thisCardInst->tiDmaMem[0]) ) {
AGTIAPI_PRINTK( "Invalid dmaIndex %d ERROR\n", thisCardInst->dmaIndex);
return AGTIAPI_FAIL;
}
if( agtiapi_MemAlloc( thisCardInst, (void *)&thisCardInst->
tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr,
&thisCardInst->tiDmaMem[thisCardInst->dmaIndex].
dmaPhysAddr,
&pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
&pRscInfo->tiSharedMem.tdSharedCachedMem1.
physAddrUpper,
&pRscInfo->tiSharedMem.tdSharedCachedMem1.
physAddrLower,
pRscInfo->tiSharedMem.tdSharedCachedMem1.
totalLength,
TI_DMA_MEM,
pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment)
!= AGTIAPI_SUCCESS )
return AGTIAPI_FAIL;
thisCardInst->tiDmaMem[thisCardInst->dmaIndex].memSize =
pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength +
pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment;
// printf( "agtiapi_InitResource: SharedMem DmaIndex=%d DMA "
// "virt %p / %p, phys 0x%x, align %d\n",
// thisCardInst->dmaIndex,
// thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr,
// pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
// pRscInfo->tiSharedMem.tdSharedCachedMem1.physAddrLower,
// pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment);
thisCardInst->dmaIndex++;
}
else if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type &
(BIT(0) | BIT(1)))
== TI_CACHED_MEM ) {
if( thisCardInst->cacheIndex >=
sizeof(thisCardInst->tiCachedMem) /
sizeof(thisCardInst->tiCachedMem[0]) ) {
AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n", thisCardInst->cacheIndex);
return AGTIAPI_FAIL;
}
if( agtiapi_MemAlloc( thisCardInst, (void *)&thisCardInst->
tiCachedMem[thisCardInst->cacheIndex],
(vm_paddr_t *)agNULL,
&pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
(U32 *)agNULL,
(U32 *)agNULL,
pRscInfo->
tiSharedMem.tdSharedCachedMem1.totalLength,
TI_CACHED_MEM,
pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment)
!= AGTIAPI_SUCCESS )
return AGTIAPI_FAIL;
// printf( "agtiapi_InitResource: SharedMem cacheIndex=%d CACHED "
// "vaddr %p / %p, length %d align 0x%x\n",
// thisCardInst->cacheIndex,
// thisCardInst->tiCachedMem[thisCardInst->cacheIndex],
// pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
// pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength,
// pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment);
AGTIAPI_PRINTK( "agtiapi_InitResource: SharedMem cacheIndex=%d CACHED "
"vaddr %p / %p, length %d align 0x%x\n",
thisCardInst->cacheIndex,
thisCardInst->tiCachedMem[thisCardInst->cacheIndex],
pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength,
pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment );
thisCardInst->cacheIndex++;
}
else {
AGTIAPI_PRINTK( "agtiapi_InitResource: "
"Unknown required memory type ERROR!\n" );
return AGTIAPI_FAIL;
}
}
// end: tiTdSharedMem
DELAY( 200000 ); // or use AGTIAPI_INIT_MDELAY(200);
return AGTIAPI_SUCCESS;
} // agtiapi_InitResource() ends here
/******************************************************************************
agtiapi_ScopeDMARes()
Purpose:
Determine the amount of DMA (non-cache) memory resources which will be
required for a card ( and necessarily allocated in agtiapi_InitResource() )
Parameters:
ag_card_info_t *thisCardInst (IN)
Return:
size of DMA memory which call to agtiapi_InitResource() will consume
Note:
this funcion mirrors the flow of agtiapi_InitResource()
results are stored in agtiapi_softc fields
******************************************************************************/
STATIC int agtiapi_ScopeDMARes( ag_card_info_t *thisCardInst )
{
struct agtiapi_softc *pmsc = thisCardInst->pCard;
U32 lAllMem = 0; // total memory count; typhn
U32 lTmpAlign, lTmpType, lTmpLen;
// tiLoLevelResource
U32 numVal;
ag_resource_info_t *pRscInfo;
pRscInfo = &thisCardInst->tiRscInfo;
if (pRscInfo->tiLoLevelResource.loLevelMem.count != 0) {
for( numVal = 0; numVal < pRscInfo->tiLoLevelResource.loLevelMem.count;
numVal++ ) {
if( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength ==
0 ) {
printf( "agtiapi_ScopeDMARes: skip ZERO %d\n", numVal );
continue;
}
// check for 64 bit alignment
lTmpAlign = pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment;
if( lTmpAlign < AGTIAPI_64BIT_ALIGN ) {
AGTIAPI_PRINTK("agtiapi_ScopeDMARes: set ALIGN %d\n", numVal);
//pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment =
lTmpAlign = AGTIAPI_64BIT_ALIGN;
}
if( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
& (BIT(0) | BIT(1))) == TI_DMA_MEM) ||
((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
& (BIT(0) | BIT(1))) == TI_CACHED_DMA_MEM)) {
//thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type =
lTmpType =
#ifdef CACHED_DMA
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
& (BIT(0) | BIT(1));
#else
TI_DMA_MEM;
#endif
if( lTmpType == TI_DMA_MEM ) {
lTmpLen =
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength;
lAllMem += lTmpLen + lTmpAlign;
}
//printf( "agtiapi_ScopeDMARes: call 1 0x%x\n", lAllMem );
}
else if ( ( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type &
(BIT(0) | BIT(1)) ) == TI_CACHED_MEM ) {
// these are not the droids we're looking for
if( thisCardInst->cacheIndex >=
sizeof(thisCardInst->tiCachedMem) /
sizeof(thisCardInst->tiCachedMem[0]) ) {
AGTIAPI_PRINTK( "agtiapi_ScopeDMARes: Invalid cacheIndex %d ERROR\n",
thisCardInst->cacheIndex );
return lAllMem;
}
}
else {
printf( "agtiapi_ScopeDMARes: Unknown required memory type %d "
"ERROR!\n",
pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type );
return lAllMem;
}
}
}
// end: TI data structure resources ...
// nothing for tiInitiatorResource
// begin: tiTdSharedMem
if (pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength != 0) {
// check for 64 bit alignment
lTmpAlign = pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment;
if( lTmpAlign < AGTIAPI_64BIT_ALIGN ) {
//pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment=AGTIAPI_64BIT_ALIGN;
lTmpAlign = AGTIAPI_64BIT_ALIGN;
}
if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type & (BIT(0) | BIT(1)))
== TI_DMA_MEM ) {
lTmpLen = pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength;
lAllMem += lTmpLen + lTmpAlign;
// printf( "agtiapi_ScopeDMARes: call 4D 0x%x\n", lAllMem );
}
else if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type &
(BIT(0) | BIT(1)))
!= TI_CACHED_MEM ) {
printf( "agtiapi_ScopeDMARes: Unknown required memory type ERROR!\n" );
}
}
// end: tiTdSharedMem
pmsc->typhn = lAllMem;
return lAllMem;
} // agtiapi_ScopeDMARes() ends here
STATIC void agtiapi_ReleasePCIMem( ag_card_info_t *pCardInfo ) {
U32 bar = 0;
int tmpRid = 0;
struct resource *tmpRsc = NULL;
device_t dev;
dev = pCardInfo->pPCIDev;
for (bar=0; bar < PCI_NUMBER_BARS; bar++) { // clean up PCI resource
tmpRid = pCardInfo->pciMemBaseRIDSpc[bar];
tmpRsc = pCardInfo->pciMemBaseRscSpc[bar];
if (tmpRsc != NULL) { // Release PCI resources
bus_release_resource( dev, SYS_RES_MEMORY, tmpRid, tmpRsc );
}
}
return;
}
/******************************************************************************
agtiapi_MemAlloc()
Purpose:
Handle various memory allocation requests.
Parameters:
ag_card_info_t *pCardInfo (IN) Pointer to card info structure
void **VirtAlloc (OUT) Allocated memory virtual address
dma_addr_t *pDmaAddr (OUT) Allocated dma memory physical address
void **VirtAddr (OUT) Aligned memory virtual address
U32 *pPhysAddrUp (OUT) Allocated memory physical upper 32 bits
U32 *pPhysAddrLow (OUT) Allocated memory physical lower 32 bits
U32 MemSize (IN) Allocated memory size
U32 Type (IN) Type of memory required
U32 Align (IN) Required memory alignment
Return:
AGTIAPI_SUCCESS - success
AGTIAPI_FAIL - fail
******************************************************************************/
STATIC agBOOLEAN agtiapi_MemAlloc( ag_card_info_t *thisCardInst,
void **VirtAlloc,
vm_paddr_t *pDmaAddr,
void **VirtAddr,
U32 *pPhysAddrUp,
U32 *pPhysAddrLow,
U32 MemSize,
U32 Type,
U32 Align )
{
U32_64 alignOffset = 0;
if( Align )
alignOffset = Align - 1;
// printf( "agtiapi_MemAlloc: debug find mem TYPE, %d vs. CACHE %d, DMA %d \n",
// ( Type & ( BIT(0) | BIT(1) ) ), TI_CACHED_MEM, TI_DMA_MEM );
if ((Type & (BIT(0) | BIT(1))) == TI_CACHED_MEM) {
*VirtAlloc = malloc( MemSize + Align, M_PMC_MMAL, M_ZERO | M_NOWAIT );
*VirtAddr = (void *)(((U32_64)*VirtAlloc + alignOffset) & ~alignOffset);
}
else {
struct agtiapi_softc *pmsc = thisCardInst->pCard; // get card reference
U32 residAlign = 0;
// find virt index value
*VirtAlloc = (void*)( (U64)pmsc->typh_mem + pmsc->typhIdx );
*VirtAddr = (void *)( ( (U32_64)*VirtAlloc + alignOffset) & ~alignOffset );
if( *VirtAddr != *VirtAlloc )
residAlign = (U64)*VirtAddr - (U64)*VirtAlloc; // find alignment needed
pmsc->typhIdx += residAlign + MemSize; // update index
residAlign = 0; // reset variable for reuse
// find phys index val
pDmaAddr = (vm_paddr_t*)( (U64)pmsc->typh_busaddr + pmsc->tyPhsIx );
vm_paddr_t *lPhysAligned =
(vm_paddr_t*)( ( (U64)pDmaAddr + alignOffset ) & ~alignOffset );
if( lPhysAligned != pDmaAddr )
residAlign = (U64)lPhysAligned - (U64)pDmaAddr; // find alignment needed
pmsc->tyPhsIx += residAlign + MemSize; // update index
*pPhysAddrUp = HIGH_32_BITS( (U64)lPhysAligned );
*pPhysAddrLow = LOW_32_BITS( (U64)lPhysAligned );
//printf( "agtiapi_MemAlloc: physIx 0x%x size 0x%x resid:0x%x "
// "addr:0x%p addrAligned:0x%p Align:0x%x\n",
// pmsc->tyPhsIx, MemSize, residAlign, pDmaAddr, lPhysAligned,
// Align );
}
if ( !*VirtAlloc ) {
AGTIAPI_PRINTK( "agtiapi_MemAlloc memory allocation ERROR x%x\n",
Type & (U32)(BIT(0) | BIT(1)));
return AGTIAPI_FAIL;
}
return AGTIAPI_SUCCESS;
}
/******************************************************************************
agtiapi_MemFree()
Purpose:
Free agtiapi_MemAlloc() allocated memory
Parameters:
ag_card_info_t *pCardInfo (IN) Pointer to card info structure
Return: none
******************************************************************************/
STATIC void agtiapi_MemFree( ag_card_info_t *pCardInfo )
{
U32 idx;
// release memory vs. alloc in agtiapi_MemAlloc; cached case
for( idx = 0; idx < pCardInfo->cacheIndex; idx++ ) {
if( pCardInfo->tiCachedMem[idx] ) {
free( pCardInfo->tiCachedMem[idx], M_PMC_MMAL );
AGTIAPI_PRINTK( "agtiapi_MemFree: TI_CACHED_MEM Mem[%d] %p\n",
idx, pCardInfo->tiCachedMem[idx] );
}
}
// release memory vs. alloc in agtiapi_typhAlloc; used in agtiapi_MemAlloc
struct agtiapi_softc *pmsc = pCardInfo->pCard; // get card reference
if( pmsc->typh_busaddr != 0 ) {
bus_dmamap_unload( pmsc->typh_dmat, pmsc->typh_mapp );
}
if( pmsc->typh_mem != NULL ) {
bus_dmamem_free( pmsc->typh_dmat, pmsc->typh_mem, pmsc->typh_mapp );
}
if( pmsc->typh_dmat != NULL ) {
bus_dma_tag_destroy( pmsc->typh_dmat );
}
//reference values:
// pCardInfo->dmaIndex
// pCardInfo->tiDmaMem[idx].dmaVirtAddr
// pCardInfo->tiDmaMem[idx].memSize
// pCardInfo->tiDmaMem[idx].type == TI_CACHED_DMA_MEM
// pCardInfo->tiDmaMem[idx].type == TI_DMA_MEM
/* This code is redundant. Commenting out for now to maintain a placekeeper.
Free actually takes place in agtiapi_ReleaseHBA as calls on osti_dmat. dm
// release possible lower layer dynamic memory
for( idx = 0; idx < AGTIAPI_DYNAMIC_MAX; idx++ ) {
if( pCardInfo->dynamicMem[idx].dmaVirtAddr != NULL ) {
printf( "agtiapi_MemFree: dynMem[%d] virtAddr"
" %p / %lx size: %d\n",
idx, pCardInfo->dynamicMem[idx].dmaVirtAddr,
(long unsigned int)pCardInfo->dynamicMem[idx].dmaPhysAddr,
pCardInfo->dynamicMem[idx].memSize );
if( pCardInfo->dynamicMem[idx].dmaPhysAddr )
some form of free call would go here (
pCardInfo->dynamicMem[idx].dmaVirtAddr,
pCardInfo->dynamicMem[idx].memSize, ... );
else
free case for cacheable memory would go here
}
}
*/
return;
}
/******************************************************************************
agtiapi_ProbeCard()
Purpose:
sets thisCardInst->cardIdIndex to structure variant consistent with card.
ag_card_type[idx].vendorId we already determined is PCI_VENDOR_ID_PMC_SIERRA.
Parameters:
device_t dev,
ag_card_info_t *thisCardInst,
int thisCard
Return:
0 - success
other values are not as good
Note:
This implementation is tailored to FreeBSD in alignment with the probe
functionality of the FreeBSD environment.
******************************************************************************/
STATIC int agtiapi_ProbeCard( device_t dev,
ag_card_info_t *thisCardInst,
int thisCard )
{
int idx;
u_int16_t agtiapi_vendor; // PCI vendor ID
u_int16_t agtiapi_dev; // PCI device ID
AGTIAPI_PRINTK("agtiapi_ProbeCard: start\n");
agtiapi_vendor = pci_get_vendor( dev ); // get PCI vendor ID
agtiapi_dev = pci_get_device( dev ); // get PCI device ID
for( idx = 0; idx < COUNT(ag_card_type); idx++ )
{
if ( ag_card_type[idx].deviceId == agtiapi_dev &&
ag_card_type[idx].vendorId == agtiapi_vendor)
{ // device ID match
memset( (void *)&agCardInfoList[ thisCard ], 0,
sizeof(ag_card_info_t) );
thisCardInst->cardIdIndex = idx;
thisCardInst->pPCIDev = dev;
thisCardInst->cardNameIndex = ag_card_type[idx].cardNameIndex;
thisCardInst->cardID =
pci_read_config( dev, ag_card_type[idx].membar, 4 ); // memAddr
AGTIAPI_PRINTK("agtiapi_ProbeCard: We've got PMC SAS, probe successful %p / %p\n",
thisCardInst->pPCIDev, thisCardInst );
device_set_desc( dev, ag_card_names[ag_card_type[idx].cardNameIndex] );
return 0;
}
}
return 1;
}