Root/target/linux/generic/files/crypto/ocf/kirkwood/mvHal/mv_hal/pci-if/pci_util/mvPciUtils.c

1/*******************************************************************************
2Copyright (C) Marvell International Ltd. and its affiliates
3
4This software file (the "File") is owned and distributed by Marvell
5International Ltd. and/or its affiliates ("Marvell") under the following
6alternative licensing terms. Once you have made an election to distribute the
7File under one of the following license alternatives, please (i) delete this
8introductory statement regarding license alternatives, (ii) delete the two
9license alternatives that you have not elected to use and (iii) preserve the
10Marvell copyright notice above.
11
12********************************************************************************
13Marvell Commercial License Option
14
15If you received this File from Marvell and you have entered into a commercial
16license agreement (a "Commercial License") with Marvell, the File is licensed
17to you under the terms of the applicable Commercial License.
18
19********************************************************************************
20Marvell GPL License Option
21
22If you received this File from Marvell, you may opt to use, redistribute and/or
23modify this File in accordance with the terms and conditions of the General
24Public License Version 2, June 1991 (the "GPL License"), a copy of which is
25available along with the File in the license.txt file or by writing to the Free
26Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
27on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
28
29THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
30WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
31DISCLAIMED. The GPL License provides additional details about this warranty
32disclaimer.
33********************************************************************************
34Marvell BSD License Option
35
36If you received this File from Marvell, you may opt to use, redistribute and/or
37modify this File under the following licensing terms.
38Redistribution and use in source and binary forms, with or without modification,
39are permitted provided that the following conditions are met:
40
41    * Redistributions of source code must retain the above copyright notice,
42        this list of conditions and the following disclaimer.
43
44    * Redistributions in binary form must reproduce the above copyright
45        notice, this list of conditions and the following disclaimer in the
46        documentation and/or other materials provided with the distribution.
47
48    * Neither the name of Marvell nor the names of its contributors may be
49        used to endorse or promote products derived from this software without
50        specific prior written permission.
51
52THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
53ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
54WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
55DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
56ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
57(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
58LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
59ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
60(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
61SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
62
63*******************************************************************************/
64
65/* includes */
66#include "mvPciUtils.h"
67
68#include "ctrlEnv/mvCtrlEnvLib.h"
69
70/* #define MV_DEBUG */
71/* defines */
72#ifdef MV_DEBUG
73    #define DB(x) x
74    #define mvOsPrintf printf
75#else
76    #define DB(x)
77#endif
78
79/*
80This module only support scanning of Header type 00h of pci devices
81There is no suppotr for Header type 01h of pci devices ( PCI bridges )
82*/
83
84
85static MV_STATUS pciDetectDevice(MV_U32 pciIf,
86                                    MV_U32 bus,
87                                    MV_U32 dev,
88                                    MV_U32 func,
89                                 MV_PCI_DEVICE *pPciAgent);
90
91static MV_U32 pciDetectDeviceBars(MV_U32 pciIf,
92                                    MV_U32 bus,
93                                    MV_U32 dev,
94                                    MV_U32 func,
95                                    MV_PCI_DEVICE *pPciAgent);
96
97
98
99
100
101
102/*******************************************************************************
103* mvPciScan - Scan a PCI interface bus
104*
105* DESCRIPTION:
106* Performs a full scan on a PCI interface and returns all possible details
107* on the agents found on the bus.
108*
109* INPUT:
110* pciIf - PCI Interface
111* pPciAgents - Pointer to an Array of the pci agents to be detected
112* pPciAgentsNum - pPciAgents array maximum number of elements
113*
114* OUTPUT:
115* pPciAgents - Array of the pci agents detected on the bus
116* pPciAgentsNum - Number of pci agents detected on the bus
117*
118* RETURN:
119* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
120*
121*******************************************************************************/
122
123MV_STATUS mvPciScan(MV_U32 pciIf,
124                    MV_PCI_DEVICE *pPciAgents,
125                    MV_U32 *pPciAgentsNum)
126{
127
128    MV_U32 devIndex,funcIndex=0,busIndex=0,detectedDevNum=0;
129    MV_U32 localBus=mvPciIfLocalBusNumGet(pciIf);
130    MV_PCI_DEVICE *pPciDevice;
131    MV_PCI_DEVICE *pMainDevice;
132
133    DB(mvOsPrintf("mvPciScan: PCI interface num %d\n", pciIf));
134    /* Parameter checking */
135    if (pciIf >= mvCtrlPexMaxIfGet())
136    {
137        DB(mvOsPrintf("mvPciScan: ERR. Invalid PCI interface num %d\n", pciIf));
138        return MV_BAD_PARAM;
139    }
140    if (NULL == pPciAgents)
141    {
142        DB(mvOsPrintf("mvPciScan: ERR. pPciAgents=NULL \n"));
143        return MV_BAD_PARAM;
144    }
145    if (NULL == pPciAgentsNum)
146    {
147        DB(mvOsPrintf("mvPciScan: ERR. pPciAgentsNum=NULL \n"));
148        return MV_BAD_PARAM;
149    }
150
151
152    DB(mvOsPrintf("mvPciScan: PCI interface num %d mvPciMasterEnable\n", pciIf));
153    /* Master enable the MV PCI master */
154    if (MV_OK != mvPciIfMasterEnable(pciIf,MV_TRUE))
155    {
156        DB(mvOsPrintf("mvPciScan: ERR. mvPciMasterEnable failed \n"));
157        return MV_ERROR;
158
159    }
160
161    DB(mvOsPrintf("mvPciScan: PCI interface num scan%d\n", pciIf));
162
163    /* go through all busses */
164    for (busIndex=localBus ; busIndex < MAX_PCI_BUSSES ; busIndex++)
165    {
166        /* go through all possible devices on the local bus */
167        for (devIndex=0 ; devIndex < MAX_PCI_DEVICES ; devIndex++)
168        {
169            /* always start with function equal to zero */
170            funcIndex=0;
171
172            pPciDevice=&pPciAgents[detectedDevNum];
173            DB(mvOsPrintf("mvPciScan: PCI interface num scan%d:%d\n", busIndex, devIndex));
174
175            if (MV_ERROR == pciDetectDevice(pciIf,
176                                           busIndex,
177                                           devIndex,
178                                           funcIndex,
179                                           pPciDevice))
180            {
181                /* no device detected , try the next address */
182                continue;
183            }
184
185            /* We are here ! means we have detected a device*/
186            /* always we start with only one function per device */
187            pMainDevice = pPciDevice;
188            pPciDevice->funtionsNum = 1;
189
190
191            /* move on */
192            detectedDevNum++;
193
194
195            /* check if we have no more room for a new device */
196            if (detectedDevNum == *pPciAgentsNum)
197            {
198                DB(mvOsPrintf("mvPciScan: ERR. array passed too small \n"));
199                return MV_ERROR;
200            }
201
202            /* check the detected device if it is a multi functional device then
203            scan all device functions*/
204            if (pPciDevice->isMultiFunction == MV_TRUE)
205            {
206                /* start with function number 1 because we have already detected
207                function 0 */
208                for (funcIndex=1; funcIndex<MAX_PCI_FUNCS ; funcIndex++)
209                {
210                    pPciDevice=&pPciAgents[detectedDevNum];
211
212                    if (MV_ERROR == pciDetectDevice(pciIf,
213                                                   busIndex,
214                                                   devIndex,
215                                                   funcIndex,
216                                                   pPciDevice))
217                    {
218                        /* no device detected means no more functions !*/
219                        continue;
220                    }
221                    /* We are here ! means we have detected a device */
222
223                    /* move on */
224                    pMainDevice->funtionsNum++;
225                    detectedDevNum++;
226
227                    /* check if we have no more room for a new device */
228                    if (detectedDevNum == *pPciAgentsNum)
229                    {
230                        DB(mvOsPrintf("mvPciScan: ERR. Array too small\n"));
231                        return MV_ERROR;
232                    }
233
234
235                }
236            }
237
238        }
239
240    }
241
242    /* return the number of devices actually detected on the bus ! */
243    *pPciAgentsNum = detectedDevNum;
244
245    return MV_OK;
246
247}
248
249
250/*******************************************************************************
251* pciDetectDevice - Detect a pci device parameters
252*
253* DESCRIPTION:
254* This function detect if a pci agent exist on certain address !
255* and if exists then it fills all possible information on the
256* agent
257*
258* INPUT:
259* pciIf - PCI Interface
260* bus - Bus number
261* dev - Device number
262* func - Function number
263*
264*
265*
266* OUTPUT:
267* pPciAgent - pointer to the pci agent filled with its information
268*
269* RETURN:
270* MV_ERROR if no device , MV_OK otherwise
271*
272*******************************************************************************/
273
274static MV_STATUS pciDetectDevice(MV_U32 pciIf,
275                                    MV_U32 bus,
276                                    MV_U32 dev,
277                                    MV_U32 func,
278                                 MV_PCI_DEVICE *pPciAgent)
279{
280    MV_U32 pciData;
281
282    /* no Parameters checking ! because it is static function and it is assumed
283    that all parameters were checked in the calling function */
284
285
286    /* Try read the PCI Vendor ID and Device ID */
287
288    /* We will scan only ourselves and the PCI slots that exist on the
289        board, because we may have a case that we have one slot that has
290        a Cardbus connector, and because CardBus answers all IDsels we want
291        to scan only this slot and ourseleves.
292
293    */
294    #if defined(MV_INCLUDE_PCI)
295    if ((PCI_IF_TYPE_CONVEN_PCIX == mvPciIfTypeGet(pciIf)) &&
296                    (DB_88F5181_DDR1_PRPMC != mvBoardIdGet()) &&
297                    (DB_88F5181_DDR1_PEXPCI != mvBoardIdGet()) &&
298                    (DB_88F5181_DDR1_MNG != mvBoardIdGet()))
299        {
300
301            if (mvBoardIsOurPciSlot(bus, dev) == MV_FALSE)
302            {
303                return MV_ERROR;
304            }
305    }
306    #endif /* defined(MV_INCLUDE_PCI) */
307
308    pciData = mvPciIfConfigRead(pciIf, bus,dev,func, PCI_DEVICE_AND_VENDOR_ID);
309
310    if (PCI_ERROR_CODE == pciData)
311    {
312        /* no device exist */
313        return MV_ERROR;
314    }
315
316    /* we are here ! means a device is detected */
317
318    /* fill basic information */
319    pPciAgent->busNumber=bus;
320    pPciAgent->deviceNum=dev;
321    pPciAgent->function=func;
322
323    /* Fill the PCI Vendor ID and Device ID */
324
325    pPciAgent->venID = (pciData & PDVIR_VEN_ID_MASK) >> PDVIR_VEN_ID_OFFS;
326    pPciAgent->deviceID = (pciData & PDVIR_DEV_ID_MASK) >> PDVIR_DEV_ID_OFFS;
327
328    /* Read Status and command */
329    pciData = mvPciIfConfigRead(pciIf,
330                              bus,dev,func,
331                              PCI_STATUS_AND_COMMAND);
332
333
334    /* Fill related Status and Command information*/
335
336    if (pciData & PSCR_TAR_FAST_BB)
337    {
338        pPciAgent->isFastB2BCapable = MV_TRUE;
339    }
340    else
341    {
342        pPciAgent->isFastB2BCapable = MV_FALSE;
343    }
344
345    if (pciData & PSCR_CAP_LIST)
346    {
347        pPciAgent->isCapListSupport=MV_TRUE;
348    }
349    else
350    {
351        pPciAgent->isCapListSupport=MV_FALSE;
352    }
353
354    if (pciData & PSCR_66MHZ_EN)
355    {
356        pPciAgent->is66MHZCapable=MV_TRUE;
357    }
358    else
359    {
360        pPciAgent->is66MHZCapable=MV_FALSE;
361    }
362
363    /* Read Class Code and Revision */
364    pciData = mvPciIfConfigRead(pciIf,
365                              bus,dev,func,
366                              PCI_CLASS_CODE_AND_REVISION_ID);
367
368
369    pPciAgent->baseClassCode =
370        (pciData & PCCRIR_BASE_CLASS_MASK) >> PCCRIR_BASE_CLASS_OFFS;
371
372    pPciAgent->subClassCode =
373        (pciData & PCCRIR_SUB_CLASS_MASK) >> PCCRIR_SUB_CLASS_OFFS;
374
375    pPciAgent->progIf =
376        (pciData & PCCRIR_PROGIF_MASK) >> PCCRIR_PROGIF_OFFS;
377
378    pPciAgent->revisionID =
379        (pciData & PCCRIR_REVID_MASK) >> PCCRIR_REVID_OFFS;
380
381    /* Read PCI_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE */
382    pciData = mvPciIfConfigRead(pciIf,
383                              bus,dev,func,
384                              PCI_BIST_HDR_TYPE_LAT_TMR_CACHE_LINE);
385
386
387
388    pPciAgent->pciCacheLine=
389        (pciData & PBHTLTCLR_CACHELINE_MASK ) >> PBHTLTCLR_CACHELINE_OFFS;
390    pPciAgent->pciLatencyTimer=
391        (pciData & PBHTLTCLR_LATTIMER_MASK) >> PBHTLTCLR_LATTIMER_OFFS;
392
393    switch (pciData & PBHTLTCLR_HEADER_MASK)
394    {
395    case PBHTLTCLR_HEADER_STANDARD:
396
397        pPciAgent->pciHeader=MV_PCI_STANDARD;
398        break;
399    case PBHTLTCLR_HEADER_PCI2PCI_BRIDGE:
400
401        pPciAgent->pciHeader=MV_PCI_PCI2PCI_BRIDGE;
402        break;
403
404    }
405
406    if (pciData & PBHTLTCLR_MULTI_FUNC)
407    {
408        pPciAgent->isMultiFunction=MV_TRUE;
409    }
410    else
411    {
412        pPciAgent->isMultiFunction=MV_FALSE;
413    }
414
415    if (pciData & PBHTLTCLR_BISTCAP)
416    {
417        pPciAgent->isBISTCapable=MV_TRUE;
418    }
419    else
420    {
421        pPciAgent->isBISTCapable=MV_FALSE;
422    }
423
424
425    /* read this device pci bars */
426
427    pciDetectDeviceBars(pciIf,
428                      bus,dev,func,
429                      pPciAgent);
430
431
432    /* check if we are bridge*/
433    if ((pPciAgent->baseClassCode == PCI_BRIDGE_CLASS)&&
434        (pPciAgent->subClassCode == P2P_BRIDGE_SUB_CLASS_CODE))
435    {
436
437        /* Read P2P_BUSSES_NUM */
438        pciData = mvPciIfConfigRead(pciIf,
439                                  bus,dev,func,
440                                  P2P_BUSSES_NUM);
441
442        pPciAgent->p2pPrimBusNum =
443            (pciData & PBM_PRIME_BUS_NUM_MASK) >> PBM_PRIME_BUS_NUM_OFFS;
444
445        pPciAgent->p2pSecBusNum =
446            (pciData & PBM_SEC_BUS_NUM_MASK) >> PBM_SEC_BUS_NUM_OFFS;
447
448        pPciAgent->p2pSubBusNum =
449            (pciData & PBM_SUB_BUS_NUM_MASK) >> PBM_SUB_BUS_NUM_OFFS;
450
451        pPciAgent->p2pSecLatencyTimer =
452            (pciData & PBM_SEC_LAT_TMR_MASK) >> PBM_SEC_LAT_TMR_OFFS;
453
454        /* Read P2P_IO_BASE_LIMIT_SEC_STATUS */
455        pciData = mvPciIfConfigRead(pciIf,
456                                  bus,dev,func,
457                                  P2P_IO_BASE_LIMIT_SEC_STATUS);
458
459        pPciAgent->p2pSecStatus =
460            (pciData & PIBLSS_SEC_STATUS_MASK) >> PIBLSS_SEC_STATUS_OFFS;
461
462
463        pPciAgent->p2pIObase =
464            (pciData & PIBLSS_IO_BASE_MASK) << PIBLSS_IO_LIMIT_OFFS;
465
466        /* clear low address (should be zero)*/
467        pPciAgent->p2pIObase &= PIBLSS_HIGH_ADDR_MASK;
468
469        pPciAgent->p2pIOLimit =
470            (pciData & PIBLSS_IO_LIMIT_MASK);
471
472        /* fill low address with 0xfff */
473        pPciAgent->p2pIOLimit |= PIBLSS_LOW_ADDR_MASK;
474
475
476        switch ((pciData & PIBLSS_ADD_CAP_MASK) >> PIBLSS_ADD_CAP_OFFS)
477        {
478        case PIBLSS_ADD_CAP_16BIT:
479
480            pPciAgent->bIO32 = MV_FALSE;
481
482            break;
483        case PIBLSS_ADD_CAP_32BIT:
484
485            pPciAgent->bIO32 = MV_TRUE;
486
487            /* Read P2P_IO_BASE_LIMIT_UPPER_16 */
488            pciData = mvPciIfConfigRead(pciIf,
489                                      bus,dev,func,
490                                      P2P_IO_BASE_LIMIT_UPPER_16);
491
492            pPciAgent->p2pIObase |=
493                (pciData & PRBU_IO_UPP_BASE_MASK) << PRBU_IO_UPP_LIMIT_OFFS;
494
495
496            pPciAgent->p2pIOLimit |=
497                (pciData & PRBU_IO_UPP_LIMIT_MASK);
498
499            break;
500
501        }
502
503
504        /* Read P2P_MEM_BASE_LIMIT */
505        pciData = mvPciIfConfigRead(pciIf,
506                                  bus,dev,func,
507                                  P2P_MEM_BASE_LIMIT);
508
509        pPciAgent->p2pMemBase =
510            (pciData & PMBL_MEM_BASE_MASK) << PMBL_MEM_LIMIT_OFFS;
511
512        /* clear low address */
513        pPciAgent->p2pMemBase &= PMBL_HIGH_ADDR_MASK;
514
515        pPciAgent->p2pMemLimit =
516            (pciData & PMBL_MEM_LIMIT_MASK);
517
518        /* add 0xfffff */
519        pPciAgent->p2pMemLimit |= PMBL_LOW_ADDR_MASK;
520
521
522        /* Read P2P_PREF_MEM_BASE_LIMIT */
523        pciData = mvPciIfConfigRead(pciIf,
524                                  bus,dev,func,
525                                  P2P_PREF_MEM_BASE_LIMIT);
526
527
528        pPciAgent->p2pPrefMemBase =
529            (pciData & PRMBL_PREF_MEM_BASE_MASK) << PRMBL_PREF_MEM_LIMIT_OFFS;
530
531        /* get high address only */
532        pPciAgent->p2pPrefMemBase &= PRMBL_HIGH_ADDR_MASK;
533
534
535
536        pPciAgent->p2pPrefMemLimit =
537            (pciData & PRMBL_PREF_MEM_LIMIT_MASK);
538
539        /* add 0xfffff */
540        pPciAgent->p2pPrefMemLimit |= PRMBL_LOW_ADDR_MASK;
541
542        switch (pciData & PRMBL_ADD_CAP_MASK)
543        {
544        case PRMBL_ADD_CAP_32BIT:
545
546            pPciAgent->bPrefMem64 = MV_FALSE;
547
548            /* Read P2P_PREF_BASE_UPPER_32 */
549            pPciAgent->p2pPrefBaseUpper32Bits = 0;
550
551            /* Read P2P_PREF_LIMIT_UPPER_32 */
552            pPciAgent->p2pPrefLimitUpper32Bits = 0;
553
554            break;
555        case PRMBL_ADD_CAP_64BIT:
556
557            pPciAgent->bPrefMem64 = MV_TRUE;
558
559            /* Read P2P_PREF_BASE_UPPER_32 */
560            pPciAgent->p2pPrefBaseUpper32Bits = mvPciIfConfigRead(pciIf,
561                                      bus,dev,func,
562                                      P2P_PREF_BASE_UPPER_32);
563
564            /* Read P2P_PREF_LIMIT_UPPER_32 */
565            pPciAgent->p2pPrefLimitUpper32Bits = mvPciIfConfigRead(pciIf,
566                                      bus,dev,func,
567                                      P2P_PREF_LIMIT_UPPER_32);
568
569            break;
570
571        }
572
573    }
574    else /* no bridge */
575    {
576        /* Read PCI_SUBSYS_ID_AND_SUBSYS_VENDOR_ID */
577        pciData = mvPciIfConfigRead(pciIf,
578                                  bus,dev,func,
579                                  PCI_SUBSYS_ID_AND_SUBSYS_VENDOR_ID);
580
581
582        pPciAgent->subSysVenID =
583            (pciData & PSISVIR_VENID_MASK) >> PSISVIR_VENID_OFFS;
584        pPciAgent->subSysID =
585            (pciData & PSISVIR_DEVID_MASK) >> PSISVIR_DEVID_OFFS;
586
587
588        /* Read PCI_EXPANSION_ROM_BASE_ADDR_REG */
589        pciData = mvPciIfConfigRead(pciIf,
590                                  bus,dev,func,
591                                  PCI_EXPANSION_ROM_BASE_ADDR_REG);
592
593
594        if (pciData & PERBAR_EXPROMEN)
595        {
596            pPciAgent->isExpRom = MV_TRUE;
597        }
598        else
599        {
600            pPciAgent->isExpRom = MV_FALSE;
601        }
602
603        pPciAgent->expRomAddr =
604            (pciData & PERBAR_BASE_MASK) >> PERBAR_BASE_OFFS;
605
606    }
607
608
609    if (MV_TRUE == pPciAgent->isCapListSupport)
610    {
611        /* Read PCI_CAPABILTY_LIST_POINTER */
612        pciData = mvPciIfConfigRead(pciIf,
613                                  bus,dev,func,
614                                  PCI_CAPABILTY_LIST_POINTER);
615
616        pPciAgent->capListPointer =
617            (pciData & PCLPR_CAPPTR_MASK) >> PCLPR_CAPPTR_OFFS;
618
619    }
620
621    /* Read PCI_INTERRUPT_PIN_AND_LINE */
622    pciData = mvPciIfConfigRead(pciIf,
623                              bus,dev,func,
624                              PCI_INTERRUPT_PIN_AND_LINE);
625
626
627    pPciAgent->irqLine=
628        (pciData & PIPLR_INTLINE_MASK) >> PIPLR_INTLINE_OFFS;
629
630    pPciAgent->intPin=
631        (MV_PCI_INT_PIN)(pciData & PIPLR_INTPIN_MASK) >> PIPLR_INTPIN_OFFS;
632
633    pPciAgent->minGrant=
634        (pciData & PIPLR_MINGRANT_MASK) >> PIPLR_MINGRANT_OFFS;
635    pPciAgent->maxLatency=
636        (pciData & PIPLR_MAXLATEN_MASK) >> PIPLR_MAXLATEN_OFFS;
637
638    mvPciClassNameGet(pPciAgent->baseClassCode,
639                      (MV_8 *)pPciAgent->type);
640
641    return MV_OK;
642
643
644}
645
646/*******************************************************************************
647* pciDetectDeviceBars - Detect a pci device bars
648*
649* DESCRIPTION:
650* This function detects all pci agent bars
651*
652* INPUT:
653* pciIf - PCI Interface
654* bus - Bus number
655* dev - Device number
656* func - Function number
657*
658*
659*
660* OUTPUT:
661* pPciAgent - pointer to the pci agent filled with its information
662*
663* RETURN:
664* detected bars number
665*
666*******************************************************************************/
667static MV_U32 pciDetectDeviceBars(MV_U32 pciIf,
668                                    MV_U32 bus,
669                                    MV_U32 dev,
670                                    MV_U32 func,
671                                    MV_PCI_DEVICE *pPciAgent)
672{
673    MV_U32 pciData,barIndex,detectedBar=0;
674    MV_U32 tmpBaseHigh=0,tmpBaseLow=0;
675    MV_U32 pciMaxBars=0;
676
677    pPciAgent->barsNum=0;
678
679    /* check if we are bridge*/
680    if ((pPciAgent->baseClassCode == PCI_BRIDGE_CLASS)&&
681        (pPciAgent->subClassCode == P2P_BRIDGE_SUB_CLASS_CODE))
682    {
683        pciMaxBars = 2;
684    }
685    else /* no bridge */
686    {
687        pciMaxBars = 6;
688    }
689
690    /* read this device pci bars */
691    for (barIndex = 0 ; barIndex < pciMaxBars ; barIndex++ )
692    {
693        /* Read PCI_MEMORY_BAR_BASE_ADDR */
694        tmpBaseLow = pciData = mvPciIfConfigRead(pciIf,
695                                       bus,dev,func,
696                                       PCI_MEMORY_BAR_BASE_ADDR(barIndex));
697
698        pPciAgent->pciBar[detectedBar].barOffset =
699            PCI_MEMORY_BAR_BASE_ADDR(barIndex);
700
701        /* check if the bar is 32bit or 64bit bar */
702        switch (pciData & PBBLR_TYPE_MASK)
703        {
704        case PBBLR_TYPE_32BIT_ADDR:
705            pPciAgent->pciBar[detectedBar].barType = PCI_32BIT_BAR;
706            break;
707        case PBBLR_TYPE_64BIT_ADDR:
708            pPciAgent->pciBar[detectedBar].barType = PCI_64BIT_BAR;
709            break;
710
711        }
712
713        /* check if it is memory or IO bar */
714        if (pciData & PBBLR_IOSPACE)
715        {
716            pPciAgent->pciBar[detectedBar].barMapping=PCI_IO_BAR;
717        }
718        else
719        {
720            pPciAgent->pciBar[detectedBar].barMapping=PCI_MEMORY_BAR;
721        }
722
723        /* if it is memory bar then check if it is prefetchable */
724        if (PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping)
725        {
726            if (pciData & PBBLR_PREFETCH_EN)
727            {
728                pPciAgent->pciBar[detectedBar].isPrefetchable = MV_TRUE;
729            }
730            else
731            {
732                pPciAgent->pciBar[detectedBar].isPrefetchable = MV_FALSE;
733            }
734
735            pPciAgent->pciBar[detectedBar].barBaseLow =
736                pciData & PBBLR_MEM_BASE_MASK;
737
738
739        }
740        else /* IO Bar */
741        {
742            pPciAgent->pciBar[detectedBar].barBaseLow =
743                pciData & PBBLR_IO_BASE_MASK;
744
745        }
746
747        pPciAgent->pciBar[detectedBar].barBaseHigh=0;
748
749        if (PCI_64BIT_BAR == pPciAgent->pciBar[detectedBar].barType)
750        {
751            barIndex++;
752
753            tmpBaseHigh = pPciAgent->pciBar[detectedBar].barBaseHigh =
754                mvPciIfConfigRead(pciIf,
755                                bus,dev,func,
756                                PCI_MEMORY_BAR_BASE_ADDR(barIndex));
757
758
759        }
760
761        /* calculating full base address (64bit) */
762        pPciAgent->pciBar[detectedBar].barBaseAddr =
763            (MV_U64)pPciAgent->pciBar[detectedBar].barBaseHigh;
764
765        pPciAgent->pciBar[detectedBar].barBaseAddr <<= 32;
766
767        pPciAgent->pciBar[detectedBar].barBaseAddr |=
768            (MV_U64)pPciAgent->pciBar[detectedBar].barBaseLow;
769
770
771
772        /* get the sizes of the the bar */
773
774        pPciAgent->pciBar[detectedBar].barSizeHigh=0;
775
776        if ((PCI_64BIT_BAR == pPciAgent->pciBar[detectedBar].barType) &&
777            (PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping))
778
779        {
780            /* write oxffffffff to the bar to get the size */
781            /* start with sizelow ( original value was saved in tmpBaseLow ) */
782            mvPciIfConfigWrite(pciIf,
783                            bus,dev,func,
784                            PCI_MEMORY_BAR_BASE_ADDR(barIndex-1),
785                            0xffffffff);
786
787            /* read size */
788            pPciAgent->pciBar[detectedBar].barSizeLow =
789                mvPciIfConfigRead(pciIf,
790                                bus,dev,func,
791                                PCI_MEMORY_BAR_BASE_ADDR(barIndex-1));
792
793
794
795            /* restore original value */
796            mvPciIfConfigWrite(pciIf,
797                            bus,dev,func,
798                            PCI_MEMORY_BAR_BASE_ADDR(barIndex-1),
799                            tmpBaseLow);
800
801
802            /* now do the same for BaseHigh */
803
804            /* write oxffffffff to the bar to get the size */
805            mvPciIfConfigWrite(pciIf,
806                            bus,dev,func,
807                            PCI_MEMORY_BAR_BASE_ADDR(barIndex),
808                            0xffffffff);
809
810            /* read size */
811            pPciAgent->pciBar[detectedBar].barSizeHigh =
812                mvPciIfConfigRead(pciIf,
813                                bus,dev,func,
814                                PCI_MEMORY_BAR_BASE_ADDR(barIndex));
815
816            /* restore original value */
817            mvPciIfConfigWrite(pciIf,
818                            bus,dev,func,
819                            PCI_MEMORY_BAR_BASE_ADDR(barIndex),
820                            tmpBaseHigh);
821
822            if ((0 == pPciAgent->pciBar[detectedBar].barSizeLow)&&
823                (0 == pPciAgent->pciBar[detectedBar].barSizeHigh))
824            {
825                /* this bar is not applicable for this device,
826                   ignore all previous settings and check the next bar*/
827
828                /* we though this was a 64bit bar , and it seems this
829                   was wrong ! so decrement barIndex */
830                barIndex--;
831                continue;
832            }
833
834            /* calculate the full 64 bit size */
835
836            if (0 != pPciAgent->pciBar[detectedBar].barSizeHigh)
837            {
838                pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK;
839
840                pPciAgent->pciBar[detectedBar].barSizeLow =
841                    ~pPciAgent->pciBar[detectedBar].barSizeLow + 1;
842
843                pPciAgent->pciBar[detectedBar].barSizeHigh = 0;
844
845            }
846            else
847            {
848
849                pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK;
850
851                pPciAgent->pciBar[detectedBar].barSizeLow =
852                    ~pPciAgent->pciBar[detectedBar].barSizeLow + 1;
853
854                pPciAgent->pciBar[detectedBar].barSizeHigh = 0;
855
856            }
857
858
859
860        }
861        else /* 32bit bar */
862        {
863            /* write oxffffffff to the bar to get the size */
864            mvPciIfConfigWrite(pciIf,
865                            bus,dev,func,
866                            PCI_MEMORY_BAR_BASE_ADDR(barIndex),
867                            0xffffffff);
868
869            /* read size */
870            pPciAgent->pciBar[detectedBar].barSizeLow =
871                mvPciIfConfigRead(pciIf,
872                                bus,dev,func,
873                                PCI_MEMORY_BAR_BASE_ADDR(barIndex));
874
875            if (0 == pPciAgent->pciBar[detectedBar].barSizeLow)
876            {
877                /* this bar is not applicable for this device,
878                   ignore all previous settings and check the next bar*/
879                continue;
880            }
881
882
883            /* restore original value */
884            mvPciIfConfigWrite(pciIf,
885                            bus,dev,func,
886                            PCI_MEMORY_BAR_BASE_ADDR(barIndex),
887                            tmpBaseLow);
888
889        /* calculate size low */
890
891            if (PCI_MEMORY_BAR == pPciAgent->pciBar[detectedBar].barMapping)
892            {
893                pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_MEM_BASE_MASK;
894            }
895            else
896            {
897                pPciAgent->pciBar[detectedBar].barSizeLow &= PBBLR_IO_BASE_MASK;
898            }
899
900            pPciAgent->pciBar[detectedBar].barSizeLow =
901                ~pPciAgent->pciBar[detectedBar].barSizeLow + 1;
902
903            pPciAgent->pciBar[detectedBar].barSizeHigh = 0;
904            pPciAgent->pciBar[detectedBar].barSize =
905                (MV_U64)pPciAgent->pciBar[detectedBar].barSizeLow;
906
907
908        }
909
910        /* we are here ! this means we have already detected a bar for
911        this device , now move on */
912
913        detectedBar++;
914        pPciAgent->barsNum++;
915    }
916
917    return detectedBar;
918}
919
920
921/*******************************************************************************
922* mvPciClassNameGet - get PCI class name
923*
924* DESCRIPTION:
925* This function returns the PCI class name
926*
927* INPUT:
928* baseClassCode - Base Class Code.
929*
930* OUTPUT:
931* pType - the class name
932*
933* RETURN:
934* MV_BAD_PARAM for bad parameters ,MV_ERROR on error ! otherwise MV_OK
935*
936*******************************************************************************/
937MV_STATUS mvPciClassNameGet(MV_U32 baseClassCode, MV_8 *pType)
938{
939
940    switch(baseClassCode)
941    {
942        case 0x0:
943            strcpy(pType,"Old generation device");
944            break;
945        case 0x1:
946            strcpy(pType,"Mass storage controller");
947            break;
948        case 0x2:
949            strcpy(pType,"Network controller");
950            break;
951        case 0x3:
952            strcpy(pType,"Display controller");
953            break;
954        case 0x4:
955            strcpy(pType,"Multimedia device");
956            break;
957        case 0x5:
958            strcpy(pType,"Memory controller");
959            break;
960        case 0x6:
961            strcpy(pType,"Bridge Device");
962            break;
963        case 0x7:
964            strcpy(pType,"Simple Communication controllers");
965            break;
966        case 0x8:
967            strcpy(pType,"Base system peripherals");
968            break;
969        case 0x9:
970            strcpy(pType,"Input Devices");
971            break;
972        case 0xa:
973            strcpy(pType,"Docking stations");
974            break;
975        case 0xb:
976            strcpy(pType,"Processors");
977            break;
978        case 0xc:
979            strcpy(pType,"Serial bus controllers");
980            break;
981        case 0xd:
982            strcpy(pType,"Wireless controllers");
983            break;
984        case 0xe:
985            strcpy(pType,"Intelligent I/O controllers");
986            break;
987        case 0xf:
988            strcpy(pType,"Satellite communication controllers");
989            break;
990        case 0x10:
991            strcpy(pType,"Encryption/Decryption controllers");
992            break;
993        case 0x11:
994            strcpy(pType,"Data acquisition and signal processing controllers");
995            break;
996        default:
997            strcpy(pType,"Unknown device");
998            break;
999    }
1000
1001    return MV_OK;
1002
1003}
1004
1005
1006
1007

Archive Download this file



interactive