一.前言
sd卡的大名是耳熟能詳,但是sdio匯流排確是不為人解,不過說起他的近親spi就知道了。我們這裡主要是理解sdio匯流排,並不去理解spi匯流排。也許大家會畏懼其龐大的**,其實我們並不需要詳細理解其具體的實現,我們需要理解其架構。
二.主機(host)
在linux2.6.28中,在sdhci-s3c.c實現對主機的sdhci的驅動,而其裝置的新增則在smdk6410_devices中。
在sdhci-s3c.c的sdhci_s3c_probe實現對主機端的驅,對於裡面具體的一些實現我們就不看了,主要是看其中通用的code。
static int __devinit sdhci_s3c_probe(structplatform_device *pdev)
對於上面的函式,主要就是關心上面的幾段**。首先,來看sdhci_host這個結構體,這個是個很重要的東西,這個將會貫穿整個驅動。
struct sdhci_host ;
上面的結構體主要需要關注mmc_host和兩個tasklet_struct。
struct mmc_host ;
mmc_host可以認為是匯流排裝置的一種封裝。
繼續上面的原始碼在sdhci_alloc_host->mmc_alloc_host中,會發現我們的申請的mmc_host裝置指向乙個特殊的類mmc_host_class,在該類中並沒有什麼特殊的function只有乙個mmc_host_classdev_release,從下面的code可知主要是釋放在mmc_alloc_host中開闢的空間。為什麼需要這樣來設計就不知道???
static void mmc_host_classdev_release(structdevice *dev)
下面來看sdhci_add_host這個函式。
int sdhci_add_host(struct sdhci_host *host)
也許大家很困惑,為什麼只關注這幾行code,在該函式中主要是集中在mmc_host成員的初始化賦值。由於中斷中需要處理的內容較多故採用底半部的辦法來處理部分內容。
card_tasklet用於處理mmc插槽上的狀態變化。finish_tasklet用於命令傳輸完成後的處理。timer用於等待硬體中斷。irq則是sdhci的中斷處理。
將host新增入mmc管理,其本質即是新增host的class_dev
int mmc_add_host(struct mmc_host *host)
void mmc_start_host(structmmc_host *host) –啟動host
void mmc_detect_change(struct mmc_host *host,unsigned long delay)
在mmc_alloc_host時,存在下面一行code
init_delayed_work(&host->detect, mmc_rescan);
到此就會發現mmc_start_host一定會執行mmc_rescan只不過乙個是延時後執行,乙個是沒有延時執行。
void mmc_rescan(struct work_struct *work)
/** ...then normal sd...
*/if(!err)
/** ...and finally mmc.
*/err= mmc_send_op_cond(host, 0, &ocr);
if(!err)
mmc_release_host(host);
mmc_power_off(host);
}else
out:
if(host->caps & mmc_cap_needs_poll)
mmc_schedule_delayed_work(&host->detect,hz);
}那先來看mmc_send_if_cond實現,從字面意思上看該函式就是傳送乙個sd標準命令,亦如usb的標準命令一樣。
在這裡不得不先說明一點就是在sd子系統中,所有的資料傳輸均是由host發起。host傳送完一命令則會等待中斷的產生,在這裡採用完成量來實現程序的阻塞。
void mmc_wait_for_req(struct mmc_host *host,struct mmc_request *mrq)
mmc_start_request->host->ops->request(即sdhci_request)
static void sdhci_request(structmmc_host *mmc, struct mmc_request *mrq)
else
sdhci_send_command(host,mrq->cmd);
}mmiowb();
spin_unlock_irqrestore(&host->lock,flags);
}sdhci_request-> sdhci_send_command傳送命令。
當命令傳輸完成系統呼叫中斷處理函式sdhci_irq。在其中進行中斷完成後的處理。
以sdio為例其會採用mmc_attach_sdio來實現驅動和裝置的匹配,其本質還是根據sdio_bus的匹配規則來實現匹配。在mmc_attach_sdio中首先是mmc匹配乙個bus,即採用何種bus來進行mmc bus來處理host。在這裡需要理解一點就是在sdio中,對於sd卡儲存器mmc為實體裝置,而對於非sd卡儲存器,如sdio介面的裝置,則mmc則表徵為bus,這個比較重要。除了mmc bus外還存在sdio_bus。
int mmc_attach_sdio(struct mmc_host *host,u32 ocr)
mmc_release_host(host);
mmc_add_card(host->card);
for(i = 0;i < funcs;i++)
return0;
}比較難以理解的是func,這個東東其實是乙個實體裝置的封裝,可以認為其是乙個裝置。
struct sdio_func *sdio_alloc_func(structmmc_card *card)
上面的code一目了然,其就是具體裝置實體的封裝,其bus型別為sdio_bus. sdio_init_func僅僅是初始化乙個裝置,而並沒有register。在sdio_add_func實現裝置的register,同理就是card實體,在mmc_add_card之前並沒有註冊,在mmc_add_card函式中才實現裝置的註冊。
到此裝置註冊也就完成了,其實sdio匯流排在形式上類似於usb bus,為什麼呢?編寫過usb驅動的童鞋們應該知道,編寫usb驅動僅僅是編寫驅動的載入,並沒有具體載入裝置實體,導致很多童鞋的困惑,為什麼沒有裝置的載入,其實在usb裝置插入時,會動態的建立乙個usb裝置實體,在usb裝置實體建立完成後,根據不同裝置id呼叫相匹配的驅動。而sdio裝置裝置也是一樣的。上面的code比較混亂,總是讓人看不出具體的裝置的載入。其實在上面的code中,其中包括了mmc host的驅動。
三.驅動載入
我們還是以sdio驅動為例,註冊乙個sdio驅動會呼叫下面的函式。
int sdio_register_driver(struct sdio_driver*drv)
其實很好理解sdio_driver其實是driver的封裝,並且該driver的bus為sdio_bus_type。這個裝置的驅動很簡單。那來看sdio_driver結構
struct sdio_driver;
id_table很熟悉吧,嘿嘿在usb的驅動中如何將裝置和驅動匹配就是根據這個東西。在sdio中也是根據該id_table來進行裝置和驅動的匹配。
四.驅動和裝置匹配
在介紹了裝置註冊和驅動註冊後,那來看這兩個是怎樣匹配的。記住sdio驅動之上有兩條匯流排乙個mmc bus 乙個是sdio bus。
先來看mmc bus的match
static int mmc_bus_match(struct device *dev,struct device_driver *drv)
這個很省事,直接就是1.
那在看sdio bus 的match
static int sdio_bus_match(struct device *dev,struct device_driver *drv)
通過檢視上面的具體code的實現你就會發現就是根據id_table來實現裝置和驅動的匹配。
五.probe
不管在裝置註冊還是驅動註冊時,如果發現存在對應的裝置和驅動則會呼叫對應的驅動。不過記住一點是均會先呼叫mmc bus的probe其次是sdio bus的probe。其實現的過程與platfrom類似,不多加贅述。
六.總結
sdio說白了還是一種匯流排,其本質還是離不開驅動和裝置這兩者,如果有usb驅動的經驗則會很好的理解sdio匯流排的驅動。在linux核心是可以觸類旁通的。
SDIO架構初解2
謹以此文紀念過往的歲月 以sdio為例其會採用mmc attach sdio來實現驅動和裝置的匹配,其本質還是根據sdio bus的匹配規則來實現匹配。在mmc attach sdio中首先是mmc匹配乙個bus,即採用何種bus來進行mmc bus來處理host。在這裡需要理解一點就是在sdio中...
SDIO架構初解2
謹以此文紀念過往的歲月 以sdio為例其會採用mmc attach sdio來實現驅動和裝置的匹配,其本質還是根據sdio bus的匹配規則來實現匹配。在mmc attach sdio中首先是mmc匹配乙個bus,即採用何種bus來進行mmc bus來處理host。在這裡需要理解一點就是在sdio中...
Rete演算法初解
rete匹配演算法是一種進行大量模式集合和大量物件集合間比較的高效方法,通過這種方法找出所有匹配各個模式的物件。rete演算法以犧牲記憶體換取高速的策略 rete演算法分為兩個部分 規則編譯 rule compilation 執行時執行 runtime execution 規則編譯 功能 如何在pr...