在线看毛片网站电影-亚洲国产欧美日韩精品一区二区三区,国产欧美乱夫不卡无乱码,国产精品欧美久久久天天影视,精品一区二区三区视频在线观看,亚洲国产精品人成乱码天天看,日韩久久久一区,91精品国产91免费

<abbr id="27omo"></abbr>

<menu id="27omo"><dl id="27omo"></dl></menu>
    • <label id="27omo"><tt id="27omo"></tt></label>

      新聞中心

      EEPW首頁 > PCI設備初始化編程的過程

      PCI設備初始化編程的過程

      ——
      作者: 時間:2007-03-06 來源:電子產品世界 收藏

      這里以PowerPC上的為例,介紹編程的過程,其他CPU的PCI基本框架是類似的.

      PowerPC的PCI控制器符合PCI2.2標準,以下使我解讀的VxWorks系統(tǒng)程序代碼分析

      主要執(zhí)行過程

      1.PCI設備

      文件romInit.s中romInit()=======>文件bootInit.c中romStart()========>文件usrConfig.c中的usrInit()======>文件syslib.c中的sysHwInit()

      syslib.c

      void sysHwInit (void){ //用于系統(tǒng)硬件

      ......................

      //和網(wǎng)絡,PCI有關的函數(shù)

      #ifdef INCLUDE_EMAC_NETWORK


      //初始化媒介訪問層MAL(控制EMAC和Buffer Descriptor BD間的數(shù)據(jù)傳輸)

      malReset();

      #endif

      #ifdef INCLUDE_PCI
      pciInit(); //初始化PCI
      #endif

      #ifdef INCLUDE_NETWORK
      sysNetHwInit(); //初始化網(wǎng)絡接口
      #endif

      }

       

      //該函數(shù)初始化PCI

      PCI的地址轉換形式:

      CPU->PCI (master/initiator) 地址轉換
      PCI->CPU (slave/target) 地址轉換

      void pciInit()
      {

      unsigned short temp_short;

      /*
      * 初始化并 disable 所有的 PCI Master regions(三個),
      little endian,直接對寄存器R操作 */

      sysPciOutLong(PMM0MA, PMM_UNUSED);
      sysPciOutLong(PMM1MA, PMM_UNUSED);
      sysPciOutLong(PMM2MA, PMM_UNUSED);

      /*

      解釋:

      PMM0MA:地址 0xEE400004, 控制PLB上的映射到PCI存儲空間的range0大小和屬性.

      在PLB上共有三個ranges, PMM1MA代表區(qū)域rang1, PMM2MA代表區(qū)域range2.

      PMM_UNUSED: 0x00000000

      range的定義

      range: map PLB======>PCI 64-bit

      PPBridge(PLB和PCI設備間的接口)responds as a target on the PLB bus in servral address ranges.

      These ranges allow a PLB Master to configure the PPBridge and to cause PPBridge to generate Mem I/O,interrupt acknowledge and special cycles to PCI bus.

      */


      /*
      * Initially disable PCI Target region 2 to start. Region 1 is hardwired
      * to always be active.
      */

      //PTM2MS:地址 0xEF400038,定義PCI存儲空間的大小.這里清零

      sysPciOutLong(PTM2MS, PTM_UNUSED);

      /*
      * Drive PCI 重新置位. 用于熱啟動,置位必須保持1ms
      */


      //解釋: 從PCI寄存器PCI_CFG_BRIDGE_OPT2中讀出數(shù)值

      其中 PPC405GP_PCI_BUSDEVFUNC = 0x00000000;

      PCI_CFG_BRIDGE_OPT2 = 0x60

      temp_short = pciConfigIn(PPC405GP_PCI_BUSDEVFUNC, PCI_CFG_BRIDGE_OPT2, 2);

      //把讀出的值放回寄存器PCI_CFG_BRIDGE_OPT2中

      pciConfigOut(PPC405GP_PCI_BUSDEVFUNC, PCI_CFG_BRIDGE_OPT2,
      temp_short | 0x1000, 2);

      sysLocalDelay(1); /* 延時1ms kernel may not be up yet!! */

      //再放一次

      pciConfigOut(PPC405GP_PCI_BUSDEVFUNC, PCI_CFG_BRIDGE_OPT2, temp_short, 2);


      /*
      * 設置PCI Master(PMM),這是從本地存儲地址Local memory address到PCI空間的映射 * CPU->PCI,參見文件 See config.h中的定義,參考 BSP配置文件
      */{{分頁}}


      //說明sysPciOutLong(A,B);放B到A

      //PMM region 0

      //PMM0LA 0xEF400000, PMM0_LOCAL_ADRS 0x80000000

      sysPciOutLong(PMM0LA, PMM0_LOCAL_ADRS);

      //PMM0PCILA 0xEF400008, PMM0_PCI_LOW_ADRS 0x80000000

      sysPciOutLong(PMM0PCILA, PMM0_PCI_LOW_ADRS);

      //PMM0PCIHA 0xEF40000C, PMM0_PCI_HIGH_ADRS 0x00000000

      sysPciOutLong(PMM0PCIHA, PMM0_PCI_HIGH_ADRS);

      //PMM0MA 0xEF400004,

      //PMM0_PCI_MASK_ATTRIB PMM_MASK_512MB|PMM_ENABLE

      sysPciOutLong(PMM0MA, PMM0_PCI_MASK_ATTRIB);


      sysPciOutLong(PMM1LA, PMM1_LOCAL_ADRS); /* PMM region 1 */
      sysPciOutLong(PMM1PCILA, PMM1_PCI_LOW_ADRS);
      sysPciOutLong(PMM1PCIHA, PMM1_PCI_HIGH_ADRS);
      sysPciOutLong(PMM1MA, PMM1_PCI_MASK_ATTRIB);

      sysPciOutLong(PMM2LA, PMM2_LOCAL_ADRS); /* PMM region 2 */
      sysPciOutLong(PMM2PCILA, PMM2_PCI_LOW_ADRS);
      sysPciOutLong(PMM2PCIHA, PMM2_PCI_HIGH_ADRS);
      sysPciOutLong(PMM2MA, PMM2_PCI_MASK_ATTRIB);


      /*
      * 設置 PCI Target (PTM). 這是從PCI的地址到本地地址的映射
      * 參見文件 config.h中的定義
      * 如果不是用 region 2, 必須保證它的使能位關閉,region 1硬件連接使能.
      */


      //PTM1LA 0xEF400034, PTM1_LOCAL_ADRS 0x00000000

      sysPciOutLong(PTM1LA, PTM1_LOCAL_ADRS);

      //PTM1MS 0xEF400030,

      sysPciOutLong(PTM1MS, PTM1_SIZE_ATTRIB);

      ...................

      /*
      * 寫 405GP PCI 設置寄存器.
      * 使能 405GP,使其成為PCI總線的一個master (PMM).
      * 使能 405GP 作為一個PCI memory target (PTM).
      */

      temp_short = pciConfigIn(PPC405GP_PCI_BUSDEVFUNC, PCI_CFG_COMMAND, 2);
      temp_short = temp_short | PCI_CMD_MASTER_ENABLE | PCI_CMD_MEM_ENABLE;
      pciConfigOut(PPC405GP_PCI_BUSDEVFUNC, PCI_CFG_COMMAND, temp_short, 2);

      ..........................


      /*
      * 作為PCI的主機host掃描PCI總線,查找PCI設備. 并為每個設備分配唯一的PCI或I/O地址* 空間
      */

      pciScan(0);
      return;
      }

       

      //pciScan() - 掃描PCI總線,根據(jù)PCI ID和 vender ID查找設置現(xiàn)有的PCI設備

      void pciScan
      (
      int busNum
      )
      {
      int Device;
      int BusDevFunc;


      /*
      * 從device 1開始,查找每個Slot,如有PCI設備,分配內存和I/O, 405GP是 device 0.
      */


      for (Device = 1; Device <= WALNUT_NUM_PCI_SLOTS; Device++)
      {
      BusDevFunc = (busNum << 16) | (Device << 11);

      //如果Device存在
      if (pciConfigIn(BusDevFunc, PCI_CFG_VENDOR_ID,2) != 0xFFFF)
      {
      #ifdef PCIDEBUG
      printf("* * * * * * * * * * * * * * * * *n");
      printf("Device %d is presentn",Device);
      #endif
      switch( pciConfigIn(BusDevFunc, PCI_CFG_SUBCLASS, 2) )
      {

      case 0x0604: /* PCI-PCI Bridge */
      break;

      default:
      pciDumpDevice(BusDevFunc); //打印 Vendor ID, Device ID

      //調用pciConfigDevice(BusDevFunc, 6)對PCI設備進行設置


      pciConfigDevice(BusDevFunc, 6);
      }
      }
      else
      {
      #ifdef PCIDEBUG
      printf("Device %d not presentn",Device);
      #endif
      }
      }
      }

      //pciConfigDevice - 為PCI設備配置內存和I/O方式

      void pciConfigDevice(int BusDevFunc,int NumBaseAddr)
      {
      int AddrSlot;
      int i;
      unsigned long AddrDesc;
      unsigned long AddrProg;
      unsigned long Min_Gnt_Val;


      // NumBaseAddr = 6
      for (AddrSlot = 0; AddrSlot < NumBaseAddr; AddrSlot++)
      {

      // PCI_CFG_BASE_ADDRESS_0 = 0x10 將0xFFFFFFFF寫入 PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot)
      pciConfigOut(BusDevFunc, PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
      0xFFFFFFFF, 4);

      // 從PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot)讀出數(shù)據(jù)
      AddrDesc = pciConfigIn(BusDevFunc,
      PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
      4);


      // 如果數(shù)據(jù)是0,沒有PCI設備,繼續(xù)循環(huán)搜索
      if (AddrDesc == 0) /* unimplemented, stop looking */
      continue;

      #ifdef PCIDEBUG
      printf("Read Base Addr Reg %d = 0x%08xn",AddrSlot,AddrDesc);
      #endif
      /* 如果AddrDesc的位0是0,表示是Mem方式 */
      if ((AddrDesc & 1) == 0)
      {
      AddrDesc &= 0xFFFFFFF0;

      for (i = 0; (AddrDesc & 1) != 1; i++) //查詢Mem的大小
      AddrDesc = AddrDesc >> 1;

      AddrDesc = 1 << i;

      if ((unsigned long)AddrDesc < 4096)
      AddrDesc = 4096;
      #ifdef PCIDEBUG
      printf(" PCI Memory space = 0x%x bytes n",AddrDesc);
      #endif
      for (AddrProg = PCI_MEMORY_START;
      AddrProg < LowestMemAddr;
      AddrProg += AddrDesc);{{分頁}}

      pciConfigOut(BusDevFunc, PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
      AddrProg, 4);
      LowestMemAddr = AddrProg + AddrDesc;
      }
      else /* I/O 方式*/
      {
      AddrDesc &= 0xFFFFFFFC;

      for (i = 0; (AddrDesc & 1) != 1; i++) //查詢I/O空間的大小
      AddrDesc = AddrDesc >> 1;

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

      pciConfigOut(BusDevFunc, PCI_CFG_BASE_ADDRESS_0 + (4*AddrSlot),
      AddrProg, 4);
      LowestIOAddr = AddrProg + AddrDesc;
      }

      }


      /*
      * Read Min_Gnt(0x3eh) register value and write it to
      * the Latency Timer(0xdh) register
      */
      Min_Gnt_Val = 0x80;
      pciConfigOut(BusDevFunc, PCI_CFG_LATENCY_TIMER, Min_Gnt_Val, 1);

      }

      2.PCI網(wǎng)卡驅動調用過程

      sysNet.c用于初始化系統(tǒng)的網(wǎng)絡

      文件sysNet.c中void sysNetHwInit(void)定義了,這里以AMD PCI網(wǎng)卡97x為例:

      #ifdef INCLUDE_PCI_NETWORK
      unsigned char sysEnetAddr [6]; /* 網(wǎng)卡的 MAC 地址 */
      char sys97xLoadString[100]; /* 需要為初始化加載的字符串 */
      #endif

      #ifdef INCLUDE_PCI_NETWORK
      STATUS sysIn97xEndBldLoadStr() // 生成網(wǎng)絡初始化的字符串


      函數(shù)sysIn97xEndBldLoadStr()調用pciFindDevice()

      STATUS pciFindDevice //用Vendor ID和Device ID查找PCI網(wǎng)卡
      (
      int VendorID,
      int DeviceID,
      int index,
      int *busDevFunc
      )
      {
      int Device;
      int tmpBusDevFunc;
      int tmpIndex;
      int busNum;

      tmpIndex = 0;
      for (busNum = MaxBusNum; busNum >= 0; busNum--) //查訊Slot
      {
      for (Device = 0; Device <= WALNUT_NUM_PCI_SLOTS; Device++)
      {
      tmpBusDevFunc = (busNum << 16) | (Device << 11);

      // 如果指定寄存器中Vendor ID和Device ID正確,賦值給*busDevFunc,返回

      if (pciConfigIn(tmpBusDevFunc, PCI_CFG_VENDOR_ID, 2) == VendorID
      && pciConfigIn(tmpBusDevFunc, PCI_CFG_DEVICE_ID, 2) == DeviceID)
      {
      if (tmpIndex == index)
      {
      *busDevFunc = tmpBusDevFunc;
      return (OK);
      }
      else /* have a match, but not correct index */
      {
      tmpIndex++;
      }
      } } }
      return (ERROR); }


      sysln97xEndBldLoadStr(..)查找PCI以太網(wǎng)卡,得到PCI網(wǎng)卡的基地址,根據(jù)PCI插槽Slot選擇正確的中斷向量,讀網(wǎng)卡的MAC地址,然后調用ln97xEndLoad

      STATUS sysln97xEndBldLoadStr ( void )
      {
      int i;
      int intvec;
      int intlvl;
      ULONG pciMemAddr;
      unsigned int busDevFunc;


      /*
      * 在PCI總線上查找設置第一個AMD設備.
      * 如果發(fā)現(xiàn)存在,函數(shù)pciFindDevice 為busDevFunc賦值
      */

      if (pciFindDevice(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_79C97X, 0, &busDevFunc))
      return(ERROR);

      /*
      * 97x的基地址 1 包含PCI存儲空間的基地址.
      */
      pciMemAddr = pciConfigIn(busDevFunc, PCI_CFG_BASE_ADDRESS_1, 4);
      pciMemAddr &= 0xFFFFFFF0;

      /*
      * 設置PCI定時器反應時間為50 Set latency timer to 50.
      */
      pciConfigOut(busDevFunc, PCI_LATENCY_TIMER, 50, 1);

      /*
      * 每個PCI插槽連接到中斷控制器的管腳不一樣,中斷取決于網(wǎng)卡插在哪一個PCI插槽上.
      */
      switch ((busDevFunc & 0x0000F800) >> 11) /* Strip off just the device */
      {
      case 1 : intvec = INT_VEC_PCI_SLOT3; /* 插槽 3 */
      intlvl = INT_LVL_PCI_SLOT3;
      break;
      case 2 : intvec = INT_VEC_PCI_SLOT2; /* 插槽 2 */
      intlvl = INT_LVL_PCI_SLOT2;
      break;
      case 3 : intvec = INT_VEC_PCI_SLOT1; /* 插槽 1 */
      intlvl = INT_LVL_PCI_SLOT1;
      break;
      case 4 : intvec = INT_VEC_PCI_SLOT0; /* 插槽 0 */
      intlvl = INT_LVL_PCI_SLOT0;
      break;
      default : return(ERROR); /* Not possible, error */

      }

      /*
      * 使能PCI Mem cycles 和 總線 Master 操作
      */
      pciConfigOut(busDevFunc, PCI_CFG_COMMAND,
      PCI_CMD_MEM_ENABLE | PCI_CMD_MASTER_ENABLE, 2);

      /*
      * 得到網(wǎng)卡的MAC地址
      */
      for (i=0; i<6; i++)
      sysEnetAddr = sysInByte(pciMemAddr+APROM01+i);

      /*
      * 生成初始化字符串,如一下形式:
      *
      * <devMemAddr>:<devIoAddr>:<pciMemBase>:<vecNum>:<intLvl>:<memAdrs>:
      * <memSize>:<memWidth>:<csr3b>:<offset>:<flags>
      *
      * 這個字符串將在函數(shù)muxEndLoad()中加載
      */

      sprintf(sys97xLoadString, "0x%x:0x%x:0:%d:%d:0x%x:0:0x%x:0:0:0",
      (unsigned int)pciMemAddr, NONE, intvec, intlvl,
      NONE,NONE);

      return(OK);

      }



      關鍵詞: PCI設備 初始化

      評論


      相關推薦

      技術專區(qū)

      關閉