⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcilib.c

📁 source code of armboot for s3c4510
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
 * All rights reserved.
 *
 * This software is copyrighted by and is the sole property of
 * VIA Networking Technologies, Inc. This software may only be used
 * in accordance with the corresponding license agreement. Any unauthorized
 * use, duplication, transmission, distribution, or disclosure of this
 * software is expressly forbidden.
 *
 * This software is provided by VIA Networking Technologies, Inc. "as is"
 * and any express or implied warranties, including, but not limited to, the
 * implied warranties of merchantability and fitness for a particular purpose
 * are disclaimed. In no event shall VIA Networking Technologies, Inc.
 * be liable for any direct, indirect, incidental, special, exemplary, or
 * consequential damages.
 *
 *
 * File:    pcilib.c
 *
 * Purpose: Diagnose PCI
 *
 * Author:  Henry Lin
 *
 * Date:    July 8, 2005
 *
 * Functions:
 *
 * Revision History:
 *
 */


#if !defined(__STR_H__)
#include "str.h"
#endif
#if !defined(__DEVICE_H__)
#include "device.h"
#endif
#if !defined(__PCIDRIVER_H__)
#include "pcidriver.h"
#endif
#if !defined(__PCILIB_H__)
#include "pcilib.h"
#endif
#include "armboot.h"



/*---------------------  Static Definitions -------------------------*/
#define DBG_PCILIB 0

//#define Print       printf
#define Print(...)  FUNC_NULL()

#define EXTINTMAX 6 /* s3c2510 has 6 external interrupt pins */
#define INTA VEC_PCI_H_INT+EXTINTMAX
#define INTB VEC_PCI_H_INT+EXTINTMAX
#define INTC VEC_PCI_H_INT+EXTINTMAX
#define INTD VEC_PCI_H_INT+EXTINTMAX

/*---------------------  Static Types  ------------------------------*/

/*---------------------  Static Macros  -----------------------------*/
#define PCI_ALLOC_MEM_BASE      0x0         /* Set to PCIBATAPM [31:28]*/
#define PCI_ALLOC_IO_BASE       0x0         /* Set to PCIBATAPI [31:26]*/

#define PCI_EXP_ROM_ENABLE      0x1

#define PCIMode()           (!(ASIC_PCI_PCICON & PCICON_PCCARDMODE))
#define HostMode()          (ASIC_PCI_PCICON & PCI_HST)
#define PCIDRV_HostMode()   (PCIMode() &&  HostMode())

/*---------------------  Static Classes  ----------------------------*/

/*---------------------  Static Variables  --------------------------*/
// queue of PCI devices
PCIDevice_t *g_sPCIDeviceList = NULL;
// root of the tree of PCI devices/buses
PCIDevice_t *g_sPCIroot = NULL;
PCIDevice_t g_arrDev[30];
UINT16  g_u16DevUseIndx = 0;

UINT32  pciScaned;

UINT32  g_u32PciIoBase;
UINT32  g_u32PciMemBase;

/*---------------------  Static Functions  --------------------------*/
char * getDeviceClass (UINT id, UINT device, UINT devClass);
static UINT32 PCIir_AllocateMemSpace (UINT32 size);
UINT32        PCIir_AllocateIOSpace (UINT32 size);

/*---------------------  Export Variables  --------------------------*/

/*---------------------  Export Functions  --------------------------*/




