EISA 匯流排支援

作者:

Marc Zyngier <maz@wild-wind.fr.eu.org>

本文件對將 EISA 驅動程式移植到新的 EISA/sysfs API 進行了一些隨機註釋。

從 2.5.59 版本開始,EISA 匯流排幾乎獲得了與 PCI 或 USB 等更多主流匯流排相同的地位。 這透過 sysfs 實現,sysfs 定義了一組不錯的抽象來管理匯流排、裝置和驅動程式。

雖然新的 API 使用起來非常簡單,但將現有驅動程式轉換為新的基礎設施並非易事(主要是因為檢測程式碼通常也用於探測 ISA 卡)。 此外,大多數 EISA 驅動程式都是最舊的 Linux 驅動程式之一,因此可以想象,多年來這裡已經積累了一些灰塵。

EISA 基礎設施由三部分組成

  • 匯流排程式碼實現了大部分通用程式碼。 它在 EISA 程式碼執行的所有架構之間共享。 它實現匯流排探測(檢測總線上可用的 EISA 卡)、分配 I/O 資源、允許透過 sysfs 進行花哨的命名,併為驅動程式註冊提供介面。

  • 匯流排根驅動程式實現了匯流排硬體和通用匯流排程式碼之間的粘合。 它負責發現實現匯流排的裝置,並設定它以便以後被匯流排程式碼探測。 這可以簡單到在 x86 上保留一個 I/O 區域,也可以更復雜,例如 hppa EISA 程式碼。 這是為了在“新”平臺上執行 EISA 而需要實現的部分。

  • 驅動程式為匯流排提供它管理的裝置列表,並實現必要的回撥來探測和釋放裝置(如果被告知)。

下面的每個函式/結構都位於 <linux/eisa.h> 中,該檔案嚴重依賴於 <linux/device.h>。

匯流排根驅動程式

int eisa_root_register (struct eisa_root_device *root);

eisa_root_register 函式用於將裝置宣告為 EISA 匯流排的根。 eisa_root_device 結構儲存對該裝置的引用,以及一些用於探測目的的引數

struct eisa_root_device {
        struct device   *dev;    /* Pointer to bridge device */
        struct resource *res;
        unsigned long    bus_base_addr;
        int              slots;  /* Max slot number */
        int              force_probe; /* Probe even when no slot 0 */
        u64              dma_mask; /* from bridge device */
        int              bus_nr; /* Set by eisa_root_register */
        struct resource  eisa_root_res; /* ditto */
};

node

用於 eisa_root_register 內部目的

dev

指向根裝置的指標

res

根裝置 I/O 資源

bus_base_addr

此總線上插槽 0 的地址

slots

要探測的最大插槽號

force_probe

即使插槽 0 為空(沒有 EISA 主機板)也進行探測

dma_mask

預設 DMA 掩碼。 通常是橋接裝置的 dma_mask。

bus_nr

唯一的匯流排 ID,由 eisa_root_register 設定

驅動

int eisa_driver_register (struct eisa_driver *edrv);
void eisa_driver_unregister (struct eisa_driver *edrv);

足夠清楚嗎?

struct eisa_device_id {
        char sig[EISA_SIG_LEN];
        unsigned long driver_data;
};

struct eisa_driver {
        const struct eisa_device_id *id_table;
        struct device_driver         driver;
};

id_table

以 NULL 結尾的 EISA ID 字串的陣列,後跟一個空字串。 每個字串都可以選擇與驅動程式相關的值(driver_data)配對。

driver

通用驅動程式,如裝置驅動程式中所述。 只有 .name、.probe 和 .remove 成員是必需的。

一個例子是 3c59x 驅動程式

static struct eisa_device_id vortex_eisa_ids[] = {
        { "TCM5920", EISA_3C592_OFFSET },
        { "TCM5970", EISA_3C597_OFFSET },
        { "" }
};

static struct eisa_driver vortex_eisa_driver = {
        .id_table = vortex_eisa_ids,
        .driver   = {
                .name    = "3c59x",
                .probe   = vortex_eisa_probe,
                .remove  = vortex_eisa_remove
        }
};

裝置

sysfs 框架在裝置發現和移除時呼叫 .probe 和 .remove 函式(請注意,.remove 函式僅在驅動程式作為模組構建時才會被呼叫)。

這兩個函式都傳遞一個指向“struct device”的指標,該指標封裝在如下所述的“struct eisa_device”中

struct eisa_device {
        struct eisa_device_id id;
        int                   slot;
        int                   state;
        unsigned long         base_addr;
        struct resource       res[EISA_MAX_RESOURCES];
        u64                   dma_mask;
        struct device         dev; /* generic device */
};

id

EISA ID,從裝置讀取。 id.driver_data 是從匹配的驅動程式 EISA ID 設定的。

slot

檢測到裝置的插槽號

state

指示裝置狀態的標誌集。 當前標誌為 EISA_CONFIG_ENABLED 和 EISA_CONFIG_FORCED。

res

分配給此裝置的四個 256 位元組 I/O 區域的集合

dma_mask

從父裝置設定的 DMA 掩碼。

dev

通用裝置(參見基本裝置結構

您可以使用 'to_eisa_device' 宏從 'struct device' 獲取 'struct eisa_device'。

其他東西

void eisa_set_drvdata (struct eisa_device *edev, void *data);

將資料儲存到裝置的 driver_data 區域中。

void *eisa_get_drvdata (struct eisa_device *edev):

獲取先前儲存到裝置的 driver_data 區域中的指標。

int eisa_get_region_index (void *addr);

返回給定地址的區域號 (0 <= x < EISA_MAX_RESOURCES)。

核心引數

eisa_bus.enable_dev

要啟用的插槽的逗號分隔列表,即使韌體將卡設定為停用。 驅動程式必須能夠在這些條件下正確初始化裝置。

eisa_bus.disable_dev

要停用的插槽的逗號分隔列表,即使韌體將卡設定為啟用。 不會呼叫驅動程式來處理此裝置。

virtual_root.force_probe

強制探測程式碼探測 EISA 插槽,即使它找不到符合 EISA 標準的主機板(插槽 0 上沒有任何顯示)。 預設為 0(不強制),當設定 CONFIG_EISA_VLB_PRIMING 時設定為 1(強制探測)。

隨機註釋

將 EISA 驅動程式轉換為新的 API 主要涉及刪除程式碼(因為探測現在位於核心 EISA 程式碼中)。 不幸的是,大多數驅動程式在 ISA 和 EISA 之間共享它們的探測例程。 拆除 EISA 程式碼時必須特別小心,因此其他匯流排不會受到這些外科手術打擊...

不得期望在從 eisa_driver_register 返回時檢測到任何 EISA 裝置,因為匯流排很可能尚未被探測。 事實上,這正是大多數時候發生的情況(匯流排根驅動程式通常在啟動過程中較晚才啟動)。 不幸的是,大多數驅動程式都在自行探測,並期望在退出其探測例程時已經探索了整臺機器。

例如,將您最喜歡的 EISA SCSI 卡切換到“熱插拔”模型是“正確的事情”(tm)。

感謝

我想感謝以下人員的幫助

  • Xavier Benigni 借給我一臺很棒的 Alpha Jensen,

  • James Bottomley, Jeff Garzik 將這些東西放入核心,

  • Andries Brouwer 貢獻了大量的 EISA ID,

  • Catrin Jones 在家裡處理了太多的機器。