pci.c

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

C
612
字号
 *        C           D
 *        D           A
 *
 *   6    A           C
 *        B           D
 *        C           A
 *        D           B
 *
 *   7    A           D
 *        B           A
 *        C           B
 *        D           C
 *
 *   Where A = pin 1, B = pin 2 and so on and pin=0 = default = A.
 *   Thus, each swizzle is ((pin-1) + (device#-4)) % 4
 *
 */
static unsigned char bridgeSwizzle(unsigned char pin, unsigned int slot)
{
    return (((pin - 1) + slot) % 4) + 1;
}
#endif

#if 0
/*============================================================================
 *
 *  routine:     PCIir_AllocateInterrupt
 *
 *  description: Allocate an interrupt #
 *
 *  returns:     void
 *
 */
static void PCIir_AllocateInterrupt (PCIDevice_t * device)
{
    PCIDevice_t *curr;
    unsigned char pin;
    unsigned char interrupt;

    // read the interrupt pin from the device
    pin = uHALr_PCICfgRead8(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
         */
    }

    // work out the interrupt number from the slot/pin
    interrupt = uHALir_PCIMapInterrupt(pin, curr->slot);

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

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

/*
 * These functions are used to generate PCI configuration bus cycles. They
 * all return 0 on success and non-zero on error.  An error should be
 * returned on a master abort for example, so that the presense/absense of
 * a device can be established.  Note that all configuration accesses are
 * DWORD wide on the bus itself, so that the simulated BYTE and WORD
 * accesses provided by these functions must be read/modify/writes of DWORDs.
 *
 *
 * The parameters are:
 *
 *    bBusNo -  Target bus number for the configuration cycle.  Type 0 or
 *              Type 1 bus cycles will be automatically based on the target
 *              specified. Since bus 0 is assumed to be directly connected to
 *              the host bridge, bus 0 references will generate Type 0 cycles
 *              and any other number will generate a Type 1 cycle.
 *
 *    bDevNo -  Device number on the target bus.  The PCI specification allows
 *              device numbers from 0 through 20.  Device 0 corresponds to
 *              setting bit 11 and clearing bits 12-31 in a Type 0 bus cycle.
 *              Device 19 corresponds to setting bit 30 and clearing bits
 *              11-29 and 31,
 *
 *    bFuncNo - The function being selected on the target device.  This can
 *              be in the range of 0 to 7.
 *
 *    bOffset - The offset into the specified configuration space.  Note that
 *              the offset will only be aligned to the size of the data item
 *              being requested.  For example, a byte read of bOffset = 7
 *              would return the high order byte of the second DWORD.
 *
 *    xData -   Pointer to the variable where the result should be stored.
 */
BYTE OEM_ReadConfigByte(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
                        DWORD dwOffset)
{
    BYTE result;
    volatile BYTE *pAddress;

    /* open the (closed) configuration window from local bus memory */
    _V3OpenConfigWindow();

    /* generate the address of correct configuration space */
    pAddress = (volatile BYTE *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
                                                      dwFuncNo, dwOffset));

    /* now that we have valid params, go read the config space data */
    result = *pAddress;

    /* close the window */
    _V3CloseConfigWindow();

    return result;
}

void OEM_WriteConfigByte(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
                         DWORD dwOffset, BYTE bData)
{
    volatile BYTE *pAddress;

    /* open the (closed) configuration window from local bus memory */
    _V3OpenConfigWindow();

    /* generate the address of correct configuration space */
    pAddress = (volatile BYTE *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
                                                     dwFuncNo, dwOffset));

    /* now that we have valid params, go write the config space data */
    *pAddress = bData;

    /* close the window */
    _V3CloseConfigWindow();
}

WORD OEM_ReadConfigWord(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
                        DWORD dwOffset)
{
    WORD result;
    volatile WORD *pAddress;

    /* open the (closed) configuration window from local bus memory */
    _V3OpenConfigWindow();

    /* generate the address of correct configuration space */
    pAddress = (volatile WORD *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
                                                     dwFuncNo, dwOffset));
    /* now that we have valid params, go read the config space data */
    result = *pAddress;

    /* close the window */
    _V3CloseConfigWindow();

    return result;
}

