]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - sys/dev/pms/freebsd/driver/common/lxutil.c
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / sys / dev / pms / freebsd / driver / common / lxutil.c
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 /******************************************************************************
23 This program is part of PMC-Sierra initiator/target device driver. 
24 The functions here are commonly used by different type of drivers that support
25 PMC-Sierra storage network initiator hardware. 
26 ******************************************************************************/
27
28
29 MALLOC_DEFINE( M_PMC_MMAL, "agtiapi_MemAlloc malloc",
30                "allocated from agtiapi_MemAlloc as simple malloc case" );
31
32
33 /*****************************************************************************
34 agtiapi_DelayMSec()
35
36 Purpose:
37   Busy wait for number of mili-seconds
38 Parameters:
39   U32 MiliSeconds (IN)  Number of mili-seconds to delay
40 Return:
41 Note:
42 *****************************************************************************/
43 STATIC void agtiapi_DelayMSec( U32 MiliSeconds )
44 {
45   DELAY(MiliSeconds * 1000);  // DELAY takes in usecs
46 }
47
48 /******************************************************************************
49 agtiapi_typhAlloc()
50 Purpose:
51   Preallocation handling
52   Allocate DMA memory which will be divided among proper pointers in
53    agtiapi_MemAlloc() later
54 Parameters:
55   ag_card_info_t *thisCardInst (IN)
56 Return:
57   AGTIAPI_SUCCESS - success
58   AGTIAPI_FAIL    - fail
59 ******************************************************************************/
60 STATIC 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 /******************************************************************************
119 agtiapi_InitResource()
120 Purpose:
121   Mapping PCI memory space
122   Allocate and initialize per card based resource
123 Parameters: 
124   ag_card_info_t *pCardInfo (IN)  
125 Return:
126   AGTIAPI_SUCCESS - success
127   AGTIAPI_FAIL    - fail
128 Note:    
129 ******************************************************************************/
130 STATIC 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 /******************************************************************************
478 agtiapi_ScopeDMARes()
479 Purpose:
480   Determine the amount of DMA (non-cache) memory resources which will be
481   required for a card ( and necessarily allocated in agtiapi_InitResource() )
482 Parameters: 
483   ag_card_info_t *thisCardInst (IN)  
484 Return:
485   size of DMA memory which call to agtiapi_InitResource() will consume  
486 Note:
487   this funcion mirrors the flow of agtiapi_InitResource()
488   results are stored in agtiapi_softc fields
489 ******************************************************************************/
490 STATIC 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
586 STATIC 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 /******************************************************************************
605 agtiapi_MemAlloc()
606 Purpose:
607   Handle various memory allocation requests.
608 Parameters: 
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
618 Return:
619   AGTIAPI_SUCCESS - success
620   AGTIAPI_FAIL    - fail
621 ******************************************************************************/
622 STATIC 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 /******************************************************************************
677 agtiapi_MemFree()
678
679 Purpose:
680   Free agtiapi_MemAlloc() allocated memory
681 Parameters: 
682   ag_card_info_t *pCardInfo (IN)  Pointer to card info structure
683 Return: none
684 ******************************************************************************/
685 STATIC 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 /******************************************************************************
739 agtiapi_ProbeCard()
740 Purpose:
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.
743 Parameters:
744   device_t dev,
745   ag_card_info_t *thisCardInst,
746   int thisCard
747 Return:
748   0 - success
749   other values are not as good
750 Note:
751  This implementation is tailored to FreeBSD in alignment with the probe
752  functionality of the FreeBSD environment.
753 ******************************************************************************/
754 STATIC 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