opnsense-src/sys/dev/pms/freebsd/driver/common/lxutil.c
Warner Losh 123049cf36 Don't forget to check the vendor when probing. Also, there's no need
to double check for if the card has probed before. In fact, there's no
reason to single check either. Simplify the code as a result.
$FreeBSD$ added to lxutil.c in a non-standard way to help keep the
diffs with upstream to a minimum.

Differential Revision: https://reviews.freebsd.org/D3263
2015-08-02 16:26:41 +00:00

786 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( agNULL, // 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;
}