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

📄 ixp1200pci.c

📁 ixp1200EB vxworks pci BSP
💻 C
📖 第 1 页 / 共 2 页
字号:
        return (void*) (((UINT32) PciAddr) + SDRAM_PHYS_BASE);
        } else {
        /* Other Memspace address */
        return (void*) (((UINT32) PciAddr) + PCI_MEM_BASE);
        }
    }

/******************************************************************************
*
* sysPhysToPci - translate a physical address to a Pci address
*
* This function converts a physical address to a Pci address. This only works
* for PCI Memory space.
*
* RETURNS: the Pci adddress
*/

void * sysPhysToPci
    (
    void *	PhysAddr	/* Physical address */
    )
    {
    if ((((UINT32) PhysAddr) >= SDRAM_VIRT_OFFSET) &&
        (((UINT32) PhysAddr) <  SDRAM_PF_BASE))
        {
        /* SDRAM address */
        return (void*) (((UINT32) PhysAddr) - SDRAM_PHYS_BASE);
        } else {
        /* Other Memspace address */
        return (void*) (((UINT32) PhysAddr) - PCI_MEM_BASE);
        }
    }

#ifdef AUTO_PCI_CONFIG

/******************************************************************************
*
* sortBars - Sort Bars largest to smallest and assign addresses
*
* This function takes in an array of pointers to BARs and a starting
* PCI address, then it will sort the BARS from largest to smallest. It will
* then align the address appropriately for the first (largest) BAR, and then
* assign increasing addresses with no gaps.
*
* RETURNS: N/A
*/

static void
sortBars
    (
    PciBar *Bars[],    /* Array of pointers to BARs */
    const int nBars,   /* Number of BARs in array */
    UINT32 startAddr   /* PCI address at which to start */
    )
{
    int i, j;
    PciBar *tmp;

    /* Sort biggest to smallest */
    for (i = 0; i < nBars-1; i++) {
        for (j = i+1; j < nBars; j++) {
            if (Bars[j]->size > Bars[i]->size) {
                /* swap them */
                tmp = Bars[i];
                Bars[i] = Bars[j];
                Bars[j] = tmp;
            }
        } /* end for j */
    } /* end for i */

    /* Assign Addresses; first align startAddr */

    startAddr = (startAddr + Bars[0]->size - 1) & ~(Bars[0]->size - 1);

    for (i=0; i < nBars; i++) {
        Bars[i]->address |= startAddr;
        startAddr += Bars[i]->size;
    } /* end for i */
}

/******************************************************************************
*
* addPageEntries - Call sysMmuMapAdd to add page entries for specified range
*
* This function takes a range of addresses containing a gap, and then calls
* sysMmuMapAdd to add page table entries for the one or two memory ranges
* specified.
*
* RETURNS: N/A
*/

static void
addPageEntries
    (
    UINT32 start,      /* Starting PCI address of range*/
    UINT32 end,        /* Ending PCI address of range */
    UINT32 startSkip,  /* Starting PCI address of hole */
    UINT32 skipLen,    /* Ending PCI address of hole */
    UINT32 offset      /* Offset from PCI address to virtual address */
    )
{
    UINT32 start1, end1;

    start1 = start;
    end1 = startSkip;
    if (start1 != end1) {
        start1 = ROUND_DOWN(start1, PAGE_SIZE);
        end1 = ROUND_UP(end1, PAGE_SIZE);
        sysMmuMapAdd((void*)(offset + start1), end1-start1,
                     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
                     VM_STATE_VALID | VM_STATE_WRITABLE     | VM_STATE_CACHEABLE_NOT);
    }
    start1 = startSkip + skipLen;
    end1 = end;
    if (start1 != end1) {
        start1 = ROUND_DOWN(start1, PAGE_SIZE);
        end1 = ROUND_UP(end1, PAGE_SIZE);
        sysMmuMapAdd((void*)(offset + start1), end1-start1,
                     VM_STATE_MASK_VALID | VM_STATE_MASK_WRITABLE | VM_STATE_MASK_CACHEABLE,
                     VM_STATE_VALID | VM_STATE_WRITABLE     | VM_STATE_CACHEABLE_NOT);
    }
}