void PCILIB_Scan(UINT32* pu32IoBA, UINT32* pu32MemBA)
{
    UINT32  u32Data;


     /* Must be PCI host to initialise the bus */
    if (PCIDRV_HostMode()) {
        /* initialise the bus */
        Print ("Initializing PCI");

        /* Where in IO and Memory do we start allocating space from? */
        g_u32PciIoBase = PCI_ALLOC_IO_BASE;   // for PCI IO Address Allocation
        g_u32PciMemBase = PCI_ALLOC_MEM_BASE;  // for PCI Memory Address Allocation
        PCILIB_Init();          // Scan PCI bus

        //Get I/O and Mem base address for VT3268
        u32Data =  PCICFG_Read32(0, 1, 0, PCIHBAR1_OFF); //MIO
        *pu32MemBA = (u32Data & 0xFFFFFFF0);    //mask [3:0]
        u32Data =  PCICFG_Read32(0, 1, 0, PCIHBAR0_OFF); //PIO
        *pu32IoBA = (u32Data & 0xFFFFFFFE); //mask Space Indicator bit
        Print ("...done \n");

        /* dump out the contents of each occupied slot */
        PCIr_ForEveryDevice (PCI_Action);
        pciScaned = 1;
    }
    else {
        Print("Sorry, not PCI host - can't scan the bus \n");
    }
}


/*============================================================================
 *
 * parameters:  none
 *
 * description: This routine initialises the PCI subsystem for this board.
 *
 * calls:   none
 *
 * returns: void.
 *
 */
void PCILIB_Init (void)
{
    // Create the root (host) PCI bridge
    g_sPCIroot = PCIir_AllocatePCIDevice ();
    g_sPCIroot->flags.bridge = 1;
    g_sPCIroot->bridge.number    = g_sPCIroot->bridge.primary =
    g_sPCIroot->bridge.secondary = g_sPCIroot->bridge.subordinate = 0;
    g_sPCIroot->bus = 0;

    // Init the device list
    g_sPCIDeviceList= NULL;

    // Scan the PCI bus looking for all available devices/bridges.
    // This builds a set of internal descriptors describing the topology
    // of the PCI subsystem.  It numbers the pci-pci bridges as it
    // scans.
    g_sPCIroot->bridge.subordinate = PCILIB_ScanPCI(g_sPCIroot);

    // Allocate the PCI devices space in IO and Memory
    PCIir_ConfigurePCIDevices (g_sPCIroot);
}


/*============================================================================
 *  description: this routine will insert all known fixed devices into the
 *               device node tree. It will then scan the PCI buses looking
 *               for valid devices.
 *
 *  returns:     device number?
 */

