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 *****************************************************************************/
agtiapi_DelayMSec(U32 MiliSeconds)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 ******************************************************************************/
agtiapi_typhAlloc(ag_card_info_t * thisCardInst)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( bus_get_dma_tag(pmsc->my_dev), // 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 ******************************************************************************/
agtiapi_InitResource(ag_card_info_t * thisCardInst)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 ******************************************************************************/
agtiapi_ScopeDMARes(ag_card_info_t * thisCardInst)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
agtiapi_ReleasePCIMem(ag_card_info_t * pCardInfo)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 ******************************************************************************/
agtiapi_MemAlloc(ag_card_info_t * thisCardInst,void ** VirtAlloc,vm_paddr_t * pDmaAddr,void ** VirtAddr,U32 * pPhysAddrUp,U32 * pPhysAddrLow,U32 MemSize,U32 Type,U32 Align)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 ******************************************************************************/
agtiapi_MemFree(ag_card_info_t * pCardInfo)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 ******************************************************************************/
agtiapi_ProbeCard(device_t dev,ag_card_info_t * thisCardInst,int thisCard)754 STATIC int agtiapi_ProbeCard( device_t dev,
755 ag_card_info_t *thisCardInst,
756 int thisCard )
757 {
758 int idx;
759 u_int16_t agtiapi_vendor; // PCI vendor ID
760 u_int16_t agtiapi_dev; // PCI device ID
761 AGTIAPI_PRINTK("agtiapi_ProbeCard: start\n");
762
763 agtiapi_vendor = pci_get_vendor( dev ); // get PCI vendor ID
764 agtiapi_dev = pci_get_device( dev ); // get PCI device ID
765 for( idx = 0; idx < COUNT(ag_card_type); idx++ )
766 {
767 if ( ag_card_type[idx].deviceId == agtiapi_dev &&
768 ag_card_type[idx].vendorId == agtiapi_vendor)
769 { // device ID match
770 memset( (void *)&agCardInfoList[ thisCard ], 0,
771 sizeof(ag_card_info_t) );
772 thisCardInst->cardIdIndex = idx;
773 thisCardInst->pPCIDev = dev;
774 thisCardInst->cardNameIndex = ag_card_type[idx].cardNameIndex;
775 thisCardInst->cardID =
776 pci_read_config( dev, ag_card_type[idx].membar, 4 ); // memAddr
777 AGTIAPI_PRINTK("agtiapi_ProbeCard: We've got PMC SAS, probe successful %p / %p\n",
778 thisCardInst->pPCIDev, thisCardInst );
779 device_set_desc( dev, ag_card_names[ag_card_type[idx].cardNameIndex] );
780 return 0;
781 }
782 }
783 return 1;
784 }
785
786