/******************************************************************************
*
* sysPciAssignAddrs - Scan PCI bus and automatically assign PCI addresses
*
* This function scans the PCI bus to see what other devices are there. It then
* sorts the BARs that it finds and assigns them addresses. It also adds page
* entries to cover the range of PCI space used. It enables PCI transactions
* as defined by INITIAL_PCI_CMD, which defaults to enabling IO transactions.
*
* As a special case, it assigns its own SDRAM space to PCI address zero.
*
* This funciton only has an effect if this processor is the PCI central function.
*
* RETURNS: N/A
*/

void
sysPciAssignAddrs(void)
{
    PciBar   *memBars[MAX_BARS];
    PciBar   *ioBars[MAX_BARS];

    int nMBars, nIOBars;
    int bus, dev, func, i, j;
    UINT16 data;
    INT32 data32, tmp, size;

#ifndef IXM1200
    int central_func;

    central_func =
        IXP1200_SA_CONTROL_PCF & *(UINT32 *)IXP1200_SA_CONTROL;
    if (! central_func)
        return;
#endif

    /* Assign first device to ourselves */
    devices[0].bus = 0;
    devices[0].device = 0;
    devices[0].func = 0;
    devices[0].vendor_id = sysRead16((void*)IXP1200_PCI_VENDOR_ID);
    devices[0].device_id = sysRead16((void*)IXP1200_PCI_DEVICE_ID);
    devices[0].error = FALSE;
    devices[0].bar[CSR_BAR].size = 0x00100000; /* 1 Meg: CSR Mem Base */
    devices[0].bar[CSR_BAR].address = 0;       /* Mem addr */
    devices[0].bar[IO_BAR].size = 0x00000080;  /* 128: CSR I/O Base */
    devices[0].bar[IO_BAR].address = 1;        /* I/O addr */
    devices[0].bar[SD_BAR].size = LOCAL_MEM_SIZE_ACTUAL; /* SDRAM Mem Base */
    devices[0].bar[SD_BAR].address = 0;                  /* Mem addr */
    devices[0].bar[NO_BAR].size = 0;
    nDevices = 1;
    nMBars = nIOBars = 0;
    /* But SDRAM base first */
    memBars[nMBars++] = &devices[0].bar[SD_BAR];
    memBars[nMBars++] = &devices[0].bar[CSR_BAR];
    ioBars[nIOBars++] = &devices[0].bar[IO_BAR];

    func = 0;
    for ( bus = 0; bus < PCI_MAX_BUS; bus++ ) {
        for (dev = 0; dev < PCI_MAX_DEV; dev++ ) {
            pciConfigInWord(bus, dev, func, PCI_CFG_VENDOR_ID, &data);
            if (data == 0xFFFF)
                continue;
            if (nDevices == MAX_DEVICES)
                break;
            devices[nDevices].bus = bus;
            devices[nDevices].device = dev;
            devices[nDevices].func = func;
            devices[nDevices].vendor_id = data;
            pciConfigInWord(bus, dev, func, PCI_CFG_DEVICE_ID, &data);
            devices[nDevices].device_id = data;
            devices[nDevices].error = FALSE;
            for (i=0; i<6; i++) {
                pciConfigOutLong(bus, dev, func,
                                 PCI_CFG_BASE_ADDRESS_0 + (4*i),
                                 0xFFFFFFFF);
                pciConfigInLong(bus, dev, func,
                                PCI_CFG_BASE_ADDRESS_0 + (4*i),
                                &data32);
                if (data32 == 0)
                    break;
                devices[nDevices].bar[i].address = (data32 & 1);
                if (data32 & 1) {
                    /* IO space */
                    tmp = data32 & ~0x00000003;
                    size = ~(tmp-1);
                    devices[nDevices].bar[i].size = size;
                    if (tmp != ~(size-1))
                        devices[nDevices].error = TRUE;
                    else {
                        if (nIOBars < MAX_BARS)
                            ioBars[nIOBars++] = &devices[nDevices].bar[i];
                    }
                } else {
                    /* Mem space */
                    tmp = data32 & ~0x0000000F;
                    size = ~(tmp-1);
                    devices[nDevices].bar[i].size = size;
                    if (tmp != ~(size-1))
                        devices[nDevices].error = TRUE;
                    else {
                        if (nMBars < MAX_BARS)
                            memBars[nMBars++] = &devices[nDevices].bar[i];
                    }
                }
            } /* end for i */
            devices[nDevices].bar[i].size = 0;
            nDevices++;
        } /* end for dev */
    } /* end for bus */

    /* Sort bars, Leave our SDRAM at Mem zero */

    sortBars(memBars+1, nMBars-1, LOCAL_MEM_SIZE_ACTUAL);
    sortBars(ioBars, nIOBars, 0);


    data = INITIAL_PCI_CMD;

    *(UINT32 *)(IXP1200_PCI_MEM_BAR)  = devices[0].bar[CSR_BAR].address;
    *(UINT32 *)(IXP1200_PCI_IO_BAR)   = devices[0].bar[IO_BAR].address;
    *(UINT32 *)(IXP1200_PCI_DRAM_BAR) = devices[0].bar[SD_BAR].address;


    /* Fix C0/Hyannis PCI CSR bug */
    *(volatile int*)(IXP1200_PCI_MEM_BAR);


	for (i=1; i<nDevices; i++) {
        if (devices[i].error)
            continue;

        for (j=0; devices[i].bar[j].size; j++) {
            pciConfigOutLong(devices[i].bus,
                             devices[i].device,
                             devices[i].func,
                             PCI_CFG_BASE_ADDRESS_0 + (4*j),
                             devices[i].bar[j].address);
        } 
        pciConfigOutLong(devices[i].bus,
                         devices[i].device,
                         devices[i].func,
                         PCI_CFG_DEV_INT_LINE,
                         INT_VEC_PIL);
        pciConfigOutWord(devices[i].bus,
                         devices[i].device,
                         devices[i].func,
                         PCI_CFG_COMMAND, 
                         data);

    } /* end for i */

    /* Add page table entries, skip our SDRAM */
    addPageEntries(memBars[1]->address,        /* start */
                   memBars[nMBars-1]->address + memBars[nMBars-1]->size, /*end*/
                   devices[0].bar[CSR_BAR].address, /* skip start */
                   devices[0].bar[CSR_BAR].size,    /* skip len */
                   PCI_MEM_BASE);
    addPageEntries(ioBars[0]->address,         
                   ioBars[nIOBars-1]->address + ioBars[nIOBars-1]->size,
                   devices[0].bar[IO_BAR].address,
                   devices[0].bar[IO_BAR].size,
                   PCI_IO_BASE);
}