UINT8 PCILIB_ScanPCI(PCIDevice_t * bus)
{
    UINT32 maxSlot;
    UINT32 slot, is_a_multi_function_device = 0;
    UINT32 max;
    UINT32 func, offset,  device;
    UINT32 devClass;
    UINT16 vendor;



    max = 0;

    // if this host doesn't support PCI, do not do anything
    if (PCIDRV_HostMode()) {
        /* maximum subordinate bus number (used in PCI bus numbering) */
        max = bus->bridge.secondary;

        /* how many slots we scan depends on whether this is the primary
            PCI bus or we're going through one or more bridges */
        maxSlot = (bus->bridge.number == 0) ? PCI_MAX_SLOT : 32;

        /* now scan all possible buses and slots looking for devices */
        slot = maxSlot+1; // slot21~slot1 and slot0(=2510 PCI Host Target)
        do {
            slot--;
            // assume that it is not a multi-function device
            is_a_multi_function_device = 0;

            /* now scan all functions */
            for (func = 0; func< 8; func++)
            {

                // if it is not a multi-function device, do not treat it as one..
                if ((func != 0) && !is_a_multi_function_device)
                    continue;

                /* read the device configuration space */
                vendor = PCICFG_Read16 (bus->bridge.number, slot, func,PCIHVID_OFF);

                /* check if it responds */
                if (vendor != PCI_NOTFITTED)
                {
                    UINT8 header_type;
                    PCIDevice_t *newDev;

                    // read the header type (this may be a multi-function device
                    header_type = PCICFG_Read8 (bus->bridge.number, slot, func, PCIHHEADER_OFF);
                    if (func == 0)
                    {
                        is_a_multi_function_device = ((header_type & 0x80) != 0);
                    }

                    // yup, get the device and create PCI device data structure
                    offset = PCIHDID_OFF;
                    device = PCICFG_Read16 (bus->bridge.number, slot, func, offset);
                    newDev = PCIr_AddPCIDevice (bus, bus->bridge.number, slot, func, vendor, device);

                    // is it a PCI-PCI bridge (make this a naturally aligned read)?
                    offset = PCIHCLASS_OFF;
                    devClass = (0x00FFFFFF & PCICFG_Read32 (bus->bridge.number, slot, func,offset)) ;

                    if ((devClass >> 16) == PCI_BRIDGE_CLASS)
                    {
                        if (((devClass & 0xFF00) >> 8) == PCI_2PCI_SUB)
                        {
                            UINT32 buses, command;

                            // init
                            buses = 0 ;
                            // initialise it
                            newDev->flags.bridge = TRUE;
                            newDev->bridge.number = newDev->bridge.secondary = ++max;
                            newDev->bridge.primary = bus->bridge.secondary;
                            newDev->bridge.subordinate = 0xFF;  // until we know better

                            // Clear all status bits and turn off memory, IO and master enables
                            command = PCICFG_Read16 (bus->bridge.number, slot, func, PCIHSC_OFF);
                            PCICFG_Write16 (bus->bridge.number, slot, func, PCIHCMD_OFF, 0x0000);
                            PCICFG_Write16 (bus->bridge.number, slot, func, PCIHST_OFF, 0xFFFF);

                            // configure the bus numbers for this bridge
                            buses &= 0xFF000000;
                            buses |= ((newDev->bridge.primary << 0) |
                            (newDev->bridge.secondary << 8) |
                            (newDev->bridge.subordinate << 16));
                            offset = 0x18;
                            PCICFG_Write32 (bus->bridge.number, slot, func, offset, buses);

                            // scan all subordinate buses
                            max = PCILIB_ScanPCI(newDev);

                            // set the subordinate bus number to its real value
                            newDev->bridge.subordinate = max;
                            buses = (buses & 0xff00ffff) | (max << 16);
                            offset = 0x18;
                            PCICFG_Write32 (bus->bridge.number, slot, func, offset, buses);
                         }
                    }
                }
            }
        } while (slot!=0);
    }

    // return the number of the subordinate bus
    return max;
}


/*============================================================================
 *
 *  description: Allocate new PCIDevice structure.
 *
 *  returns:     Pointer to a devNodeType or NULL if it fails.
 *
 */
PCIDevice_t * PCIir_AllocatePCIDevice (void)
{
    PCIDevice_t *newDev;


    newDev = &g_arrDev[g_u16DevUseIndx++];


    // initialise it
    if (newDev != NULL)
    {
        newDev->flags.bridge = 0;
        newDev->next = NULL;
        newDev->sibling = NULL;
        newDev->parent = NULL;
        newDev->bridge.children = NULL;
    }

    // return a pointer to it
    return newDev;
}


/*============================================================================
 *
 *  description: this routine will insert this device into the devNode tree.
 *               It will keep track of available devNodes.
 *
 *  returns:     void
 *
 */
PCIDevice_t * PCIr_AddPCIDevice (PCIDevice_t * bridge, UINT32 bus, UINT32 slot, UINT32 func,
           UINT16 vendor, UINT16 device)
{
    PCIDevice_t *newDev;

    /* first allocate a new one */
    newDev = PCIir_AllocatePCIDevice ();
    if (newDev != NULL)
    {
        // fill it out
        newDev->bus = bus;
        newDev->slot = slot;
        newDev->func = func;
        newDev->vendor = vendor;
        newDev->device = device;

        // enqueue it [1]
        newDev->next = g_sPCIDeviceList;
        g_sPCIDeviceList = newDev;

        // enqueue it [2]
        newDev->sibling = bridge->bridge.children;
        bridge->bridge.children = newDev;
        newDev->parent = bridge;
    }

    // return it
    return newDev;
}


void PCI_Action (UINT32 bus, UINT32 slot,UINT32 func)
{
    UINT32 data, offset = PCIHBAR0_OFF;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -