pciconfig.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,063 行 · 第 1/3 页

C
1,063
字号
/* -*-C-*-
 *
 * $Revision: 1.8 $
 *   $Author: kwelton $
 *     $Date: 2000/08/08 21:45:52 $
 *
 * THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
 * ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
 * PARTICULAR PURPOSE.
 *
 * Copyright (c) 1995, 1996, 1997, 1998  Microsoft Corporation
 * Copyright (c) 1999, 2000 ARM Limited
 * All Rights Reserved
 */

#include <windows.h>
#include <ceddk.h>
#include "pcilib.h"
#include "platform.h"
#include "cdefs.h"
#include "arm_ddk.h"

/*
 * Where in IO and Memory do we start allocating PCI space from?
 */
unsigned int PCI_IOBase = PCI_IO_ALLOCATION_BASE;
unsigned int PCI_MemBase = PHYS_PCI_MEM_BASE; // Virtual addr instead ?

/*
 * structures for holding PCI hierarchy information
 */
#define MAX_PCIDEVICES 128

int PCIDevicesInitialised = FALSE;

PCIDevice_t StaticPCIDevices[MAX_PCIDEVICES];
PCIDevice_t *freePCIDevices = NULL;
PCIDevice_t *PCIDeviceList = NULL;
PCIDevice_t *PCIroot = NULL;

#define MAX(val1, val2)         (((val1) > (val2)) ? (val1) : (val2))

static LPSTR BaseClass[] =
{
    "PRE_20",
    "MASS_STORAGE_CTLR",
    "NETWORK_CTLR",
    "DISPLAY_CTLR",
    "MULTIMEDIA_DEV",
    "MEMORY_CTLR",
    "BRIDGE_DEV",
    "SIMPLE_COMMS_CTLR",
    "BASE_SYSTEM_DEV",
    "INPUT_DEV",
    "DOCKING_STATION",
    "PROCESSOR",
    "SERIAL_BUS_CTLR"
};

typedef struct _DEVICETABLE
{
    WORD wDeviceID;
    LPSTR szDevName;
} DEVICETABLE, *PDEVICETABLE;

typedef struct _VENDORTABLE
{
    WORD wVendorID;
    LPSTR szVendorName;
    PDEVICETABLE pDeviceTable;
    DWORD dwTableSize;
} VENDORTABLE, *PVENDORTABLE;

static DEVICETABLE devIntel[] =
{
    {0x1960, "i960 ATU"},
    {0x0960, "i960"},
    {0x7000, "PIIX3 PCI-ISA Bridge"},
    {0x122E, "PIIX PCI-ISA Bridge"},
    {0x7010, "PIIX3 IDE Interface"},
    {0x1230, "PIIX IDE Interface"},
    {0x7100, "430TX MTXC"},
    {0x1250, "430HX TXC"}
};

static DEVICETABLE devDigital[] =
{
    {0x0019, "21143 ether"},
    {0x0009, "21140 ether"},
    {0x0022, "21150 pci-pci"}
};

static DEVICETABLE devNational[] =
{
    {0x0002, "87560 IDE"},
    {0x000E, "87560 I/O"},
    {0x0011, "87560 I/O"},
    {0x0012, "87560 USB"}
};

static DEVICETABLE devS3[] =
{
    {0x5631, "ViRGE"},
    {0x8C05, "ViRGE"}
};

static DEVICETABLE devEctiva[] =
{
    {0xC935, "EV1936 MachOne Plus"}
};

static DEVICETABLE devCirrus[] =
{
    {0x00B8, "CL-GD5446"}
};

static DEVICETABLE devTI[] =
{
    {0xAC16, "PCI1250A"}
};

static VENDORTABLE vendors[] =
{
    {0x8086, "Intel",    devIntel,
     sizeof(devIntel) / sizeof(DEVICETABLE)},
    {0x1011, "Digital",  devDigital,
     sizeof(devDigital) / sizeof(DEVICETABLE)},
    {0x100B, "National", devNational,
     sizeof(devNational) / sizeof(DEVICETABLE)},
    {0x5333, "S3",       devS3,
     sizeof(devS3) / sizeof(DEVICETABLE)},
    {0x1045, "Ectiva",   devEctiva,
     sizeof(devEctiva) / sizeof(DEVICETABLE)},
    {0x1013, "Cirrus Logic", devCirrus,
     sizeof(devCirrus) / sizeof(DEVICETABLE)},
    {0x104C, "TI",       devTI,
     sizeof(devTI) / sizeof(DEVICETABLE)},
    {0,0,0,0}
};

#define NUMVENDORS  (sizeof(vendors)/sizeof(VENDORTABLE))

static BOOL PrintVendorString(WORD wVendor, WORD wDevice)
{
    DWORD v,d;

    for (v = 0; v < NUMVENDORS; v++)
    {
        if (wVendor == vendors[v].wVendorID)
        {
            for (d = 0; d < vendors[v].dwTableSize; d++)
            {
                if (wDevice == (vendors[v].pDeviceTable)[d].wDeviceID)
                {
                    DPF("%s (%s)", vendors[v].szVendorName,
                        (vendors[v].pDeviceTable)[d].szDevName);

                    return TRUE;
                }
            }

            DPF("%a (0x%H)", vendors[v].szVendorName,
                (vendors[v].pDeviceTable)[d].wDeviceID);

            return TRUE;
        }
    }

    return FALSE;
}

