版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
嵌入式Linux内核驱动深入实验手国嵌编著嵌入式LINUX培训该资料归属国(简称“国嵌”)所有,并保留。非经国嵌同意(形1.1:kobjectSysfs文件系统工作原理,kobject工作原理 测试创建的文件是否可读#mkdir/home/guoqian/5-4-1#cd/home/guoqian/5-4-1说明:上图kobject.ko为编译生成的内核模块#cpkobject.ko在加载内核模块前先查看当前#ls#insmodkobject.ko在加载模块后查看#ls #ls/sys/kobject_test/ 首先测试是否可#cat再测试是否可#echo1234>/ 再次查看#ls 件系统相似,相比于proc文件系统,使用sysfs导出内核数据的方1.2:busBus设备模型工作原理编写内核模块,向系统中添加一条总线#mkdir/home/guoqian/5-4-2#cd/home/guoqian/5-4-2说明:上图bus.ko为编译生成的内核模块#cpbus.ko在加载内核模块前先查看当前#ls#ls#insmodbus.ko查看#ls#ls说明:从上图可以发现,属性文#ls9.总线属性文件信#cat说明:属性文件,函数show_bus_version被调用打印输出相应信#rmmodbus再次查看#ls#ls说明:从上图可以看出总线/sys/bus/my_bus,属性文/sys/bus/my_bus/version,总线设/sys/devices/my_bus0被删除为:pci,usb,i2c,i2s,tform等驱动。本实验需要大家掌握最本的总线操作,如:总线创建与删除、总线属性文件的读写等1.3:deviceDevice设备模型工作原理基于实验5.4.2实现的总线,在该总线上添加一个设备#mkdir/home/guoqian/5-4-3#cd/home/guoqian/5-4-3说明:上图device.ko为编译生成的内核模块#cpdevice.ko在加载内核模块前先查看当前#ls#ls#insmod注:先加载实验5.4.2总线模#insmod注:然后在该总线上添加一个设查看#ls/sys/bus/my_bus/devices#ls/sys/devices/my_bus0/#ls/sys/devices/my_bus0/my_dev、创建设备属性文/sys/devices/my_bus0/my_dev/dev#cat#rmmoddevice说明:卸载内核模块时,模块卸载函数完成设备的删除作再次查看#ls/sys/bus/my_bus/devices#ls/sys/devices/my_bus0说明:从上图可以看出设备my_dev从总/sys/bus/my_bus上被成功的删除1.4:driverDriver设备模型工作原理基于实验1.2和实验1.3,在该总线上一个驱动程序#mkdir/home/guoqian/5-4-4#cd/home/guoqian/5-4-4说明:上图driver.ko为编译生成的内核模块#cpdriver.ko在加载内核模块前先查看当前#ls#ls#insmod注:加载总#insmod注:在总线上添加设#insmod注:为总线上设备添加驱调用,打印输出语句”Driverfounddevicewhichmydrivercanhandle!”;除了驱动,函数my_driver_init/sys/bus/my_bus/drivers/my_dev/drv查看#ls#ls说明:在加载驱动内核模块时,函数在总/sys/bus/my_bus上添加设备驱/sys/bus/my_bus/drivers/my_dev、创建驱动属性文/sys/bus/my_bus/drivers/my_dev/drv#cat#rmmoddriver说明:卸载内核模块时,模块卸载函数完成驱动的删除作再次查看#ls实验1.5:tform驱动模掌握tform驱动模型工作原理使用tform驱动模型改写按键驱动程设计应用程序,测试tform驱动是否可#mkdir/home/guoqian/5-4-5#cd/home/guoqian/5-4-5#cd/home/guoqian/4-3-1/linux-2.6.29 configARCH=armPILE=arm-注:按键驱动位于Devicedrivers-->Characterdevices<>ButtonsdriverforFriendlyARMMini2440/QQ2440developmentboards#make根据实验要求编写内核模块t_device部分t_device.c(见实验代码光盘5-4-5);编写t_driver编写Makefile(见实验代码光盘5-4-说明:上图t_device.ko和t_buttons.ko为编译生成 t_buttons.ko使用重新编译后的内核起根文件系首先加载t_device内核模块#insmodt_device.ko说明:在加载t_device内核模块时,模块初始化函tform_init被调用,该函数完成t_device的定义和注加载t_buttons内核模块#insmodt_buttons.ko说明:在加载t_buttons内核模块时,模块初始化函数buttons_init被调用,该函数完成t_driver的定义和操作。在t_driver时内核会在相应的tform总线动中函数mini2440_buttons_probe(t_buttons.c)被调由于t_driver中采用混杂型字符设备驱动方式来设#ls-l/dev/*|grep说明:主设备号:10,内核分配的次设备号:57#arm-linux-gcc–staticapp-button.c–oapp-button#cpapp-button/nfsroot/rootfs/tmp运试程运行应用程序,并按键测试功能是否实现#./app-是多次,这是因为按键没有去抖动。可采用延时的方式抖动#rmmodt_buttons.ko#rmmodt_device.ko总结:tform是一种虚拟的总线,tform驱动与传统的设备驱动模型相比,优势在于tform机制将设备本身的资源2.1:DM9000掌握网卡驱动设计规范分析DM9000网卡驱动程序,编写分析文档DM9000网卡驱动位于内核源代码/*模块加载函数staticint init{printk(KERN_INFO"%sEthernetDriver,V%s\n",CARDNAME,/*平台驱动return}/*平台驱动定义staticstructtform_driverdm9000_driver=.driver= =.owner= = = .suspend= =问题:probe调用时机tform.c)册的驱动能驱动该设备,则probe函数被调用。staticint dm9000_probe(structtform_device{ structboard_info*db;/* structure*/structnet_deviceconstunsignedchar*mac_src;intret=0;intiosize;inti;u32/*Initnetworkdevice/*分配ndev=alloc_etherdev(sizeof(structboard_info));if(!ndev){dev_err(&pdev->dev,"couldnotallocatedevice.\n");return-ENOMEM;}SET_NETDEV_DEV(ndev,&pdev->dev);/*setupboardinfostructure*/db=netdev_priv(ndev);memset(db,0,sizeof(*db));db->dev=&pdev->dev;db->ndev=ndev;/*获取tform设备资源 IORESOURCE_MEM,0); IORESOURCE_MEM,1); IORESOURCE_IRQ,0);if(db->addr_res==NULL||db->data_res==NULL||db->irq_res==NULL){dev_err(db->dev,"insufficientresources\n");ret=-ENOENT;goto}iosize=res_size(db-/*I/O内存申请db->addr_req=request_mem_region(db->addr_res->start,if(db->addr_req==NULL)dev_err(db->dev,"cannotclaimaddressregarea\n");ret=-EIO;goto}/*映射db->io_addr=ioremap(db->addr_res->start,if(db->io_addr==NULL)dev_err(db->dev,"failedtoioremapaddressreg\n");ret=-EINVAL;goto}iosize=res_size(db-db->data_req=request_mem_region(db->data_res->start,if(db->data_req==NULL)dev_err(db->dev,"cannotclaimdataregarea\n");ret=-EIO;goto}db->io_data=ioremap(db->data_res->start,iosize);if(db->io_data==NULL){dev_err(db->dev,"failedtoioremapdatareg\n");ret=-EINVAL;goto}/*fillinparametersfornet-devstructurendev->base_addr=(unsignedlong)db->io_addr;ndev->irq=db->irq_res->start;/*ensureatleastwehaveadefaultsetofIOroutines指针*/dm9000_set_io(db,/*checktoseeifanythingisbeingover-ridden/*根据tform的定义(16bit),再次初始化读写数据帧if(pdata!=NULL)/*checktoseeifthedriverwantstoover-ride*defaultIOwidthif(pdata->flags&DM9000_TF_8BITONLY)dm9000_set_io(db,1);if(pdata->flags&DM9000_TF_16BITONLY)dm9000_set_io(db,2);if(pdata->flags&DM9000_TF_32BITONLY)dm9000_set_io(db,4);/*checktoseeifthereareanyIO*over-ridesif(pdata->inblk!=db->inblk=pdata-if(pdata->outblk!=db->outblk=pdata-if(pdata->dumpblk!=db->dumpblk=pdata-db->flags=pdata-}#ifdefCONFIG_DM9000_/*复位/*ID号并判断是否为/*trymultipletimes,DM9000sometimesgetsthereadwrong*/for(i=0;i<8;i++) =ior(db,id_val|=(u32)ior(db,DM9000_VIDH)<<8;id_val|=(u32)ior(db,DM9000_PIDL)<<16;id_val|=(u32)ior(db,DM9000_PIDH)<<if(id_val==DM9000_ID)dev_err(db->dev,"readwrongid0x%08x\n",}if(id_val!=DM9000_ID)dev_err(db->dev,"wrongid:0x%08x\n",id_val);ret=-ENODEV;goto}/*IdentifywhattypeofDM9000weareworkingon/*DM9000_CHIPR=0x2c寄存器,判断网卡类型id_val=ior(db,dev_dbg(db->dev,"dm9000revision0x%02x\n",switch(id_val)casedb->type=TYPE_DM9000A;casedb->type=TYPE_DM9000B; DM9000E\n",id_val);db->type=}/*fromthispointweassumethatwehavefounda/*driversystemfunction/*初始化以太网ndev的部分成员/*设置ndev的基本操作 = =&dm9000_start_xmit; =&dm9000_timeout;ndev->watchdog_timeo=msecs_to_jiffies(watchdog); =&dm9000_stop;ndev->set_multicast_list=&dm9000_hash_table; =&dm9000_ethtool_ops; =&dm9000_ioctl;#ifdefndev->poll_controller=&dm9000_poll_controller; =NETIF_MSG_LINK; =0x1f;db->mii.reg_num_mask=0x1f; =0; =0; =ndev; =dm9000_phy_read; =/*设置MAC地址的操作#if mac_src="friendly-arm";ndev->dev_addr[0]=0x08;ndev->dev_addr[1]=0x90;ndev->dev_addr[2]=0x90;ndev->dev_addr[3]=0x90;ndev->dev_addr[4]=0x90;ndev->dev_addr[5]=mac_src=/*tryreadingthenodeaddressfromtheattachedfor(i=0;i<6;i+=dm9000_read_eeprom(db,i/2,ndev- NULL){mac_src="tform}if(!is_valid_ether_addr(ndev->dev_addr))/*tryreadingfrommacmac_src="chip";for(i=0;i<6;i++)ndev->dev_addr[i]=ior(db,}if(!is_valid_ether_addr(ndev-Please"setusingifconfig\n",ndev-/*网卡驱动ret=if(ret==printk(KERN_INFO"%s:dm9000%cat%p,%pIRQ%dMAC:%pM(%s)\n",ndev->name,dm9000_type_to_char(db->type),db->io_addr,db->io_data,ndev->irq,returndev_err(db->dev,"notfound(%d).\n",return}问题:open函数调用时机在网卡open函数中应该完成以下操作中断;设置寄存器,启动设备;启动发送队staticintdm9000_open(structnet_device{board_info_t*db= ifdev_dbg(db->dev,"enabling%s\n",dev-/*IfthereisnoIRQtypespecified,defaulttosomething*maywork,andltheuserthatthisisaproblemif(irqflags==dev_warn(db->dev,"WARNING:noIRQresourceflags/*中断irqflags|= dev->name,dev))return-/*InitializeDM9000board/*复位DM9000,初始化的寄存器*//*Initdrivervariable*/ t=0;mii_check_media(&db->mii,netif_msg_link(db),/*开启网络接口发送数据队列return}问题:数据发送函数调用时机答:当网卡有数据要发送的时候,该函数被调用 net_device*dev){unsignedlongboard_info_t*db=netdev_priv(dev);dm9000_dbg(db,3,"%s:\n", if(db-> t>1)return1;/*MovedatatoDM9000TXRAM*/writeb(DM9000_MWCMD,db->io_addr);/*把skb的数据拷贝到DM9000的SRAM中*/(db->outblk)(db->io_data,skb->data,skb->len);dev->stats.tx_bytes+=skb->len; /*TXcontrol:Firstpacketimmedia ysend,secondpacketqueue*/if(db- t==1)/*将要发送数据包的长度写入寄存器/*SetTXlengthtoDM9000*/iow(db,DM9000_TXPLL,skb->len);iow(db,DM9000_TXPLH,skb->len>>/*置0x02寄存器bit0位为1,发送数据/*IssueTXpollingcommandiow(db,DM9000_TCR,TCR_TXREQ);/* complete*/dev->trans_start=jiffies;/*savethetimestamp}else/*Secondpacketdb->queue_pkt_len=skb->len;}spin_unlock_irqrestore(&db->lock, thisSKB*/return}问题:网卡有几种类型的中断staticirqreturn_tdm9000_interrupt(intirq,void{structnet_device*dev=dev_id;board_info_t*db=netdev_priv(dev);intint_status;unsignedlongu8dm9000_dbg(db,3,"entering%s\n", /*Arealinterruptcoming/*holdersofdb->lockmustalwaysblockIRQs*/spin_lock_irqsave(&db->lock,flags);/*Savepreviousregisteraddress*/reg_save=readb(db->io_addr);/*Disableallinterrupts/*关闭所有中断iow(db,DM9000_IMR,/*中断状态寄存器,清中断/*GotDM9000interruptstatusint_status=ior(db,DM9000_ISR); /*GotISR*/iow(db,DM9000_ISR,int_status);/*ClearISRstatus*/if /*Receivedthecomingpacket/*文到达中断if(int_status&ISR_PRS)/*TrnasmitInterruptcheck/*报文发送完成中断if(int_status&ISR_PTS)if(db->type!=TYPE_DM9000E)if(int_status&ISR_LNKCHNG)/*firealink-changerequest*/schedule_delayed_work(&db->phy_poll,1);}}/*重新使能中断/*Re-enableinterruptmask*/iow(db,DM9000_IMR,db->imr_all);/*Restorepreviousregisteraddress*/writeb(reg_save,db->io_addr);spin_unlock_irqrestore(&db->lock,return}中断状态寄存器判断出是否是接收中断,接着使用函数dm9000_rx处理接收到的数据。staticdm9000_rx(structnet_device{board_info_t*db=netdev_priv(dev);structdm9000_rxhdrrxhdr;structsk_buff*skb;u8rxbyte,*rdptr;boolGoodPacket;intRxLen;/*Checkpacketreadyornot*/do{ior(db, /*Dummyread/*Getmostupdateddata*/rxbyte=readb(db->io_data);/*Statuscheck:thisbytemustbe0or1*/if(rxbyte>DM9000_PKT_RDY){ request}
iow(db,DM9000_RCR,0x00);/*StopDevice*/iow(db,DM9000_ISR,IMR_PAR);/* if(rxbyte!=DM9000_PKT_RDY)/*Apacketreadynow &Getstatus/length*/GoodPacket=true;writeb(DM9000_MRCMD,db-(db->inblk)(db->io_data,&rxhdr,sizeof(rxhdr));RxLen=le16_to_cpu(rxhdr.RxLen);if length%04x\n",/*PacketStatuscheck*/if(RxLen<0x40){GoodPacket=ifdev_dbg(db->dev,"RX:BadPacket}if(RxLen>DM9000_PKT_MAX)dev_dbg(db->dev,"RST:RXLen:%x\n",}/*rxhdr.RxStatusisidenticaltoRSRregister.if(rxhdr.RxStatus&(RSR_FOE|RSR_CE|RSR_AE|RSR_PLE|RSR_RWTO|RSR_LCS|RSR_RF))GoodPacket=if(rxhdr.RxStatus&RSR_FOE){if(netif_msg_rx_err(db))dev_dbg(db->dev,"fifoerror\n");}if(rxhdr.RxStatus&RSR_CE){if(netif_msg_rx_err(db))dev_dbg(db->dev,"crcerror\n");}if(rxhdr.RxStatus&RSR_RF){if(netif_msg_rx_err(db))dev_dbg(db->dev,"lengtherror\n");}}/*MovedatafromDM9000/*分配if&&((skb=dev_alloc_skb(RxLen+4))!=NULL)){skb_reserve(skb,2);rdptr=(u8*)skb_put(skb,RxLen-/*ReadreceivedpacketfromRXSRAM/*从硬件中数据到(db->inblk)(db->io_data,rdptr,RxLen);dev->stats.rx_bytes+=RxLen;/*Passtoupperlayerskb->protocol=eth_type_trans(skb,/*调用netif_rx将数据交给协议栈}else/*needtodumpthepacket'sdata(db->dumpblk)(db->io_data,}}while(rxbyte==}2.2掌握网卡驱动设计规实现回环网卡驱动程#mkdir/home/guoqian/5-5-2#cd/home/guoqian/5-5-2说明:上图loopback.ko为编译生成的内核模块#cploopback.ko#insmodloopback.ko由于网络接口驱动本身特点,在 下没有设节点,而是使用socket系统调用内核子系统。故 #ifconfiglotest#rmmodloopback说明:卸载内核模块时,模块卸载函数被调用,函数完成网络接口驱动注销操作2.3:input掌握input子系统驱动模型工作原理以input驱动模式改写按键驱动程设计应用程序,测试驱#mkdir/home/guoqian/5-5-3#cd/home/guoqian/5-5-3由于内核本身自带mini2440按键驱动,为了不跟本验,内核配置时去掉对mini2440按键驱动的支持#cd/home/guoqian/4-3-1/linux-2.6.29 configARCH=armPILE=arm-注:按键驱动位于Devicedrivers-->Characterdevices<>ButtonsdriverforFriendlyARMMini2440/QQ2440developmentboards#make注:按键驱动中断触发方式采沿触发说明:上图input_button.ko为编译生成的内核模块#cpinput_button.ko使用重新编译后的内核起根文件系#insmodinput_button.ko说明:加载内核模块时,模块初始化函数dev_init被#cat说明:主设备号:13,次设备号:64输入子系统设备文件会被自动创#ls-l/dev/*|grep#arm-linux-gcc-staticapp-input.c-oapp-input#cpapp-input/nfsroot/rootfs/tmp运试程#./app-说明:type:1,code:2,value:1-->表示2号键被按下#rmmodinput_button总结:iux系统提供了nut子系统,按键、触摸屏、鼠标等输入型设备都可以利用nut接口函数来实现设备驱动。这里留一个思考题,本实验中断触发方式采沿触发,能否将中断触发方式改为单沿触发?2.4:s3c2440掌握触摸屏驱动工作流程,回顾input子系统驱动模型分析s3c2440触摸屏驱动程软件:linux-2.6.29内核源代模块加载函数主要完成以下工作INT_TC,INT_ADC中断staticint init{structinput_dev/*获取时钟,触摸屏是挂载在APBBUS上的设备,需adc_clock=clk_get(NULL,if(!adc_clock)printk(KERN_ERR"failedtogetadcclocksource\n");return-ENOENT;}/*I/O内存是不能直接进行的,必须对其进行映射if(base_addr==NULL){printk(KERN_ERR"Failedtoremapregisterblock\n");return-ENOMEM;}/*ConfigureGPIOs*/s3c2410_ts_connect*GPIO设置*//*使能预分频和设置分频系数iowrite32(S3C2410_ADCCON_PRSCEN|/*设置ADC延时,在等待中断模式下表示产生的间隔时间,ADC转换周期等待定时器 /*ADCTSC0xd3将触摸屏置为等待中断模式,等待iowrite32(WAIT4INT(0),/*以下配置2.6内核划分出来的输入设备/*Initialiseinputstuffinput_dev=if(!input_dev)printk(KERN_ERR"Unabletoallocatetheinputdevice!!\n");return-}dev=dev->evbit[0]=BIT(EV_SYN)|BIT(EV_KEY)|dev->keybit[BITS_TO_LONGS(BTN_TOUCH)]/*设置绝对坐标x的最小最大值(0-0x3FF)input_set_abs_params(dev,ABS_X,0,0x3FF,0,/*设置绝对坐标y的最小最大值(0-0x3FF)input_set_abs_params(dev,ABS_Y,0,0x3FF,0,input_set_abs_params(dev,ABS_PRESSURE,0,1,0,dev->name=s3c2410ts_name;dev->id.bustype=BUS_RS232;dev->id.vendor=0xDEAD;dev->duct=dev->id.version=/*INT_TC,INT_ADC中断,问题:两种中断的产生/*Getirqsif(request_irq(IRQ_ADC,stylus_action,"s3c2410_action",dev))printk(KERN_ERR"s3c2410_ts.c:CouldnotallocatetsIRQ_ADC!\n");return-EIO;}if(request_irq(IRQ_TC,stylus_updown,"s3c2410_action",dev))printk(KERN_ERR"s3c2410_ts.c:CouldnotallocatetsIRQ_TC!\n");return-EIO;}printk(KERN_INFO"%ssuccessfullyloaded\n",/*Allwentok,soregistertotheinputsystem/*输入设备return}staticirqreturn_tstylus_updown(intirq,void{unsignedlongdata0;unsignedlongdata1;intupdown;了这个锁,才能进入到启动ADC代码部分,注意尽管中信号量因为休眠不适合使用在ISR中,down_trylock是一个例外,它不会休眠if(down_trylock(&ADC_LOCK)==0){OwnADC=1;data0=ioread32(base_addr+S3C2410_ADCDAT0);data1=updown=(!(data0&S3C2410_ADCDAT0_UPDOWN))&&(!(data1&S3C2410_ADCDAT0_UPDOWN));updown=1 updown=0 if(updown)}elseOwnADC=0;}}return}接下来应分析函数touch_timer_fire函数staticvoidtouch_timer_fire(unsignedlongdata){unsignedlongdata0;unsignedlongdata1;intupdown;data0=ioread32(base_addr+S3C2410_ADCDAT0);data1=updown=(!(data0&S3C2410_ADCDAT0_UPDOWN))&&(!(data1&S3C2410_ADCDAT0_UPDOWN));if(updown)/*转换四次后进行汇报if(count!=0){longtmp;tmp=xp;xp=yp;yp=tmp;/*求平均值xp>>=yp>>=input_report_abs(devABS_Xxp);input_report_abs(devABS_Y/*报告按键,键值为1(代表触摸屏对应的被按下input_report_key(dev,BTN_TOUCH,/*报告触摸屏的状态,1表明触摸屏被按下input_report_abs(dev,ABS_PRESSURE,/*同步}
xp=yp=count=完毕
AUTOPST,}elsecount=于等待触摸的阶段*/放)*/input_report_key(dev,BTN_TOUCH,/*报告触摸屏的状态,0表明触摸屏未被按下input_report_abs(dev,ABS_PRESSURE,/*同步/*设置触摸屏为等待中断模式,等待触摸笔按下if(OwnADC){OwnADC=0;}}}制器的处理模式为x/y位置自动转换模式,开启ADCINT_ADCstaticirqreturn_tstylus_action(intirq,void{unsignedlongdata0;unsignedlongif(OwnADC)data0=ioread32(base_addr+S3C2410_ADCDAT0);data1=xp+=data0&S3C2410_ADCDAT0_XPDATA_MASK;yp+=data1&/*如果小于四次重新启动ADC转换if(count<(1<<2))|AUTOPST,iowrite32(ioread32(base_addr+S3C2410_ADCCON)|}else/*如果超过四次,启动1个时间滴答的定时器,停止mod_timer(&touch_timer,jiffies+1);}}return}INT_ADC中断处理函数主要完成记录四次ADC转换完代码if(updown)/*转换四次后进行汇报if(count!=0){longtmp;tmp=xp;xp=yp;yp=tmp;/*求平均值xp>>=yp>>=input_report_abs(devABS_Xxp);input_report_abs(devABS_Y/*报告按键,键值为1(代表触摸屏对应的被按下input_report_key(dev,BTN_TOUCH,/*报告触摸屏的状态,1表明触摸屏被按下input_report_abs(dev,ABS_PRESSURE,/*同步}
xp=yp=count=AUTOPST,}代码staticstructtimer_listtouch_timer=TIMER_INITIALIZER(touch_timer_fire,0,0);表明定时器处理函数为touch_timer_fire代码mod_timer(&touch_timer,表明定时器超时时间为10msupdownISR,如果能获取ADC_LOCK则调用后,启动1个时间滴答的定时器,停止ADC,也就是说在这样可以防止屏幕抖动3.1:RTL-8139PCIRTC-8139pci网卡,既是一个pci总线驱动,又是一个网络设分析RTL-8139PCI网卡驱动程序,编写分析文软件:linux-2.6.29内核源代RTL-8139PCI网卡驱动位于内核源代码:模块加载函数主要完成以下工作采用pci_register_driverpci驱动程序/*模块加载函数staticint initrtl8139_init_module{/*whenwe'reamodule,wealwaysprintaversion*evenifno8139boardis#ifdefprintk(KERN_INFORTL8139_DRIVER_NAME/*PCI驱动return}/*pci_driver定义staticstructpci_driverrtl8139_pci_driver= = = = = #ifdefCONFIG_PM = =rtl8139_resume,#endif/*CONFIG_PM*/问题:probe调用时机答当pci驱动时内核会在pci总线上去遍历所有的码drivers/pci/pci-driver.c),匹配方式为设备ID和驱动注册的id_table是否一致;如果匹配成功,说明的驱动能驱动该设备,则probe函数被调用。staticint devinitrtl8139_init_one(structpci_devconststructpci_device_id{/*初始化8139网卡dev=rtl8139_init_board(pdev);if(IS_ERR(dev))return/*TheRtl8139-specificentriesinthedevicestructure./*设置net_device的基本方法dev->netdev_ops=&rtl8139_netdev_ops;dev->ethtool_ops=&rtl8139_ethtool_ops;dev->watchdog_timeo=TX_TIMEOUT;netif_napi_add(dev,&tp->napi,rtl8139_poll,DPRINTK("abouttoregisterdevicenamed%s(%p)...\n",dev->name,dev);/*网卡驱动i=register_netdev(dev);if(i)gotoerr_out;}接下来分析函数rtl8139_init_board和net_device基本方rtl8139_netdev_ops函数static devinitstructnet_device*rtl8139_init_boardpci_dev{/*devandprivzeroedinalloc_etherdev/*分配dev=alloc_etherdev(sizeof/*enabledevice(incl.PCIPMwakeupandhotplug/*在PCI驱动使用PCI设备的任何资源(I/O区或者中断)之前,驱动必须使能设备*/rc=pci_enable_deviceifgoto/*获得bar地址上的资源pio_start=pci_resource_start(pdev,0);pio_end=pci_resource_end(pdev,0);pio_flags=pci_resource_flags(pdev,0);pio_len=pci_resource_len(pdev,0);mmio_start=pci_resource_start(pdev,1);mmio_end=pci_resource_end(pdev,1);mmio_flags=pci_resource_flags(pdev,1);mmio_len=pci_resource_len(pdev,1);/*I/O资源的申请rc=pci_request_regions(pdev,DRV_NAME);if(rc)gotoerr_out;disable_dev_on_err=1;/*enablePCIbus-mastering/*通过设置PCI设备令寄存器允许pci_set_master(pdev);if(use_io){/*I/O地址映射ioaddr=pci_iomap(pdev,0,0);if(!ioaddr){dev_err(&pdev->dev,"cannotmapPIO,rc=-goto}dev->base_addr=pio_start;tp->regs_len=pio_len;}else/*ioremapMMIOregion/*I/O地址映射ioaddr=pci_iomap(pdev,1,0);if(ioaddr==NULL){dev_err(&pdev->dev,"cannotremapMMIO,}
use_io=1;gotodev->base_addr=(long)ioaddr;tp->regs_len=mmio_len;}/*复位rtl8139_chip_reset}/*网络接口操作函数集staticconststructnet_device_opsrtl8139_netdev_ops= = /*网络接口打开函数 = = = rtl8139_start_xmit,/*发送函数 = = =rtl8139_tx_timeout,#ifdefCONFIG_NET_POLL_CONTROLLER =rtl8139_poll_controller,问题:open函数调用时机函数rtl8139_open主要完成以下操作8139DMA缓冲区设置寄staticintrtl8139_open(structnet_device{/*中断retval=request_irq(dev->irq,rtl8139_interrupt,IRQF_SHARED,dev->name,dev);ifreturn/*分配8139接收与传送DMA缓冲区tp->tx_bufs=dma_alloc_coherent(&tp->pci_dev->dev,TX_BUF_TOT_LEN,&tp->tx_bufs_dma,GFP_KERNEL);tp->rx_ring=dma_alloc_coherent(&tp->pci_dev->dev,RX_BUF_TOT_LEN,&tp->rx_ring_dma,GFP_KERNEL);/*开启网络接口发送数据队列netif_start_queuereturn}staticirqreturn_trtl8139_interrupt(intirq,{/*中断状态寄存器spin_lock(&tp-status=RTL_R16/*ReceivepacketsareprocessedbypollIfnotrunningstartitnow./*文到达中断if(status&if(netif_rx_schedule_prep(&tp->napi)){RTL_W16_F(IntrMask,rtl8139_norx_intr_mask); }}/*报文发送完成中断if(status&(TxOK|TxErr)){rtl8139_tx_interrupt(dev,tp,ioaddr);if(status&TxErr)RTL_W16(IntrStatus,}return}RTL8139网卡的发送和接收与前面实验5.5.1DM9000网掌握块设备驱动设计规范模式,测试方法设计ramdisk驱动程序,并测#mkdir/home/guoqian/part5/4-1#cd/home/guoqian/part5/4-1 注:本程序以X86说明:上图blk.ko为编译生成的内核模块#insmodblk.ko#lsmod|grepblk#ls注:查看设备文件是否自动建#mkfs.ext3注意:格式化块设备文件为ext3系#mkdir–p注:创建挂#mount/dev/simp_blkdev/mnt/blk#ls/mnt/blk注:挂载块设备simp_blkdev #cp/etc/init.d/*/mnt/blk#ls/mnt/blk注
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 高速公路顶管穿越工程合同
- 2025管材买卖合同
- 2025厂房出租合同范本
- 设计师合作协议证书聘用合同
- 证券投资指导员聘用合同
- 设计委托合同范本导师
- 2025房地产销售代理合同书(范本)
- 小学音乐感知课模板
- 我国布病流行状况
- 山西财贸职业技术学院《平面摄影基础》2023-2024学年第一学期期末试卷
- 手机硬件测试介绍
- 2023-2024学年贵州省贵阳市八年级(上)期末数学试卷
- 科普绘本设计理念
- 三年级上册口算练习1000道一附答案
- 胃镜室工作总结
- 商品总监述职报告
- 述职报告及工作思路(四篇合集)
- 2023-2024学年云南省昆明市盘龙区九年级上学期期末物理试卷及答案
- 政府采购评审专家考试题库(完整版)
- 国库现金流预测分析报告
- 福建省厦门市2023-2024学年九年级上学期化学用语教学质量监测试题(无答案)
评论
0/150
提交评论