Linux DMA驅(qū)動構(gòu)架分析_第1頁
Linux DMA驅(qū)動構(gòu)架分析_第2頁
Linux DMA驅(qū)動構(gòu)架分析_第3頁
Linux DMA驅(qū)動構(gòu)架分析_第4頁
Linux DMA驅(qū)動構(gòu)架分析_第5頁
已閱讀5頁,還剩8頁未讀 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、Linux DMA驅(qū)動構(gòu)架分析以linux2.6.32中的S3C2440驅(qū)動為例進行分析,DMA驅(qū)動所對應(yīng)的源碼為 linux-2.6.32.2archarmmach-s3c2440dma.c,代碼入口為: arch_initcall(s3c2440_dma_init);static int _init s3c2440_dma_init(void)return sysdev_driver_register(&s3c2440_sysclass, &s3c2440_dma_driver);DMA驅(qū)動作為系統(tǒng)驅(qū)動由sysdev_driver_register來向內(nèi)核注冊,這里只關(guān)注 s3c2440_

2、dma_driver相關(guān)的內(nèi)容,即調(diào)用drive中的add方法,其他的kobject對 象略過。static struct sysdev_driver s3c2440_dma_driver = .add= s3c2440_dma_add, TOC o 1-5 h z ;s3c2440_dma_add做了一系列的初始化工作,相應(yīng)的代碼如下:static int _init s3c2440_dma_add(struct sys_device *sysdev)s3c2410_dma_init();s3c24xx_dma_order_set(&s3c2440_dma_order);return s3c

3、24xx_dma_init_map(&s3c2440_dma_sel);下面就其中出的三個函數(shù)一一進行分析。A.s3c2410_dma_init首先 s3c2410_dma_init()調(diào)用 了 plat-s3c24xx 平臺公共的函數(shù) s3c24xx_dma_init(4, IRQ_DMA0, 0 x40);int _init s3c24xx_dma_init(unsigned int channels, unsigned int irq,unsigned int stride)struct s3c2410_dma_chan *cp;int channel;int ret;13121313p

4、rintk(S3C24XXDMA Driver, (c) 2003-2004,2006SimtecElectronicsn);13141315dma_channels = channels;1316dma_base = ioremap(S3C24XX_PA_DMA, stride * channels);if (dma_base = NULL) printk(KERN_ERR dma failed to remap register blockn);return -ENOMEM;1322dma_kmem = kmem_cache_create(dma_desc”,sizeof(struct s

5、3c2410_dma_buf), 0,SLAB_HWCACHE_ALIGN,s3c2410_dma_cache_ctor);1327if (dma_kmem = NULL) printk(KERN_ERRdmafailedtomakekmemcachen);ret = -ENOMEM;goto err;1333for (channel = 0; channel number = channel;cp-irq = channel + irq;cp-regs = dma_base + (channel* stride);1343/* point current stats somewhere */

6、cp-stats = &cp-stats_store;cp-stats_store.timeout_shortest = LONG_MAX;13471348/* basic channel configuration */13491350cp-load_timeout = 1number, cp-regs, cp-irq);13551356return 0;1357err:kmem_cache_destroy(dma_kmem);iounmap(dma_base);dma_base = NULL;return ret;1364首先來關(guān)注一下函數(shù)傳遞的參數(shù):unsigned int channe

7、ls: s3c2440 平臺對應(yīng)的 DMA 通道總數(shù),為 4unsigned int irq:起始DMA中斷的中斷號unsigned int stride:每通道DMA所占寄存器資源數(shù)1309行struct s3c2410_dma_chan記錄dma通道信息,內(nèi)容如下:151 struct s3c2410_dma_chan 152/* channel state flags and information */153unsigned charnumber;/dma 通道號,154unsigned charin_use;當前通道是否已經(jīng)使用155unsigned charirq_claimed;

8、 / 有無 dma 中斷156unsigned charirq_enabled; /是否使能了 dma中斷157unsigned charxfer_unit;傳輸塊大小158159/* channel state */160161enum s3c2410_dma_state state;162enum s3c2410_dma_loadst load_state;163struct s3c2410_dma_client *client;164165/* channel configuration */166enum s3c2410_dmasrc source;167enum dma_chreq_

9、ch;168unsigned longdev_addr;169unsigned longload_timeout;170 unsigned int flags; /* channel flags */171 172 struct s3c24xx_dma_map *map; /* channel hw maps */173174/* channels hardware position and configuration */175void _iomem*regs;/* channels registers */176void _iomem*addr_reg; /* data address r

10、egister */177unsigned intirq;中斷號178unsigned longdcon;/默認控制寄存器的值179/* driver handles */s3c2410_dma_cbfn_t callback_fn;傳輸完成回調(diào)函數(shù)s3c2410_dma_opfn_t op_fn; 操作完成回調(diào)函數(shù)*/183/* stats gathering */struct s3c2410_dma_stats*stats;struct s3c2410_dma_statsstats_store;187/* buffer list and information */structs3c241

