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