ARM-Linux驱动--DMA驱动分析(一)
时间:11-20
来源:互联网
点击:
- *sysdev)
- {
- interror;
- structsysdev_class*cls=sysdev->cls;/*所属的系统设备类*/
- if(!cls)
- return-EINVAL;
- pr_debug("Registeringsysdeviceofclass%s\n",
- kobject_name(&cls->kset.kobj));
- /*initializethekobjectto0,incaseithadpreviouslybeenused*/
- memset(&sysdev->kobj,0x00,sizeof(structkobject));
- /*Makesuretheksetisset*/
- sysdev->kobj.kset=&cls->kset;
- /*Registertheobject*/
- error=kobject_init_and_add(&sysdev->kobj,&ktype_sysdev,NULL,
- "%s%d",kobject_name(&cls->kset.kobj),
- sysdev->id);
- if(!error){
- structsysdev_driver*drv;
- pr_debug("Registeringsysdevice%s\n",
- kobject_name(&sysdev->kobj));
- mutex_lock(&sysdev_drivers_lock);
- /*Genericnotificationisimplicit,becauseitsthat
- *codethatshouldhavecalledus.
- */
- /*Notifyclassauxillarydrivers*/
- list_for_each_entry(drv,&cls->drivers,entry){
- if(drv->add)
- drv->add(sysdev);/*遍历该设备所属同一个设备类的所有设备,并执行相应的add函数*/
- }
- mutex_unlock(&sysdev_drivers_lock);
- kobject_uevent(&sysdev->kobj,KOBJ_ADD);
- }
- returnerror;
- }
(1)首先看第一个函数int __init s3c2410_dma_init(void),在./arch/arm/plat-s3c24xx/dma.c
[cpp]view plaincopy
- int__inits3c2410_dma_init(void)
- {
- returns3c24xx_dma_init(4,IRQ_DMA0,0x40);
- }
下面是该函数的实现
- int__inits3c24xx_dma_init(unsignedintchannels,unsignedintirq,
- unsignedintstride)/*参数分别为通道个数、中断号、寄存器的覆盖范围*/
- {
- structs3c2410_dma_chan*cp;/*通道的结构体表示*/
- intchannel;
- intret;
- printk("S3C24XXDMADriver,Copyright2003-2006SimtecElectronics\n");
- dma_channels=channels;
- dma_base=ioremap(S3C24XX_PA_DMA,stride*channels);
- if(dma_base==NULL){
- printk(KERN_ERR"dmafailedtoremapregisterblock\n");
- return-ENOMEM;
- }
- /*分配DMA告诉缓冲区*/
- dma_kmem=kmem_cache_create("dma_desc",
- sizeof(structs3c2410_dma_buf),0,
- SLAB_HWCACHE_ALIGN,
- s3c2410_dma_cache_ctor);
- if(dma_kmem==NULL){
- printk(KERN_ERR"dmafailedtomakekmemcache\n");
- ret=-ENOMEM;
- gotoerr;
- }
- for(channel=0;channel
- cp=&s3c2410_chans[channel];
- memset(cp,0,sizeof(structs3c2410_dma_chan));
- /*dmachannelirqsareinorder..*/
- cp->number=channel;
- cp->irq=channel+irq;
- cp->regs=dma_base+(channel*stride);
- /*pointcurrentstatssomewhere*/
- cp->stats=&cp->stats_store;
- cp->stats_store.timeout_shortest=LONG_MAX;
- /*basicchannelconfiguration*/
- cp->load_timeout=1<18;
- printk("DMAchannel%dat%p,irq%d\n",
- cp->number,cp->regs,cp->irq);
- }
- return0;
- /*异常处理*/
- err:
- kmem_cache_destroy(dma_kmem);
- iounmap(dma_base);
- dma_base=NULL;
- returnret;
- }
(2)然后是函数s3c24xx_dma_order_set(&s3c2440_dma_order);
- int__inits3c24xx_dma_order_set(structs3c24xx_dma_order*ord)
- {
- structs3c24xx_dma_order*nord=dma_order;
- if(nord==NULL)
- nord=kmalloc(sizeof(structs3c24xx_dma_order),GFP_KERNEL);
- if(nord==NULL){
- printk(KERN_ERR"nomemorytostoredmachannelorder\n");
- return-ENOMEM;
- }
- dma_order=nord;
- memcpy(nord,ord,sizeof(structs3c24xx_dma_order));
- return0;
- }
(3)最后一个函数s3c24xx_dma_init_map(&s3c2440_dma_sel)
该函数功能是建立DMA源与硬件通道的映射图
- int__inits3c24xx_dma_init_map(structs3c24xx_dma_selection*sel)
- {
- structs3c24xx_dma_map*nmap;
- size_tmap_sz=sizeof(*nmap)*sel->map_size;
- intptr;
- nmap=kmalloc(map_sz,GFP_KERNEL);
- if(nmap==NULL)
- return-ENOMEM;
- memcpy(nmap,sel->map,map_sz);
- memcpy(&dma_sel,sel,sizeof(*sel));
- dma_sel.map=nmap;
- for(ptr=0;ptr
map_size;ptr++) - s3c24xx_dma_check_entry(nmap+ptr,ptr);
- return0;
- }
注:由于内核实在是太深了,这里只是表面上按流程大体了解了子同设备的注册和系统设备驱动的注册以及DMA设备的注册和初始化,函数中有很多细节有待进一步研究。
ARM-Linux驱动DMA驱动分 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)