lxutil.c revision 285809
1/******************************************************************************
2*Copyright (c) 2014 PMC-Sierra, Inc.  All rights reserved.
3*
4*Redistribution and use in source and binary forms, with or without modification, are permitted provided
5*that the following conditions are met:
6*1. Redistributions of source code must retain the above copyright notice, this list of conditions and the
7*following disclaimer.
8*2. Redistributions in binary form must reproduce the above copyright notice,
9*this list of conditions and the following disclaimer in the documentation and/or other materials provided
10*with the distribution.
11*
12*THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED
13*WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
14*FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
15*FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
16*NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
17*BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
18*LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
19*SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
20
21******************************************************************************/
22/******************************************************************************
23This program is part of PMC-Sierra initiator/target device driver.
24The functions here are commonly used by different type of drivers that support
25PMC-Sierra storage network initiator hardware.
26******************************************************************************/
27
28
29MALLOC_DEFINE( M_PMC_MMAL, "agtiapi_MemAlloc malloc",
30               "allocated from agtiapi_MemAlloc as simple malloc case" );
31
32
33/*****************************************************************************
34agtiapi_DelayMSec()
35
36Purpose:
37  Busy wait for number of mili-seconds
38Parameters:
39  U32 MiliSeconds (IN)  Number of mili-seconds to delay
40Return:
41Note:
42*****************************************************************************/
43STATIC void agtiapi_DelayMSec( U32 MiliSeconds )
44{
45  DELAY(MiliSeconds * 1000);  // DELAY takes in usecs
46}
47
48/******************************************************************************
49agtiapi_typhAlloc()
50Purpose:
51  Preallocation handling
52  Allocate DMA memory which will be divided among proper pointers in
53   agtiapi_MemAlloc() later
54Parameters:
55  ag_card_info_t *thisCardInst (IN)
56Return:
57  AGTIAPI_SUCCESS - success
58  AGTIAPI_FAIL    - fail
59******************************************************************************/
60STATIC agBOOLEAN agtiapi_typhAlloc( ag_card_info_t *thisCardInst )
61{
62  struct agtiapi_softc *pmsc = thisCardInst->pCard;
63  int wait = 0;
64
65  if( bus_dma_tag_create( agNULL,                      // parent
66                          32,                          // alignment
67                          0,                           // boundary
68                          BUS_SPACE_MAXADDR,           // lowaddr
69                          BUS_SPACE_MAXADDR,           // highaddr
70                          NULL,                        // filter
71                          NULL,                        // filterarg
72                          pmsc->typhn,                 // maxsize (size)
73                          1,                           // number of segments
74                          pmsc->typhn,                 // maxsegsize
75                          0,                           // flags
76                          NULL,                        // lockfunc
77                          NULL,                        // lockarg
78                          &pmsc->typh_dmat ) ) {
79    printf( "agtiapi_typhAlloc: Can't create no-cache mem tag\n" );
80    return AGTIAPI_FAIL;
81  }
82
83  if( bus_dmamem_alloc( pmsc->typh_dmat,
84                        &pmsc->typh_mem,
85                        BUS_DMA_WAITOK | BUS_DMA_ZERO | BUS_DMA_NOCACHE,
86                        &pmsc->typh_mapp ) ) {
87    printf( "agtiapi_typhAlloc: Cannot allocate cache mem %d\n",
88            pmsc->typhn );
89    return AGTIAPI_FAIL;
90  }
91
92  if ( bus_dmamap_load( pmsc->typh_dmat,
93                        pmsc->typh_mapp,
94                        pmsc->typh_mem,
95                        pmsc->typhn,
96                        agtiapi_MemoryCB, // try reuse of CB for same goal
97                        &pmsc->typh_busaddr,
98                        0 ) || !pmsc->typh_busaddr ) {
99    for( ; wait < 20; wait++ ) {
100      if( pmsc->typh_busaddr ) break;
101      DELAY( 50000 );
102    }
103
104    if( ! pmsc->typh_busaddr ) {
105      printf( "agtiapi_typhAlloc: cache mem won't load %d\n",
106              pmsc->typhn );
107      return AGTIAPI_FAIL;
108    }
109  }
110
111  pmsc->typhIdx = 0;
112  pmsc->tyPhsIx = 0;
113
114  return AGTIAPI_SUCCESS;
115}
116
117
118/******************************************************************************
119agtiapi_InitResource()
120Purpose:
121  Mapping PCI memory space
122  Allocate and initialize per card based resource
123Parameters:
124  ag_card_info_t *pCardInfo (IN)
125Return:
126  AGTIAPI_SUCCESS - success
127  AGTIAPI_FAIL    - fail
128Note:
129******************************************************************************/
130STATIC agBOOLEAN agtiapi_InitResource( ag_card_info_t *thisCardInst )
131{
132  struct agtiapi_softc *pmsc = thisCardInst->pCard;
133  device_t devx = thisCardInst->pPCIDev;
134
135  //AGTIAPI_PRINTK( "agtiapi_InitResource: begin; pointer values %p / %p \n",
136  //        devx, thisCardInst );
137  // no IO mapped card implementation, we'll implement memory mapping
138
139  if( agtiapi_typhAlloc( thisCardInst ) == AGTIAPI_FAIL ) {
140    printf( "agtiapi_InitResource: failed call to agtiapi_typhAlloc \n" );
141    return AGTIAPI_FAIL;
142  }
143
144  AGTIAPI_PRINTK( "agtiapi_InitResource: dma alloc MemSpan %p -- %p\n",
145                  (void*) pmsc->typh_busaddr,
146                  (void*) ( (U32_64)pmsc->typh_busaddr + pmsc->typhn ) );
147
148  //  logical BARs for SPC:
149  //    bar 0 and 1 - logical BAR0
150  //    bar 2 and 3 - logical BAR1
151  //    bar4 - logical BAR2
152  //    bar5 - logical BAR3
153  //    Skiping the assignments for bar 1 and bar 3 (making bar 0, 2 64-bit):
154  U32 bar;
155  U32 lBar = 0; // logicalBar
156  for (bar = 0; bar < PCI_NUMBER_BARS; bar++) {
157    if ((bar==1) || (bar==3))
158      continue;
159    thisCardInst->pciMemBaseRIDSpc[lBar] = PCIR_BAR(bar);
160    thisCardInst->pciMemBaseRscSpc[lBar] =
161      bus_alloc_resource_any( devx,
162                              SYS_RES_MEMORY,
163                              &(thisCardInst->pciMemBaseRIDSpc[lBar]),
164                              RF_ACTIVE );
165    AGTIAPI_PRINTK( "agtiapi_InitResource: bus_alloc_resource_any rtn %p \n",
166                    thisCardInst->pciMemBaseRscSpc[lBar] );
167    if ( thisCardInst->pciMemBaseRscSpc[lBar] != NULL ) {
168      thisCardInst->pciMemVirtAddrSpc[lBar] =
169        (caddr_t)rman_get_virtual(
170          thisCardInst->pciMemBaseRscSpc[lBar] );
171      thisCardInst->pciMemBaseSpc[lBar]  =
172        bus_get_resource_start( devx, SYS_RES_MEMORY,
173                                thisCardInst->pciMemBaseRIDSpc[lBar]);
174      thisCardInst->pciMemSizeSpc[lBar]  =
175        bus_get_resource_count( devx, SYS_RES_MEMORY,
176                                thisCardInst->pciMemBaseRIDSpc[lBar] );
177      AGTIAPI_PRINTK( "agtiapi_InitResource: PCI: bar %d, lBar %d "
178                      "VirtAddr=%lx, len=%d\n", bar, lBar,
179                      (long unsigned int)thisCardInst->pciMemVirtAddrSpc[lBar],
180                      thisCardInst->pciMemSizeSpc[lBar] );
181    }
182    else {
183      thisCardInst->pciMemVirtAddrSpc[lBar] = 0;
184      thisCardInst->pciMemBaseSpc[lBar]  = 0;
185      thisCardInst->pciMemSizeSpc[lBar]  = 0;
186    }
187    lBar++;
188  }
189  thisCardInst->pciMemVirtAddr = thisCardInst->pciMemVirtAddrSpc[0];
190  thisCardInst->pciMemSize = thisCardInst->pciMemSizeSpc[0];
191  thisCardInst->pciMemBase = thisCardInst->pciMemBaseSpc[0];
192
193  // Allocate all TI data structure required resources.
194  // tiLoLevelResource
195  U32 numVal;
196  ag_resource_info_t *pRscInfo;
197  pRscInfo = &thisCardInst->tiRscInfo;
198  pRscInfo->tiLoLevelResource.loLevelOption.pciFunctionNumber =
199    pci_get_function( devx );
200
201  struct timeval tv;
202  tv.tv_sec  = 1;
203  tv.tv_usec = 0;
204  int ticksPerSec;
205  ticksPerSec = tvtohz( &tv );
206  int uSecPerTick = 1000000/USEC_PER_TICK;
207
208  if (pRscInfo->tiLoLevelResource.loLevelMem.count != 0) {
209    //AGTIAPI_INIT("agtiapi_InitResource: loLevelMem count = %d\n",
210    // pRscInfo->tiLoLevelResource.loLevelMem.count);
211
212    // adjust tick value to meet Linux requirement
213    pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick = uSecPerTick;
214    AGTIAPI_PRINTK( "agtiapi_InitResource: "
215                    "pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick"
216                    " 0x%x\n",
217                    pRscInfo->tiLoLevelResource.loLevelOption.usecsPerTick );
218    for( numVal = 0; numVal < pRscInfo->tiLoLevelResource.loLevelMem.count;
219         numVal++ ) {
220      if( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength ==
221          0 ) {
222        AGTIAPI_PRINTK("agtiapi_InitResource: skip ZERO %d\n", numVal);
223        continue;
224      }
225
226      // check for 64 bit alignment
227      if ( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment <
228           AGTIAPI_64BIT_ALIGN ) {
229        AGTIAPI_PRINTK("agtiapi_InitResource: set ALIGN %d\n", numVal);
230        pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment =
231          AGTIAPI_64BIT_ALIGN;
232      }
233      if( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
234            & (BIT(0) | BIT(1))) == TI_DMA_MEM)  ||
235          ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
236            & (BIT(0) | BIT(1))) == TI_CACHED_DMA_MEM)) {
237        if ( thisCardInst->dmaIndex >=
238             sizeof(thisCardInst->tiDmaMem) /
239             sizeof(thisCardInst->tiDmaMem[0]) ) {
240          AGTIAPI_PRINTK( "Invalid dmaIndex %d ERROR\n",
241                          thisCardInst->dmaIndex );
242          return AGTIAPI_FAIL;
243        }
244        thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type =
245#ifdef CACHED_DMA
246          pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
247          & (BIT(0) | BIT(1));
248#else
249        TI_DMA_MEM;
250#endif
251        if( agtiapi_MemAlloc( thisCardInst,
252              &thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr,
253              &thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaPhysAddr,
254              &pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr,
255              &pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].
256              physAddrUpper,
257              &pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].
258              physAddrLower,
259              pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength,
260              thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type,
261              pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment)
262            != AGTIAPI_SUCCESS ) {
263          return AGTIAPI_FAIL;
264        }
265        thisCardInst->tiDmaMem[thisCardInst->dmaIndex].memSize =
266          pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength;
267        //AGTIAPI_INIT("agtiapi_InitResource: LoMem %d dmaIndex=%d  DMA virt"
268        //             " %p, phys 0x%x, length %d align %d\n",
269        //       numVal, pCardInfo->dmaIndex,
270        //     pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr,
271        //   pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].physAddrLower,
272        //     pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength,
273        //     pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment);
274        thisCardInst->dmaIndex++;
275      }
276      else if ( (pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type &
277                 (BIT(0) | BIT(1))) == TI_CACHED_MEM) {
278        if (thisCardInst->cacheIndex >=
279            sizeof(thisCardInst->tiCachedMem) /
280            sizeof(thisCardInst->tiCachedMem[0])) {
281          AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n",
282                  thisCardInst->cacheIndex );
283          return AGTIAPI_FAIL;
284        }
285        if ( agtiapi_MemAlloc( thisCardInst,
286               &thisCardInst->tiCachedMem[thisCardInst->cacheIndex],
287               (vm_paddr_t *)agNULL,
288               &pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr,
289               (U32 *)agNULL,
290               (U32 *)agNULL,
291               pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength,
292               TI_CACHED_MEM,
293               pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment)
294             != AGTIAPI_SUCCESS ) {
295          return AGTIAPI_FAIL;
296        }
297
298        //AGTIAPI_INIT("agtiapi_InitResource: LoMem %d cacheIndex=%d CACHED "
299        //      "vaddr %p / %p, length %d align %d\n",
300        //      numVal, pCardInfo->cacheIndex,
301        //      pCardInfo->tiCachedMem[pCardInfo->cacheIndex],
302        //      pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].virtPtr,
303        //      pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength,
304        //      pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment);
305
306        thisCardInst->cacheIndex++;
307      }
308      else if ( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
309                  & (BIT(0) | BIT(1))) == TI_DMA_MEM_CHIP)) {
310        // not expecting this case, print warning that should get attention
311        printf( "RED ALARM: we need a BAR for TI_DMA_MEM_CHIP, ignoring!" );
312      }
313      else {
314        printf( "agtiapi_InitResource: Unknown required memory type %d "
315                "ERROR!\n",
316                pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type);
317        return AGTIAPI_FAIL;
318      }
319    }
320  }
321  // end: TI data structure resources ...
322
323  // begin: tiInitiatorResource
324  if ( pmsc->flags & AGTIAPI_INITIATOR ) {
325    if ( pRscInfo->tiInitiatorResource.initiatorMem.count != 0 ) {
326      //AGTIAPI_INIT("agtiapi_InitResource: initiatorMem count = %d\n",
327      //         pRscInfo->tiInitiatorResource.initiatorMem.count);
328      numVal =
329        (U32)( pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick
330               / uSecPerTick );
331      if( pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick
332          % uSecPerTick > 0 )
333        pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick =
334          (numVal + 1) * uSecPerTick;
335      else
336        pRscInfo->tiInitiatorResource.initiatorOption.usecsPerTick =
337          numVal * uSecPerTick;
338      for ( numVal = 0;
339            numVal < pRscInfo->tiInitiatorResource.initiatorMem.count;
340            numVal++ ) {
341        // check for 64 bit alignment
342        if( pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
343            alignment < AGTIAPI_64BIT_ALIGN ) {
344          pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
345            alignment = AGTIAPI_64BIT_ALIGN;
346        }
347        if( thisCardInst->cacheIndex >=
348            sizeof( thisCardInst->tiCachedMem) /
349            sizeof( thisCardInst->tiCachedMem[0])) {
350          AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n",
351                  thisCardInst->cacheIndex );
352          return AGTIAPI_FAIL;
353        }
354        // initiator memory is cached, no check is needed
355        if( agtiapi_MemAlloc( thisCardInst,
356              (void *)&thisCardInst->tiCachedMem[thisCardInst->cacheIndex],
357              (vm_paddr_t *)agNULL,
358              &pRscInfo->tiInitiatorResource.initiatorMem.
359              tdCachedMem[numVal].virtPtr,
360              (U32 *)agNULL,
361              (U32 *)agNULL,
362              pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
363              totalLength,
364              TI_CACHED_MEM,
365              pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
366              alignment)
367            != AGTIAPI_SUCCESS) {
368          return AGTIAPI_FAIL;
369        }
370        // AGTIAPI_INIT("agtiapi_InitResource: IniMem %d cacheIndex=%d CACHED "
371        //      "vaddr %p / %p, length %d align 0x%x\n",
372        //      numVal,
373        //      pCardInfo->cacheIndex,
374        //      pCardInfo->tiCachedMem[pCardInfo->cacheIndex],
375        //      pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
376        //       virtPtr,
377        //pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
378        //       totalLength,
379        // pRscInfo->tiInitiatorResource.initiatorMem.tdCachedMem[numVal].
380        //       alignment);
381        thisCardInst->cacheIndex++;
382      }
383    }
384  }
385  // end: tiInitiatorResource
386
387  // begin: tiTdSharedMem
388  if (pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength != 0) {
389    // check for 64 bit alignment
390    if( pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment <
391	AGTIAPI_64BIT_ALIGN ) {
392      pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment = AGTIAPI_64BIT_ALIGN;
393    }
394    if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type & (BIT(0) | BIT(1)))
395	== TI_DMA_MEM )	{
396      if( thisCardInst->dmaIndex >=
397	  sizeof(thisCardInst->tiDmaMem) / sizeof(thisCardInst->tiDmaMem[0]) ) {
398	AGTIAPI_PRINTK( "Invalid dmaIndex %d ERROR\n", thisCardInst->dmaIndex);
399	return AGTIAPI_FAIL;
400      }
401      if( agtiapi_MemAlloc( thisCardInst, (void *)&thisCardInst->
402			    tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr,
403			    &thisCardInst->tiDmaMem[thisCardInst->dmaIndex].
404			    dmaPhysAddr,
405			    &pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
406			    &pRscInfo->tiSharedMem.tdSharedCachedMem1.
407			    physAddrUpper,
408			    &pRscInfo->tiSharedMem.tdSharedCachedMem1.
409			    physAddrLower,
410			    pRscInfo->tiSharedMem.tdSharedCachedMem1.
411			    totalLength,
412			    TI_DMA_MEM,
413			    pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment)
414	  != AGTIAPI_SUCCESS )
415	return AGTIAPI_FAIL;
416
417      thisCardInst->tiDmaMem[thisCardInst->dmaIndex].memSize =
418        pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength +
419        pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment;
420      //    printf( "agtiapi_InitResource: SharedMem DmaIndex=%d DMA "
421      //            "virt %p / %p, phys 0x%x, align %d\n",
422      //            thisCardInst->dmaIndex,
423      //            thisCardInst->tiDmaMem[thisCardInst->dmaIndex].dmaVirtAddr,
424      //            pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
425      //            pRscInfo->tiSharedMem.tdSharedCachedMem1.physAddrLower,
426      //            pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment);
427      thisCardInst->dmaIndex++;
428    }
429    else if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type &
430	      (BIT(0) | BIT(1)))
431	     == TI_CACHED_MEM )	{
432      if( thisCardInst->cacheIndex >=
433	  sizeof(thisCardInst->tiCachedMem) /
434	  sizeof(thisCardInst->tiCachedMem[0]) ) {
435	AGTIAPI_PRINTK( "Invalid cacheIndex %d ERROR\n", thisCardInst->cacheIndex);
436	return AGTIAPI_FAIL;
437      }
438      if( agtiapi_MemAlloc( thisCardInst, (void *)&thisCardInst->
439			    tiCachedMem[thisCardInst->cacheIndex],
440			    (vm_paddr_t *)agNULL,
441			    &pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
442			    (U32 *)agNULL,
443			    (U32 *)agNULL,
444			    pRscInfo->
445			    tiSharedMem.tdSharedCachedMem1.totalLength,
446			    TI_CACHED_MEM,
447			    pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment)
448	  != AGTIAPI_SUCCESS )
449	return AGTIAPI_FAIL;
450      //    printf( "agtiapi_InitResource: SharedMem cacheIndex=%d CACHED "
451      //                 "vaddr %p / %p, length %d align 0x%x\n",
452      //                 thisCardInst->cacheIndex,
453      //                 thisCardInst->tiCachedMem[thisCardInst->cacheIndex],
454      //                 pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
455      //                 pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength,
456      //                 pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment);
457      AGTIAPI_PRINTK( "agtiapi_InitResource: SharedMem cacheIndex=%d CACHED "
458                      "vaddr %p / %p, length %d align 0x%x\n",
459                      thisCardInst->cacheIndex,
460                      thisCardInst->tiCachedMem[thisCardInst->cacheIndex],
461                      pRscInfo->tiSharedMem.tdSharedCachedMem1.virtPtr,
462                      pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength,
463                      pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment );
464      thisCardInst->cacheIndex++;
465    }
466    else {
467      AGTIAPI_PRINTK( "agtiapi_InitResource: "
468                      "Unknown required memory type ERROR!\n" );
469      return AGTIAPI_FAIL;
470    }
471  }
472  // end: tiTdSharedMem
473  DELAY( 200000 ); // or use AGTIAPI_INIT_MDELAY(200);
474  return AGTIAPI_SUCCESS;
475} // agtiapi_InitResource() ends here
476
477/******************************************************************************
478agtiapi_ScopeDMARes()
479Purpose:
480  Determine the amount of DMA (non-cache) memory resources which will be
481  required for a card ( and necessarily allocated in agtiapi_InitResource() )
482Parameters:
483  ag_card_info_t *thisCardInst (IN)
484Return:
485  size of DMA memory which call to agtiapi_InitResource() will consume
486Note:
487  this funcion mirrors the flow of agtiapi_InitResource()
488  results are stored in agtiapi_softc fields
489******************************************************************************/
490STATIC int agtiapi_ScopeDMARes( ag_card_info_t *thisCardInst )
491{
492  struct agtiapi_softc *pmsc = thisCardInst->pCard;
493  U32 lAllMem = 0; // total memory count; typhn
494  U32 lTmpAlign, lTmpType, lTmpLen;
495
496  // tiLoLevelResource
497  U32 numVal;
498  ag_resource_info_t *pRscInfo;
499  pRscInfo = &thisCardInst->tiRscInfo;
500
501  if (pRscInfo->tiLoLevelResource.loLevelMem.count != 0) {
502    for( numVal = 0; numVal < pRscInfo->tiLoLevelResource.loLevelMem.count;
503         numVal++ ) {
504      if( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength ==
505          0 ) {
506        printf( "agtiapi_ScopeDMARes: skip ZERO %d\n", numVal );
507        continue;
508      }
509      // check for 64 bit alignment
510      lTmpAlign = pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment;
511      if( lTmpAlign < AGTIAPI_64BIT_ALIGN ) {
512        AGTIAPI_PRINTK("agtiapi_ScopeDMARes: set ALIGN %d\n", numVal);
513        //pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].alignment =
514        lTmpAlign = AGTIAPI_64BIT_ALIGN;
515      }
516      if( ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
517            & (BIT(0) | BIT(1))) == TI_DMA_MEM)  ||
518          ((pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
519            & (BIT(0) | BIT(1))) == TI_CACHED_DMA_MEM)) {
520        //thisCardInst->tiDmaMem[thisCardInst->dmaIndex].type =
521        lTmpType =
522#ifdef CACHED_DMA
523          pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type
524          & (BIT(0) | BIT(1));
525#else
526        TI_DMA_MEM;
527#endif
528        if( lTmpType == TI_DMA_MEM ) {
529          lTmpLen =
530            pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].totalLength;
531          lAllMem += lTmpLen + lTmpAlign;
532        }
533        //printf( "agtiapi_ScopeDMARes: call 1 0x%x\n", lAllMem );
534      }
535      else if ( ( pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type &
536                  (BIT(0) | BIT(1)) ) == TI_CACHED_MEM ) {
537        // these are not the droids we're looking for
538        if( thisCardInst->cacheIndex >=
539            sizeof(thisCardInst->tiCachedMem) /
540            sizeof(thisCardInst->tiCachedMem[0]) ) {
541          AGTIAPI_PRINTK( "agtiapi_ScopeDMARes: Invalid cacheIndex %d ERROR\n",
542                          thisCardInst->cacheIndex );
543          return lAllMem;
544        }
545      }
546      else {
547        printf( "agtiapi_ScopeDMARes: Unknown required memory type %d "
548                "ERROR!\n",
549                pRscInfo->tiLoLevelResource.loLevelMem.mem[numVal].type );
550        return lAllMem;
551      }
552    }
553  }
554  // end: TI data structure resources ...
555
556  // nothing for tiInitiatorResource
557
558  // begin: tiTdSharedMem
559  if (pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength != 0) {
560    // check for 64 bit alignment
561    lTmpAlign = pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment;
562    if( lTmpAlign < AGTIAPI_64BIT_ALIGN ) {
563      //pRscInfo->tiSharedMem.tdSharedCachedMem1.alignment=AGTIAPI_64BIT_ALIGN;
564       lTmpAlign = AGTIAPI_64BIT_ALIGN;
565    }
566    if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type & (BIT(0) | BIT(1)))
567        == TI_DMA_MEM )	{
568      lTmpLen = pRscInfo->tiSharedMem.tdSharedCachedMem1.totalLength;
569      lAllMem += lTmpLen + lTmpAlign;
570      // printf( "agtiapi_ScopeDMARes: call 4D 0x%x\n", lAllMem );
571    }
572    else if( (pRscInfo->tiSharedMem.tdSharedCachedMem1.type &
573              (BIT(0) | BIT(1)))
574             != TI_CACHED_MEM )	{
575      printf( "agtiapi_ScopeDMARes: Unknown required memory type ERROR!\n" );
576    }
577  }
578  // end: tiTdSharedMem
579
580  pmsc->typhn = lAllMem;
581  return lAllMem;
582
583} // agtiapi_ScopeDMARes() ends here
584
585
586STATIC void agtiapi_ReleasePCIMem( ag_card_info_t *pCardInfo ) {
587  U32 bar = 0;
588  int tmpRid = 0;
589  struct resource *tmpRsc = NULL;
590  device_t dev;
591  dev = pCardInfo->pPCIDev;
592
593  for (bar=0; bar  < PCI_NUMBER_BARS; bar++) {  // clean up PCI resource
594    tmpRid = pCardInfo->pciMemBaseRIDSpc[bar];
595    tmpRsc = pCardInfo->pciMemBaseRscSpc[bar];
596    if (tmpRsc != NULL) {   // Release PCI resources
597      bus_release_resource( dev, SYS_RES_MEMORY, tmpRid, tmpRsc );
598    }
599  }
600  return;
601}
602
603
604/******************************************************************************
605agtiapi_MemAlloc()
606Purpose:
607  Handle various memory allocation requests.
608Parameters:
609  ag_card_info_t *pCardInfo (IN)  Pointer to card info structure
610  void **VirtAlloc (OUT)          Allocated memory virtual address
611  dma_addr_t *pDmaAddr (OUT)      Allocated dma memory physical address
612  void **VirtAddr (OUT)           Aligned memory virtual address
613  U32 *pPhysAddrUp (OUT)          Allocated memory physical upper 32 bits
614  U32 *pPhysAddrLow (OUT)         Allocated memory physical lower 32 bits
615  U32 MemSize (IN)                Allocated memory size
616  U32 Type (IN)                   Type of memory required
617  U32 Align (IN)                  Required memory alignment
618Return:
619  AGTIAPI_SUCCESS - success
620  AGTIAPI_FAIL    - fail
621******************************************************************************/
622STATIC agBOOLEAN agtiapi_MemAlloc( ag_card_info_t *thisCardInst,
623                                   void       **VirtAlloc,
624                                   vm_paddr_t  *pDmaAddr,
625                                   void       **VirtAddr,
626                                   U32         *pPhysAddrUp,
627                                   U32         *pPhysAddrLow,
628                                   U32          MemSize,
629                                   U32          Type,
630                                   U32          Align )
631{
632  U32_64  alignOffset = 0;
633  if( Align )
634    alignOffset = Align - 1;
635
636// printf( "agtiapi_MemAlloc: debug find mem TYPE, %d vs. CACHE %d, DMA %d \n",
637//          ( Type & ( BIT(0) | BIT(1) ) ), TI_CACHED_MEM, TI_DMA_MEM );
638
639  if ((Type & (BIT(0) | BIT(1))) == TI_CACHED_MEM) {
640    *VirtAlloc = malloc( MemSize + Align, M_PMC_MMAL, M_ZERO | M_NOWAIT );
641    *VirtAddr  = (void *)(((U32_64)*VirtAlloc + alignOffset) & ~alignOffset);
642  }
643  else {
644    struct agtiapi_softc *pmsc = thisCardInst->pCard; // get card reference
645    U32 residAlign = 0;
646    // find virt index value
647    *VirtAlloc = (void*)( (U64)pmsc->typh_mem + pmsc->typhIdx );
648    *VirtAddr = (void *)( ( (U32_64)*VirtAlloc + alignOffset) & ~alignOffset );
649    if( *VirtAddr != *VirtAlloc )
650      residAlign = (U64)*VirtAddr - (U64)*VirtAlloc; // find alignment needed
651    pmsc->typhIdx += residAlign + MemSize; // update index
652    residAlign = 0; // reset variable for reuse
653    // find phys index val
654    pDmaAddr = (vm_paddr_t*)( (U64)pmsc->typh_busaddr + pmsc->tyPhsIx );
655    vm_paddr_t *lPhysAligned =
656      (vm_paddr_t*)( ( (U64)pDmaAddr + alignOffset ) & ~alignOffset );
657    if( lPhysAligned != pDmaAddr )
658      residAlign = (U64)lPhysAligned - (U64)pDmaAddr; // find alignment needed
659    pmsc->tyPhsIx += residAlign + MemSize;  // update index
660    *pPhysAddrUp  = HIGH_32_BITS( (U64)lPhysAligned );
661    *pPhysAddrLow = LOW_32_BITS( (U64)lPhysAligned );
662    //printf( "agtiapi_MemAlloc: physIx 0x%x size 0x%x resid:0x%x "
663    //        "addr:0x%p addrAligned:0x%p Align:0x%x\n",
664    //        pmsc->tyPhsIx, MemSize, residAlign, pDmaAddr, lPhysAligned,
665    //        Align );
666  }
667  if ( !*VirtAlloc ) {
668    AGTIAPI_PRINTK( "agtiapi_MemAlloc memory allocation ERROR x%x\n",
669                    Type & (U32)(BIT(0) | BIT(1)));
670    return AGTIAPI_FAIL;
671  }
672  return AGTIAPI_SUCCESS;
673}
674
675
676/******************************************************************************
677agtiapi_MemFree()
678
679Purpose:
680  Free agtiapi_MemAlloc() allocated memory
681Parameters:
682  ag_card_info_t *pCardInfo (IN)  Pointer to card info structure
683Return: none
684******************************************************************************/
685STATIC void agtiapi_MemFree( ag_card_info_t *pCardInfo )
686{
687  U32 idx;
688
689  // release memory vs. alloc in agtiapi_MemAlloc; cached case
690  for( idx = 0; idx < pCardInfo->cacheIndex; idx++ ) {
691    if( pCardInfo->tiCachedMem[idx] ) {
692      free( pCardInfo->tiCachedMem[idx], M_PMC_MMAL );
693      AGTIAPI_PRINTK( "agtiapi_MemFree: TI_CACHED_MEM Mem[%d] %p\n",
694              idx, pCardInfo->tiCachedMem[idx] );
695    }
696  }
697
698  // release memory vs. alloc in agtiapi_typhAlloc; used in agtiapi_MemAlloc
699  struct agtiapi_softc *pmsc = pCardInfo->pCard; // get card reference
700  if( pmsc->typh_busaddr != 0 ) {
701    bus_dmamap_unload( pmsc->typh_dmat, pmsc->typh_mapp );
702  }
703  if( pmsc->typh_mem != NULL )  {
704    bus_dmamem_free( pmsc->typh_dmat, pmsc->typh_mem, pmsc->typh_mapp );
705  }
706  if( pmsc->typh_dmat != NULL ) {
707    bus_dma_tag_destroy( pmsc->typh_dmat );
708  }
709//reference values:
710//  pCardInfo->dmaIndex
711//  pCardInfo->tiDmaMem[idx].dmaVirtAddr
712//  pCardInfo->tiDmaMem[idx].memSize
713//  pCardInfo->tiDmaMem[idx].type == TI_CACHED_DMA_MEM
714//  pCardInfo->tiDmaMem[idx].type == TI_DMA_MEM
715
716/* This code is redundant.  Commenting out for now to maintain a placekeeper.
717   Free actually takes place in agtiapi_ReleaseHBA as calls on osti_dmat. dm
718  // release possible lower layer dynamic memory
719  for( idx = 0; idx < AGTIAPI_DYNAMIC_MAX; idx++ ) {
720    if( pCardInfo->dynamicMem[idx].dmaVirtAddr != NULL ) {
721      printf( "agtiapi_MemFree: dynMem[%d] virtAddr"
722	            " %p / %lx size: %d\n",
723              idx, pCardInfo->dynamicMem[idx].dmaVirtAddr,
724              (long unsigned int)pCardInfo->dynamicMem[idx].dmaPhysAddr,
725              pCardInfo->dynamicMem[idx].memSize );
726      if( pCardInfo->dynamicMem[idx].dmaPhysAddr )
727	      some form of free call would go here  (
728                    pCardInfo->dynamicMem[idx].dmaVirtAddr,
729                    pCardInfo->dynamicMem[idx].memSize, ... );
730      else
731        free case for cacheable memory would go here
732    }
733  }
734*/
735  return;
736}
737
738/******************************************************************************
739agtiapi_ProbeCard()
740Purpose:
741  sets thisCardInst->cardIdIndex to structure variant consistent with card.
742  ag_card_type[idx].vendorId we already determined is PCI_VENDOR_ID_PMC_SIERRA.
743Parameters:
744  device_t dev,
745  ag_card_info_t *thisCardInst,
746  int thisCard
747Return:
748  0 - success
749  other values are not as good
750Note:
751 This implementation is tailored to FreeBSD in alignment with the probe
752 functionality of the FreeBSD environment.
753******************************************************************************/
754STATIC int agtiapi_ProbeCard( device_t dev,
755			      ag_card_info_t *thisCardInst,
756			      int thisCard )
757{
758  int idx;
759  static U32 cardMap[4] = { 0, 0, 0, 0 };
760  u_int16_t agtiapi_dev; // PCI device ID
761  AGTIAPI_PRINTK("agtiapi_ProbeCard: start\n");
762
763  if ( ! atomic_cmpset_32( &cardMap[thisCard], 0, 5 ) ) { // card already ran
764    AGTIAPI_PRINTK( "We'll only ID this card once -- %d\n", thisCard );
765    return 2; // error return value; card already ran this function
766  }
767  else {
768    agtiapi_dev = pci_get_device( dev ); // get PCI device ID
769    for( idx = 0; idx < COUNT(ag_card_type); idx++ )
770    {
771      if( ag_card_type[idx].deviceId == agtiapi_dev )
772      { // device ID match
773        memset( (void *)&agCardInfoList[ thisCard ], 0,
774                sizeof(ag_card_info_t) );
775        thisCardInst->cardIdIndex = idx;
776        thisCardInst->pPCIDev = dev;
777        thisCardInst->cardNameIndex = ag_card_type[idx].cardNameIndex;
778        thisCardInst->cardID =
779          pci_read_config( dev, ag_card_type[idx].membar, 4 ); // memAddr
780        AGTIAPI_PRINTK("agtiapi_ProbeCard: We've got PMC SAS, probe successful %p / %p\n",
781                thisCardInst->pPCIDev, thisCardInst );
782        device_printf( dev,
783                       "agtiapi PCI Probe Vendor ID : 0x%x Device ID : 0x%x\n",
784                       pci_get_vendor(dev), agtiapi_dev );
785        device_set_desc( dev, ag_card_names[ag_card_type[idx].cardNameIndex] );
786        return 0;
787      }
788    }
789  }
790  return 7;
791}
792
793