11、0_dma_buf*curr;structs3c2410_dma_buf*next;structs3c2410_dma_buf*end;192/* system device */structsys_device dev;/* current dma buffer */* next buffer to load */* end of queue */dma 緩沖區(qū)鏈表1315行dma_channels是全局變量記錄了當前系統(tǒng)dma通道總數(shù) 1317-1321行映射dma控制寄存器 1323-1332 行 為 struct s3c2410_dma_buf 分 配 cache,并利 用函數(shù) s3c

12、2410_dma_cache_ctor 初始化為 0。1334-1354 行的循環(huán)就是初始化全局數(shù)組 struct s3c2410_dma_chan s3c2410_chansS3C_DMA_CHANNELS;,其中包括通道編號、中斷號以及寄存 器基地址等信息。這個數(shù)組是針對實際的硬件信息建立的,每個硬件的dma通 道唯一對應(yīng)一個struct s3c2410_dma_chan的數(shù)據(jù)結(jié)構(gòu)。與之對應(yīng)的還有一個虛擬 的dma通道,其實質(zhì)是將不同dma請求源區(qū)分開來,然后用一個虛擬的通道號 與之一一對應(yīng),然后與實際的dma通道通過一張map表關(guān)聯(lián)起來。關(guān)于map的 相關(guān)內(nèi)容后面將會分析。首先這個函數(shù)的

13、意義是預定一些目標板要用的dma通道,使用的是上文提到的 虛擬的dma通道號。int _init s3c24xx_dma_order_set(struct s3c24xx_dma_order *ord)struct s3c24xx_dma_order *nord = dma_order;1478if (nord = NULL)nord = kmalloc(sizeof(struct s3c24xx_dma_order), GFP_KERNEL);1481if (nord = NULL) printk(KERN_ERR no memory to store dma channel ordern)