/**********************************************************************/

static unsigned int ALIGN(unsigned int val, unsigned int align)
{
    /*
     * if the value is zero, it is aligned, no matter what the size
     */
    if (val == 0)
        return val;

    /*
     * if the value is less than the alignment, return the alignment
     */
    if (val < align)
        return align;

    /*
     * finally, if there is need to move the value upwards, do so
     */
    if ((val & ~(align - 1)) != 0)
        return (((val) + ((align) - 1)) & ~((align) - 1));
    else
        return val;
}

int GetPCIConfig(ULONG bus, ULONG device, ULONG function,
                 PCI_COMMON_CONFIG *pConfig)
{
    PCI_SLOT_NUMBER slotNumber;
    int length;

    slotNumber.u.AsULONG = 0;
    slotNumber.u.bits.DeviceNumber = device;
    slotNumber.u.bits.FunctionNumber = function;

    length = PCIGetBusDataByOffset(bus, slotNumber.u.AsULONG, pConfig,
                                   0, sizeof(PCI_COMMON_CONFIG));

    return length;
}

int SetPCIConfig(ULONG bus, ULONG device, ULONG function,
                 PCI_COMMON_CONFIG *pConfig)
{
    PCI_SLOT_NUMBER slotNumber;
    int length;

    slotNumber.u.AsULONG = 0;
    slotNumber.u.bits.DeviceNumber = device;
    slotNumber.u.bits.FunctionNumber = function;

    length = PCISetBusDataByOffset(bus, slotNumber.u.AsULONG, pConfig,
                                   0, sizeof(PCI_COMMON_CONFIG));

    return length;
}


/*
 *  Routine:     PCI_AllocateMemSpace
 *
 *  Description: Allocate space in PCI memory
 *
 *  Returns:     Base address of allocated PCI memory space
 *
 *  Note:        Calling this code has a side effect of moving the global
 *               Memory base on.
 */
static DWORD PCI_AllocateMemSpace(DWORD size)
{
    DWORD alignto;
    DWORD base;

    /*
     * align in minimum sized chunks of DEFAULT_MEMORY_ALIGNMENT
     */
    alignto = MAX(size, DEFAULT_MEMORY_ALIGNMENT);
    base = ALIGN(PCI_MemBase, alignto);
    PCI_MemBase = base + size;

    return base;
}


/*
 *  Routine:     PCI_AllocateInterrupt
 *
 *  Description: Allocate an interrupt #
 *
 *  Returns:     Nothing
 *
 */
static void PCI_AllocateInterrupt(PCIDevice_t * device)
{
    unsigned char pin = 0;
    unsigned char interrupt = 0xFF;

    // NOTE: we only support single function PCI devices in the slots and since
    // we don't use compact PCI, we won't worry about the 21152.

    // read the interrupt pin from the device
    pin = OEM_ReadConfigByte(device->bus, device->slot, device->func,
                             PCI_INTERRUPT_PIN);

    // If the device doesn't use interrupts, return.
    if (!pin)
        return;

    // Assign an interrupt to function 0 per a slot.
    if (!device->func)
    {
        switch(device->slot)
        {
        case PCI_SLOT1:
            interrupt = IRQ_PCIINT3;	// PCI Slot 1 INTA = System INTD
            break;
        case PCI_SLOT2:
            interrupt = IRQ_PCIINT2;	// PCI Slot 2 INTA = System INTC
            break;
        case PCI_SLOT3:
            interrupt = IRQ_PCIINT1;	// PCI Slot 3 INTA = System INTB
            break;
        default:
            interrupt = 0xFF;
        }
    }
    else
    {
        EdbgOutputDebugString("WARNING: multiple function interrupts not supported.\r\n");
        return;
    }
    
   
EdbgOutputDebugString("INFO: Assigning IRQ=0x%x to PCI function=0x%x in slot=0x%x\r\n", interrupt, device->func, device->slot);

    /*
     * write it to the device (this will be read later by a
     * device driver
     */
    OEM_WriteConfigByte(device->bus, device->slot, device->func,
                       PCI_INTERRUPT_LINE, interrupt);

    return;

#if 0 
    PCIDevice_t *curr;
    unsigned char pin;
    unsigned char interrupt;

    // read the interrupt pin from the device
    pin = OEM_ReadConfigByte(device->bus, device->slot, device->func,
                             PCI_INTERRUPT_PIN);

    // figure out the interrupt number
    if (device->bus == 0)
    {
        /*
         * Primary bus
         *   pin is this device's pin
         *   curr is this device
         */
        curr = device;
    }
    else
    {
        /*
         * Secondary bus or beyond
         */
        curr = device;

        while (curr->bus != 0)
        {
            /*
             * swizzle the interrupt pins through each PCI-PCI bridge
             */
            pin = bridgeSwizzle (pin, curr->slot);
            curr = curr->parent;
        }

        /*
         * pin is now the pin of the last bridge
         * curr is the last PCI-PCI bridge
         */

⌨️ 快捷键说明

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