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

📄 405gp_pci.c

📁 嵌入式ARM的一些源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
   int                     BusDevFunc;

   /*--------------------------------------------------------------------------+
   | Start with device 1, the 405GP is device 0.  MCG 01/04/99
   +--------------------------------------------------------------------------*/
   for (Device = 1; Device < MAX_PCI_DEVICES; Device++)
   {
      BusDevFunc = (BusNum << 16) | (Device << 11);

      if (PCI_Read_CFG_Reg(BusDevFunc, PCIVENDORID,2) != 0xFFFF)
      {
#ifdef DEBUG
         printf("Device %d is present\n",Device);
#endif
         switch( PCI_Read_CFG_Reg(BusDevFunc, PCICLASSCODE, 2) )
         {

            case 0x0604:   /*  PCI-PCI Bridge */
               PCI_Config_Device(BusDevFunc, 2);
               PCI_Config_Bridge(BusDevFunc);
               break;

            case 0x0300:   /*  VGA Display controller */
            case 0x0001:   /*  VGA Display controller (pre PCI rev 2.0)*/
               PCI_Config_VGA_Device(BusDevFunc, 6);
               break;

            default:
               PCI_Config_Device(BusDevFunc, 6);
         }
      }
      else
      {
#ifdef DEBUG
         printf("Device %d not present\n",Device);
#endif
      }
   }
}

/*-----------------------------------------------------------------------
|  Subroutine:  PCI_Config_Device
|
|  Description: Configure a PCI device by examining its I/O and memory
|               address space needs and allocating address space to it by
|               programming the address decoders in the Base Address Registers.
|
|  Inputs:
|               BusDevFunc    Bus+Device+Function number
|               NumBaseAddr   Number of base address registers to
|                             configure
|  Return value:
|               None
+----------------------------------------------------------------------*/
void    PCI_Config_Device(int BusDevFunc, int NumBaseAddr)
{
    int     AddrSlot, i;
    unsigned long  AddrDesc, AddrProg, Min_Gnt_Val, int_line;

    for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++)
    {
       PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 0xFFFFFFFF,4);

       AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 4);

       if (AddrDesc == 0)                   /* unimplemented, stop looking */
          continue;                         /* 01/04/99 MCG */

#ifdef DEBUG
       printf("Read Base Addr Reg %d = 0x%08x\n",AddrSlot,AddrDesc);
#endif

       if ((AddrDesc & 1) == 0)        /* Memory */
       {
          AddrDesc &= 0xFFFFFFF0;

          for (i = 0; (AddrDesc & 1) != 1; i++)
             AddrDesc = AddrDesc >> 1;

          AddrDesc = 1 << i;

          if ((unsigned long)AddrDesc < 4096)
             AddrDesc = 4096;
#ifdef DEBUG
          printf("    PCI Memory space = 0x%x bytes \n",AddrDesc);
#endif
          for (AddrProg = MIN_PCI_MEMADDR1; AddrProg < LowestMemAddr1; AddrProg += AddrDesc);

          PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
          LowestMemAddr1 = AddrProg + AddrDesc;
       }
       else                            /* I/O */
       {
          AddrDesc &= 0xFFFFFFFC;

          for (i = 0; (AddrDesc & 1) != 1; i++)
             AddrDesc = AddrDesc >> 1;

          AddrDesc = 1 << i;
#ifdef DEBUG
          printf("    PCI I/O space = 0x%x bytes \n",AddrDesc);
#endif
          for (AddrProg = MIN_PCI_PCI_IOADDR; AddrProg < LowestIOAddr; AddrProg += AddrDesc);

          PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
          LowestIOAddr = AddrProg + AddrDesc;
       }

    }

    Min_Gnt_Val = 0x80;
    PCI_Write_CFG_Reg(BusDevFunc, PCILATENCYTIM, Min_Gnt_Val, 1);

    /*
     * Write pci interrupt line register (cpci405 specific)
     */
    switch ((BusDevFunc >> 11) & 0x03)
      {
      case 0:
        int_line = 27 + 2;
        break;
      case 1:
        int_line = 27 + 3;
        break;
      case 2:
        int_line = 27 + 0;
        break;
      case 3:
        int_line = 27 + 1;
        break;
      }
    PCI_Write_CFG_Reg(BusDevFunc, PCIINTLINE, int_line, 1);

    /*
     * Enable i/o space, memory space and master on this device
     */
    PCI_Write_CFG_Reg(BusDevFunc, PCICMD, 7, 2);

}

/*-----------------------------------------------------------------------
|  Subroutine:  PCI_Config_VGA_Device
|
|  Description: Configure a PCI VGA device by examining its I/O and memory
|               address space needs and allocating address space to it by
|               programming the address decoders in the Base Address Registers.
|
|  Inputs:
|               BusDevFunc    Bus+Device+Function number
|               NumBaseAddr   Number of base address registers to
|                             configure
|  Return value:
|               None
+----------------------------------------------------------------------*/
void    PCI_Config_VGA_Device(int BusDevFunc, int NumBaseAddr)
{
    int     AddrSlot, i;
    unsigned long  AddrDesc, AddrProg, Min_Gnt_Val;

    for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++)
    {
       PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 0xFFFFFFFF,4);

       AddrDesc = PCI_Read_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot), 4);

       if (AddrDesc == 0)                   /* unimplemented, stop looking */
          continue;                         /* 01/04/99 MCG */