14、;return -ENOMEM;1486dma_order = nord;memcpy(nord, ord, sizeof(struct s3c24xx_dma_order);return 0;1477行dma_order是個全局變量,其作用是記錄下目標板的dma預定信息。這里使用的是s3c2440_dma_order為其賦值,數(shù)據(jù)如下:51static struct s3c24xx_dma_order_initdata s3c244052.channels = 53DMACH_SDI = 54.list = 550 = 3 | DMA_CH_VALID,561 = 2 | DMA_CH_VA

15、LID,572 = 1 | DMA_CH_VALID,583 = 0 | DMA_CH_VALID,59,60,61DMACH_I2S_IN = 62.list = 630 = 1 | DMA_CH_VALID,641 = 2 | DMA_CH_VALID,65,66,67DMACH_I2S_OUT=68.list = 690 = 2 | DMA_CH_VALID,701 = 1 | DMA_CH_VALID,71,72,_dma_order = 7374757677787980818283848586878889909192DMACH_PCM_IN = .list = 0 = 2 | DMA

16、_CH_VALID,1 = 1 | DMA_CH_VALID,DMACH_PCM_OUT = .list = 0 = 1 | DMA_CH_VALID,1 = 3 | DMA_CH_VALID, DMACH_MIC_IN = .list = 0 = 3 | DMA_CH_VALID,1 = 2 | DMA_CH_VALID,;DMACH_SDI、DMACH_I2S_IN等是系統(tǒng)為dma所分配的虛擬dma通道號, 猶如中斷子系統(tǒng)為中斷分配的中斷號一樣,與具體硬件的中斷向量號是不一致 的。后面我們在系統(tǒng)中使用的dma通道號,都將是內(nèi)核虛擬出來的, s3c2410_dma_request函數(shù)將為用戶

17、找到硬件對應(yīng)的 dma通道號。提取上面 DMACH_SDI虛擬通道來分析一下:DMACH_SDI = .list = 0=3 | DMA_CH_VALID,1=2 | DMA_CH_VALID,2=1 | DMA_CH_VALID,3=0 | DMA_CH_VALID,List這個結(jié)構(gòu)列出的是實際dma通道的可用信息,這里表面對于sdi所能夠使用 的dma通道包含通道3,2,1,0 一共四個通道,為什么從大到小排列是因為某些dma 請求只能使用dma0,dma1等較小的通道號,比如外部總線dma只能使用dma0, 為了避免sdi占用,這里就采用了這種排列。三、 s3c24xx_dma_init

18、_map上面提到過一個map,這里就是為這個map的初始化函數(shù)了。他實際是根據(jù)硬 件情況為一個全局變量賦值。與前面的初始化一樣,這里主要是為了統(tǒng)一管理 plat24xx這個平臺下的dma資源,所以不同的芯片必須將自己硬件有關(guān)的dma 信息初始化到相應(yīng)的全局變量中。再說函數(shù)之前先來關(guān)注一下struct s3c24xx_dma_map這個數(shù)據(jù)結(jié)構(gòu),他提供了 dma虛擬通道與實際的dma通道直 接的關(guān)聯(lián):struct s3c24xx_dma_map const char*name;/虛擬 dma 通道名稱struct s3c24xx_dma_addr hw_addr;unsigned longcha

19、nnelsS3C_DMA_CHANNELS;/實際 dma 通道信息unsigned longchannels_rxS3C_DMA_CHANNELS;上面的結(jié)構(gòu)只提供了單個虛擬通道的dma視圖,整個芯片的虛擬dma通道的分 配情況是靠struct s3c24xx_dma_map數(shù)組完成的。在這里由struct s3c24XX_dma_selection 來統(tǒng)一管理。struct s3c24xx_dma_selection struct s3c24xx_dma_map *map;/記錄了 struct s3c24xx_dma_map 數(shù)組的首地 址unsigned longmap_size;/

20、struct s3c24xx_dma_map 數(shù)組的成員個數(shù)unsigned longdcon_mask;/dma 控制器掩碼void (*select)(struct s3c2410_dma_chan *chan,struct s3c24xx_dma_map *map);/ 虛擬通道選擇函數(shù)void (*direction)(struct s3c2410_dma_chan *chan,struct s3c24xx_dma_map *map, enum s3c2410_dmasrc dir);/dma 方向;有了上面的背景以后下面函數(shù)就是簡單的數(shù)據(jù)拷貝了,函數(shù)比較簡單不在展開說 明。int _

21、init s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel)struct s3c24xx_dma_map *nmap;size_t map_sz = sizeof(*nmap) * sel-map_size;int ptr;1459nmap = kmalloc(map_sz, GFP_KERNEL);if (nmap = NULL)return -ENOMEM;14631464memcpy(nmap, sel-map, map_sz);memcpy(&dma_sel, sel, sizeof(*sel);dma_sel.map = n

22、map;for (ptr = 0; ptr map_size; ptr+) s3c24xx_dma_check_entry(nmap+ptr, ptr);return 0;146514661467146814691470147114721473初始化的任務(wù)比較簡單,就是建立硬件dma通道信息即:struct s3c2410_dma_chan s3c2410_chansS3C_DMA_CHANNELS;建立目標板虛擬dma通道與硬件的dma通道的關(guān)聯(lián):static struct s3c24xx_dma_order *dma_order;建立芯片本身的虛擬dma通道與硬件dma通道的視圖:stat

23、ic struct s3c24xx_dma_selection dma_sel;完成上述工作以后,基本的dma框架就已經(jīng)建立起來了。接下分析dma使用過程中相關(guān)的函數(shù):(一)s3c2410_dma_requestint s3c2410_dma_request(unsigned int channel,struct s3c2410_dma_client *client,void *dev)struct s3c2410_dma_chan *chan;unsigned long flags;int err;722pr_debug(dma%d: s3c2410_request_dma: client=

24、%s, dev=%pn”,channel, client-name, dev);725726local_irq_save(flags);727chan = s3c2410_dma_map_channel(channel);if (chan = NULL) local_irq_restore(flags);return -EBUSY;733734dbg_showchan(chan);735chan-client = client;chan-in_use = 1;738if (!chan-irq_claimed) pr_debug(dma%d: %s : requesting irq %dn”,c

25、hannel, _func_, chan-irq);742chan-irq_claimed = 1;local_irq_restore(flags);745err = request_irq(chan-irq,s3c2410_dma_irq, IRQF_DISABLED,client-name, (void *)chan);748749local_irq_save(flags);750if (err) chan-in_use = 0;chan-irq_claimed = 0;local_irq_restore(flags);755printk(KERN_ERR %s: cannot get I

26、RQ %d for DMA %dn,client-name, chan-irq, chan-number);return err;760chan-irq_enabled = 1;763764local_irq_restore(flags);765766/* need to setup */767768 pr_debug(%s: channel initialised, %pn, _func, chan);769return chan-number I DMACH_LOW_LEVEL;728行s3c2410_dma_map_channel為虛擬的dma通道可用的硬件dma資源,相應(yīng) 的代碼如下:

27、static struct s3c2410_dma_chan *s3c2410_dma_map_channel(int channel)struct s3c24xx_dma_order_ch *ord = NULL;struct s3c24xx_dma_map *ch_map;struct s3c2410_dma_chan *dmach;int ch;1394if (dma_sel.map = NULL II channel dma_sel.map_size)return NULL;13971398 ch_map = dma_sel.map + channel;13991400/* first, try the board mapping */1401if (dma_order) ord = &dma_order-channelschannel;1404for (ch = 0; ch listch)continue;1408if (s3c2410_chansord-listch.in_use = 0) ch = ord-listch& DMA_CH_VALID;

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論