void OEM_WriteConfigWord(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
                         DWORD dwOffset, WORD wData)
{
    volatile WORD *pAddress;

    /* open the (closed) configuration window from local bus memory */
    _V3OpenConfigWindow();

    /* generate the address of correct configuration space */
    pAddress = (volatile WORD *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
                                                      dwFuncNo, dwOffset));

    /* now that we have valid params, go write the config space data */
    *pAddress = wData;

    /* close the window */
    _V3CloseConfigWindow();
}

DWORD OEM_ReadConfigDword(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
                          DWORD dwOffset)
{
    DWORD result;
    volatile DWORD *pAddress;

    /* Open the (closed) configuration window from local bus memory */
    _V3OpenConfigWindow();

    /* generate the address of correct configuration space */
    pAddress = (volatile DWORD *)PCIMakeConfigAddress(dwBusNo, dwDevNo,
                                                      dwFuncNo, dwOffset);

    /* now that we have valid params, go read the config space data */
    result = *pAddress;

    /* close the window */
    _V3CloseConfigWindow();

    return result;
}

void OEM_WriteConfigDword(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
                          DWORD dwOffset, DWORD dwData)
{
    volatile DWORD *pAddress;

    /* open the (closed) configuration window from local bus memory */
    _V3OpenConfigWindow();

    /* generate the address of correct configuration space */
    pAddress = (DWORD *)(PCIMakeConfigAddress(dwBusNo, dwDevNo,
                                              dwFuncNo, dwOffset));

    /* now that we have valid params, go write the config space data */
    *pAddress = dwData;
    if (*pAddress != dwData) {    // V3 sync. bug, tmp Jes
      *pAddress = dwData;
    }

    /* close the window */
    _V3CloseConfigWindow();
}

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

/*
 * This function will encode a Type 0 or Type 1 configuration address based on
 * the parameters passed in.
 */
void OEM_EncodeConfigAddress(DWORD dwBusNo, DWORD dwDevNo, DWORD dwFuncNo,
                             DWORD dwOffset, DWORD *pdwAddress )
{

    *pdwAddress = (DWORD)PCIMakeConfigAddress(dwBusNo, dwDevNo,
                                              dwFuncNo,dwOffset);
}

ULONG PCI_Type1_Configuration(ULONG BusNumber, ULONG SlotNumber, PVOID Buffer,\
                              ULONG Offset, ULONG Length, BOOL  fSet)
{
    PULONG   pBuffer;
    int      registerOffset, endOffset;
    ULONG    DeviceNumber, FunctionNumber;

    if (BusNumber >= PCI_MAX_BUS)
        return (0);

    DeviceNumber = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.DeviceNumber;
    FunctionNumber = ((PCI_SLOT_NUMBER *)&SlotNumber)->u.bits.FunctionNumber;

    if (DeviceNumber >= PCI_MAX_DEVICES)
        return (0);

    registerOffset = Offset / sizeof(ULONG);
    endOffset = registerOffset + (Length + sizeof(ULONG) - 1) / sizeof(ULONG);
    pBuffer = Buffer;

    for ( ; registerOffset < endOffset; ++registerOffset)
    {
        if (fSet)
            OEM_WriteConfigDword(BusNumber, DeviceNumber, FunctionNumber,
                                 registerOffset * 4, *pBuffer++);
        else
            *(pBuffer++) = OEM_ReadConfigDword(BusNumber, DeviceNumber,
                                               FunctionNumber,
                                               registerOffset * 4);
    }

    return (Length);
}

ULONG PCIGetBusDataByOffset(IN ULONG BusNumber, IN ULONG SlotNumber,
                            IN PVOID Buffer, IN ULONG Offset,
                            IN ULONG Length)
{
    return (PCI_Type1_Configuration(BusNumber, SlotNumber,
                                    Buffer, Offset, Length, FALSE));
}

ULONG PCISetBusDataByOffset(IN ULONG BusNumber, IN ULONG SlotNumber,
                            IN PVOID Buffer, IN ULONG Offset,
                            IN ULONG Length)
{
    return (PCI_Type1_Configuration(BusNumber, SlotNumber,
                                    Buffer, Offset, Length, TRUE));
}

/* EOF pci.c */

⌨️ 快捷键说明

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