pci枚舉初始化部分(1)

来源:https://www.cnblogs.com/weiyoutongxing/archive/2018/11/29/10039005.html
-Advertisement-
Play Games

基於linux 4.20 rc3源碼分析 1 .掃描所有PCI設備並檢測,填充設備結構體 其中pci_setup_device(dev)函數對掛載在該匯流排上所有的設備進行檢測並獲取相關數據,並設備信息進行填充。對於有些需特殊處理的設備也進行了特殊處理,達到儘量相容新老設備的目的。 1.1查詢設備廠商 ...


基於linux-4.20-rc3源碼分析

1 .掃描所有PCI設備並檢測,填充設備結構體

static struct pci_dev *pci_scan_device(struct pci_bus *bus, int devfn)
{
 struct pci_dev *dev;
 u32 l;

 //查詢PCI設備廠商號和設備號,以判斷設備是否發生異常
 if (!pci_bus_read_dev_vendor_id(bus, devfn, &l, 60*1000))
  return NULL;

//分配設備結構體
 dev = pci_alloc_dev(bus);
 if (!dev)
  return NULL;

 dev->devfn = devfn;
 dev->vendor = l & 0xffff;                  //獲取廠商號
 dev->device = (l >> 16) & 0xffff;    //獲取設備號

//設置鏈表節點
 pci_set_of_node(dev);

//掃描所有設備並設置,和獲取信息
 if (pci_setup_device(dev)) {
  pci_bus_put(dev->bus);
  kfree(dev);
  return NULL;
 }

 return dev;
}

其中pci_setup_device(dev)函數對掛載在該匯流排上所有的設備進行檢測並獲取相關數據,並設備信息進行填充。對於有些需特殊處理的設備也進行了特殊處理,達到儘量相容新老設備的目的。

1.1查詢設備廠商號和設備號

pci_bus_read_dev_vendor_id()

#ifdef CONFIG_PCI_QUIRKS
 struct pci_dev *bridge = bus->self;

 /*
  * Certain IDT switches have an issue where they improperly trigger
  * ACS Source Validation errors on completions for config reads.
  */
  //某些IDT交換機有一個問題,即它們在完成配置讀取時錯誤地觸發ACS源驗證錯誤。
 if (bridge && bridge->vendor == PCI_VENDOR_ID_IDT &&
     bridge->device == 0x80b5)
  return pci_idt_bus_quirk(bus, devfn, l, timeout);
#endif

 return pci_bus_generic_read_dev_vendor_id(bus, devfn, l, timeout);

該函數主要讀取PCI設備的廠商號和設備號,如果讀取出來包含全0,全1之類數據,這判斷為PCI設備異常不再進行下一步操作。
對於某些IDT交換機設備,可能存在在讀取設備信息時觸發ACS驗證錯誤,此時需要進行特殊操作,如果代碼允許在IDT交換機上請一定配置PCI_QUIRKS選項。
ACS:安全接入控制器,接入伺服器(Access Server)又稱網路接入伺服器NAS或遠程接入伺服器RAS,它是位於公用電話網(PSTN/ISDN)與IP網之間的一種遠程訪問接入設備。

  • pci_bus_generic_read_dev_vendor_id()
    該函數用於獲取設備廠商號,並對錯誤的狀態進行識別,對需重試獲取的設備進行重試獲取信息,並通過超時加以限制。
 if (pci_bus_read_config_dword(bus, devfn, PCI_VENDOR_ID, l))
  return false;

 /* Some broken boards return 0 or ~0 if a slot is empty: */
//如果槽為空時會返回0或者~0
 if (*l == 0xffffffff || *l == 0x00000000 ||
     *l == 0x0000ffff || *l == 0xffff0000)
  return false;

//具有配置重試機制的設備進行重試讀取廠商號
 if (pci_bus_crs_vendor_id(*l))
  return pci_bus_wait_crs(bus, devfn, l, timeout);

 return true;

1.2獲取設備信息並設置

1.2.1獲取設備頭信息

pci_hdr_type()

 pci_read_config_byte(dev, PCI_HEADER_TYPE, &hdr_type);

1.2.2 判斷是否為pcie設備

//判斷是否為pcie設備
 pos = pci_find_capability(pdev, PCI_CAP_ID_EXP);
 if (!pos)
  return;

 pdev->pcie_cap = pos;
 pci_read_config_word(pdev, pos + PCI_EXP_FLAGS, &reg16);
 pdev->pcie_flags_reg = reg16;
 pci_read_config_word(pdev, pos + PCI_EXP_DEVCAP, &reg16);
 pdev->pcie_mpss = reg16 & PCI_EXP_DEVCAP_PAYLOAD;

通過state寄存器獲取capability的有效性,並通過capability首地址順勢查找是否有PCIE capatility結構體存在,從而判斷該設備是否時pcie設備

1.2.2.1 查找設備的capability,判斷其是否為pcie設備

pci_find_capability()