#ifdef DEBUG
       printf("Read Base Addr Reg %d = 0x%08x\n",AddrSlot,AddrDesc);
#endif

       if ((AddrDesc & 1) == 0)        /* Memory */
       {
          AddrDesc &= 0xFFFFFFF0;

          for (i = 0; (AddrDesc & 1) != 1; i++)
             AddrDesc = AddrDesc >> 1;

          AddrDesc = 1 << i;

          if ((unsigned long)AddrDesc < 4096)
             AddrDesc = 4096;
#ifdef DEBUG
          printf("    PCI Memory space = 0x%x bytes \n",AddrDesc);
#endif
          for (AddrProg = MIN_PCI_MEMADDR2; AddrProg < LowestMemAddr2; AddrProg += AddrDesc);

          PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
          LowestMemAddr2 = AddrProg + AddrDesc;
       }
       else                            /* I/O */
       {
          AddrDesc &= 0xFFFFFFFC;

          for (i = 0; (AddrDesc & 1) != 1; i++)
             AddrDesc = AddrDesc >> 1;

          AddrDesc = 1 << i;
#ifdef DEBUG
          printf("    PCI I/O space = 0x%x bytes \n",AddrDesc);
#endif
          for (AddrProg = MIN_PCI_PCI_IOADDR; AddrProg < LowestIOAddr; AddrProg
+= AddrDesc);

          PCI_Write_CFG_Reg(BusDevFunc, PCIBASEADDR0 + (4*AddrSlot),AddrProg,4);
          LowestIOAddr = AddrProg + AddrDesc;
       }

    }

    Min_Gnt_Val = 0x80;
    PCI_Write_CFG_Reg(BusDevFunc, PCILATENCYTIM, Min_Gnt_Val, 1);
}

/*-----------------------------------------------------------------------
|
|  Subroutine:  PCI_Config_Bridge
|
|  Prototype:   void    PCI_Config_Bridge(int BusDevFunc)
|
|  Description: Configure a PCI-PCI bridge
|
|  Inputs:
|               BusDevFunc      Bus+Device+Function number
|
|  Return value:
|               None
|
+----------------------------------------------------------------------*/
void    PCI_Config_Bridge(int BusDevFunc)
{
   int     SecondaryBus;
   int     PrimaryBus;
   int     CommandReg_Val;
   int     InitialLowestIOAddr, InitialLowestMemAddr;
   int     IOBase, MemBase;
   int     IOLimit, MemLimit;

   InitialLowestIOAddr = LowestIOAddr;
   InitialLowestMemAddr = LowestMemAddr1;

   CommandReg_Val = PCI_Read_CFG_Reg(BusDevFunc, PCICMD, 2);

   /* Configure bridge's base address registers */

   PCI_Config_Device(BusDevFunc, 2);

   if ( LowestIOAddr > InitialLowestIOAddr )    /* bridge uses IO space?     */
      CommandReg_Val |= 0x01;                   /* enable I/O Space          */

   if ( LowestMemAddr1 > InitialLowestMemAddr )  /* bridge uses memory space? */
      CommandReg_Val |= 0x02;                   /* enable Memory Space       */

   PrimaryBus = (BusDevFunc >> 16) & 0xFF;
   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_PRIMARYBUS, PrimaryBus, 1);

   SecondaryBus = ++MaxBusNum;
   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SECONDARYBUS, SecondaryBus, 1);

   /* Start with max. possible value for subordinate bus number                    */
   /* Later, after any additional child busses are found, we'll update this        */

   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, 0xFF, 1);

   /* IO Base must be on 4Kb boundary.  Adjust if needed */

   if ((LowestIOAddr % 4096) != 0)
      LowestIOAddr += 4096 - (LowestIOAddr % 4096);

   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOBASE, (LowestIOAddr>>8) & 0xF0, 1);
   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_IOBASEUPPER16, (LowestIOAddr>>16) & 0xFFFF, 2);

   IOBase = LowestIOAddr;

   /* Mem Base must be on 1 MB boundary.  adjust if needed */
   if ((LowestMemAddr1 % 0x100000) != 0)
      LowestMemAddr1 += 0x100000 - (LowestMemAddr1 % 0x100000);

   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_MEMBASE, (LowestMemAddr1>>16) & 0xFFF0, 2);
   MemBase = LowestMemAddr1;

   PCI_Scan(SecondaryBus);

   PCI_Write_CFG_Reg(BusDevFunc, PCIPCI_SUBORDINATEBUS, MaxBusNum, 1);

   IOLimit = LowestIOAddr;
   if (LowestIOAddr > IOBase)           /* IO space used on secondary bus?   */
   {
      CommandReg_Val |= 0x01;           /*   enable IO Space                 */
      IOLimit--;                        /*   IOLimit is highest used address */

⌨️ 快捷键说明

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