#ifdef INCLUDE_AUTO_PCI_CONFIG_SHOW_ROUTINE

/******************************************************************************
*
* pciAddrShow - Shows PCI address assignments
*
* This function prints the PCI address assignments automatically generated. 
* It prints a table giving for each device the bus number, device number,
* a flag indicating whether there was an error for that device, and the
* vendor/device ID. Then it lists the BARs for that device, giving the
* size of the region and its address. If the low-order bit of the address
* is "1", then the address corresponds to I/O space, otherwise it is in
* memory space.
*
* RETURNS: N/A
*/

void pciAddrShow(void)
{
    int i, j;
    for (i=0; i<nDevices; i++) {
        printf("bus %d  dev %d  error %d  id %04X%04X\n",
               devices[i].bus,
               devices[i].device,
               devices[i].error,
               devices[i].vendor_id,
               devices[i].device_id);
        for (j=0; devices[i].bar[j].size; j++) {
            printf("  size %08X  addr %08X\n",
                   devices[i].bar[j].size,
                   devices[i].bar[j].address);
        }
    } /* end for i */
}


/******************************************************************************
*
* pciInfoGet - Retrieves PCI device information
*
* This function retrieves the PCI assignments of the specified device. 
* It returns a pointer to a PciDevice structure containing the bus number,
* device number, a flag indicating whether there was an error for that
* device, the vendor/device ID and a lists the BARs indicating the size of
* the region and its address for that device. A NULL pointer will be
* returned if the specified device is not within range of the configured
* devices.
*
* RETURNS: Pointer to PCI device information, or NULL
*/
PciDevice *pciInfoGet
	(
	UINT16 device
	)
{
    if(device >= nDevices) return(NULL);
	return(&devices[device]);
}

#endif /* ifdef #ifdef INCLUDE_AUTO_PCI_CONFIG_SHOW_ROUTINE */
#endif /* ifdef AUTO_PCI_CONFIG */

⌨️ 快捷键说明

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