//判斷capability有效性,有效則獲取capability表起始地址
 pos = __pci_bus_find_cap_start(dev->bus, dev->devfn, dev->hdr_type);

 //獲取ID為cap的capability的偏移
 if (pos)
  pos = __pci_find_next_cap(dev->bus, dev->devfn, pos, cap);
  • __pci_bus_find_cap_start()
 //判斷capabilityPointer寄存器中的值是否有效
 pci_bus_read_config_word(bus, devfn, PCI_STATUS, &status);
 if (!(status & PCI_STATUS_CAP_LIST))
  return 0;

 switch (hdr_type) {
 case PCI_HEADER_TYPE_NORMAL:
 case PCI_HEADER_TYPE_BRIDGE:
  return PCI_CAPABILITY_LIST;                 //普通設備偏移
 case PCI_HEADER_TYPE_CARDBUS:
  return PCI_CB_CAPABILITY_LIST;           //橋設備偏移
 }
  • __pci_find_next_cap()
//pos為capatibility結構首地址
 pci_bus_read_config_byte(bus, devfn, pos, &pos);

//目前ttl = PCI_FIND_CAP_TTL = 48;
 while ((*ttl)--) {
  if (pos < 0x40)
   break;
  pos &= ~3;
  pci_bus_read_config_word(bus, devfn, pos, &ent);

  id = ent & 0xff;
  if (id == 0xff)
   break;
  if (id == cap)            //獲取ID為PCI_CAP_ID_EXP的capatility結構體偏移
   return pos;
  pos = (ent >> 8);
 }

1.2.3 添加槽結構體到鏈表

pci_dev_assign_slot()

 struct pci_slot *slot;

 mutex_lock(&pci_slot_mutex);
 list_for_each_entry(slot, &dev->bus->slots, list)
  if (PCI_SLOT(dev->devfn) == slot->number)
   dev->slot = slot;
 mutex_unlock(&pci_slot_mutex);

1.2.4設置驅動名稱

 dev_set_name(&dev->dev, "%04x:%02x:%02x.%d", pci_domain_nr(dev->bus),
       dev->bus->number, PCI_SLOT(dev->devfn),
       PCI_FUNC(dev->devfn));

1.2.5獲取設備類別等信息

//獲取設備類別
 class = pci_class(dev);            //讀取PCI空間偏移0x8處數據。

 dev->revision = class & 0xff;                                //版本號
 dev->class = class >> 8;   /* upper 3 bytes */       //設備類型

1.2.6 boot階段列印PCI信息

if (pci_early_dump)
early_dump_pci_device(dev);
boot階段用於列印pci設備所有配置空間信息

1.2.7 獲取pci配置空間大小

pci_cfg_space_size()
通過判斷設備類型從而獲取配置空間大小。
pci和pxi模式1的設備的配置空間大小為256byte,PXI模式2和pcie設備的配置空間大小為4096byte


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • [TOC] Shell腳本規範     良好的代碼規範不僅方便閱讀,也利於維護和提升開發效率。因此建議大家在編寫Shell腳本時養成良好的代碼習慣。今天就和大家探討一下在Shell腳本中的一些規範,詳細如下所示: 1、在Shell腳本中,第一行指定腳本解釋器,如下所示: 2、在S ...
  • ifconfig命令 作用:用於顯示以及設置當前活動網卡信息 一. 顯示當前活動網卡信息 ifconfig 從上面可以看到當前主要有2塊活動網卡,eth0:代表當前本地真實網卡 lo:代表回訪網卡,也可以看到當前的ip地址:192.168.125.128 二. 重新設置網卡的ip地址,一般只有roo ...
  • 索引: 商業開發實戰總結 一、機器概述 1.屏幕:14'' 2.解析度:1920*1080 3.顯卡:Intel 核顯 & Nvidia GeForce 940MX 獨顯 ,雙顯卡 4.其它硬體在 Linux 下可忽略 二、目標概述 1.系統安裝後為中文環境 2.輸入法為中文拼音輸入法 3.屏幕顯示 ...
  • hostname命令 作用:顯示以及設置主機名 一. 顯示系統主機名 第一種方式:hostname 第二種方式:cat /etc/sysconfig/ntework 使用舉例: 從上面可以看到我的系統主機名為pclu 二. 設置系統主機名,必須是root用戶才可以執行 第一種方式:hostname ...
  • [TOC] 背景 一直沒搞清楚 與 的區別, 看著公司里遺留的shell, 也就稀里糊塗地用著... 這是很糟糕的態度 結論放前面 使進程在後臺運行, 預設輸出到標準輸出(即當前屏幕), 除非重定向輸出. 此時忽略 SIGINT 信號. ==若關閉會話, 則進程會結束== 進程仍舊在前臺跑, 預設輸 ...
  • 前言:因windows10的更新,最近很多朋友會遇到mstsc遠程連接桌面報錯: windows10企業版解決方式: 按“win+R”,運行 gpedit.msc, 找:“電腦配置”->“管理模板”->“系統”->“憑據分配”,這裡面有個“加密 Oracle 修正”,按圖修改即可; windows ...
  • 【轉載】 Windows Subsystem for Linux -- Pico Process Overview Overview This post discusses pico processes, the foundation of WSL. It explains how pico pro ...
  • Zabbix簡介 Zabbix是一個高度集成的企業級開源網路監控解決方案,與Cacti、nagios類似,提供分散式監控以及集中的web管理界面。zabbix具備常見商業監控軟體所具備的功能,例如主機性能監控,網路設備性能監控,資料庫性能監控,ftp等通用協議的監控,能夠靈活利用可定製警告機制,允許 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...