1. gzyueqian
      13352868059
      首頁 > 新聞中心 > > 正文

      S3C2410網(wǎng)卡CS8900A驅(qū)動(dòng)程序的移植及問題解析

      更新時(shí)間: 2008-02-26 09:03:52來源: 粵嵌教育瀏覽量:828

        硬件環(huán)境:SBC-2410X開發(fā)板(CPU:S3C2410X)
        內(nèi)核版本:2.6.11.1
        運(yùn)行環(huán)境:Debian2.6.8
        交叉編譯環(huán)境:gcc-3.3.4-glibc-2.3.3

      部分 網(wǎng)卡CS8900A驅(qū)動(dòng)程序的移植

      一、從網(wǎng)上將Linux內(nèi)核源代碼下載到本機(jī)上,并將其解壓:
        #tar jxf linux-2.6.11.1.tar.bz2

      二、打開內(nèi)核頂層目錄中的Makefile文件,這個(gè)文件中需要修改的內(nèi)容包括以下兩個(gè)方面。
        (1)指定目標(biāo)平臺。
      移植前:
      ARCH?= $(SUBARCH)
      移植后:
      ARCH :=arm
        (2)指定交叉編譯器。
      移植前:
      CROSS_COMPILE ?=
      移植后:
      CROSS_COMPILE :=/opt/crosstool/arm-s3c2410-linux-gnu/gcc-3.3.4-glibc-2.3.3/bin/arm-s3c2410-linux-gnu-
      注:這里假設(shè)編譯器就放在本機(jī)的那個(gè)目錄下。

      三、添加驅(qū)動(dòng)程序源代碼,這涉及到以下幾個(gè)方面。
        (1)、從網(wǎng)上下載了cs8900.c和cs8900.h兩個(gè)針對2.6.7的內(nèi)核的驅(qū)動(dòng)程序源代碼,將其放在drivers/net/arm/目錄下面。
      #cp cs8900.c ./drivers/net/arm/
      #cp cs8900.h ./drivers/net/arm/
      并在cs8900_probe()函數(shù)中,memset (&priv,0,sizeof (cs8900_t));函數(shù)之后添加如下兩條語句:
      __raw_writel(0x2211d110,S3C2410_BWSCON);
      __raw_writel(0x1f7c,S3C2410_BANKCON3);
      注:其原因在"第二部分"解釋。

        (2)、修改drivers/net/arm/目錄下的Kconfig文件,在添加如下內(nèi)容:
      Config ARM_CS8900
      tristate "CS8900 support"
      depends on NET_ETHERNET && ARM && ARCH_SMDK2410
      help
      Support for CS8900A chipset based Ethernet cards. If you have a network (Ethernet) card of this type, say Y and read the Ethernet-HOWTO, available from as well as .
      To compile this driver as a module, choose M here and read
      . The module will be
      called cs8900.o.
      注:內(nèi)核系統(tǒng)配置文件由2.4版本的config.in變成了2.6版本Kconfig文件,在這個(gè)文件里面添加如上內(nèi)容,則在運(yùn)行make menuconfig或者make xconfig命令的時(shí)候就會(huì)出現(xiàn):
      [ ] CS8900 support
      這一選項(xiàng)。

        (3)、修改drivers/net/arm/目錄下的Makefile文件,在添加如下內(nèi)容:
      obj-$(CONFIG_ARM_CS8900) += cs8900.o
      注:2.6版本內(nèi)核的Makefile文件也與2.4版本的有所不同。添加以上語句,就會(huì)使內(nèi)核在編譯的時(shí)候根據(jù)配置將cs8900A的驅(qū)動(dòng)程序以模塊或靜態(tài)的方式編譯到內(nèi)核當(dāng)中。

        (4)、在/arch/arm/mach-s3c2410/mach-smdk2410.c文件中,找到smdk2410_iodesc[]結(jié)構(gòu)數(shù)組,添加如下如下內(nèi)容:{vSMDK2410_ETH_IO, 0x19000000, SZ_1M, MT_DEVICE}
      修改之后變成了:
      static struct map_desc smdk2410_iodesc[] __initdata = {
      /* nothing here yet */
      /* Map the ethernet controller CS8900A */ {vSMDK2410_ETH_IO, 0x19000000, SZ_1M, MT_DEVICE}
      };
      注:由于在驅(qū)動(dòng)程序的開發(fā)的時(shí)候,在驅(qū)動(dòng)程序當(dāng)中所用到的跟設(shè)備有關(guān)的地址都是虛擬地址,也就是說驅(qū)動(dòng)程序操作的都是虛擬地址,那么要使驅(qū)動(dòng)程序?qū)υO(shè)備的操作反映到設(shè)備上去,就得將設(shè)備的物理地址映射到正確的虛擬地址上去,從而保證驅(qū)動(dòng)程序?qū)μ摂M地址的操作也就是對相應(yīng)的物理地址操作。以上添加的語句就是為了將網(wǎng)卡的物理地址(0x19000000)映射到vSMDK2410_ETH_IO所指向的虛擬地址上去,上面的結(jié)構(gòu)還定義了網(wǎng)卡虛擬地址所占用的區(qū)間,也就是從vSMDK2410_ETH_IO開始的SZ_1M大小的去間,并指定了該區(qū)間所指向的域(的屬性)。(疑問:在本開發(fā)板上,網(wǎng)卡占用的是CPU的nGCS3片選信號,也就是在Bank3,根據(jù)處理器的地址空間定義,這個(gè)地址應(yīng)該是0x18000000,為什么這里使用的是0x19000000?查找到2.4.18的內(nèi)核當(dāng)中,也是用0x19000000來進(jìn)行映射。)

        (5)、在include/asm-arm/arch-s3c2410/目錄下創(chuàng)建smdk2410.h文件,其內(nèi)容為:
      #ifndef _INCLUDE_SMDK2410_H_
      #define _INCLUDE_SMDK2410_H_
      #include
      #define pSMDK2410_ETH_IO 0x19000000
      #define vSMDK2410_ETH_IO 0xE0000000
      #define SMDK2410_ETH_IRQ IRQ_EINT9
      #endif // _INCLUDE_SMDK2410_H_
      注:因?yàn)樵诰W(wǎng)卡驅(qū)動(dòng)程序當(dāng)中,用到了一些常量,所以特意在此添加這個(gè)頭文件。這個(gè)頭文件定義了網(wǎng)卡的物理地址、虛擬地址以及網(wǎng)卡占用的中斷線。

      四、配置、編譯內(nèi)核。在內(nèi)核頂層目錄當(dāng)中鍵入:
      #make smdk2410_defconfig
      由于2.6的內(nèi)核默認(rèn)就支持了S3C2410,所以就有一個(gè)默認(rèn)的內(nèi)核配置文件。里面只是包括了一個(gè)簡單的配置,要使網(wǎng)卡編譯進(jìn)內(nèi)核,還要進(jìn)行手工配置。
      #make menuconfig
      Networking support --->
      Ethernet (10 or 100Mbit) --->
      [*] CS8900 support
      將剛才添加的網(wǎng)卡驅(qū)動(dòng)程序靜態(tài)添加到內(nèi)核當(dāng)中。
      進(jìn)行內(nèi)核編譯。
      #make
      然后將鏡像下載到開發(fā)板中去。

      第二部分 問題解析
      在移植網(wǎng)卡的過程中,并不是一帆風(fēng)順的,整個(gè)過程遇到了問題雖然不多,但是去尋找問題的原因及解決的辦法的時(shí)候卻是非常曲折的。現(xiàn)在將本人在進(jìn)行網(wǎng)卡驅(qū)動(dòng)移植過程中所遇到的問題以及解決方法介紹如下。
      因?yàn)榻?jīng)驗(yàn)不足,剛開始進(jìn)行工作的時(shí)候,沒有將移植的思路明確。是打算將開發(fā)板供應(yīng)商隨板提供的2.4.18內(nèi)核下的驅(qū)動(dòng)程序cs8900a.c移植到2.6.10的內(nèi)核下。首先就是計(jì)劃先以編譯模塊的方式將該程序編譯通過之后,再將起編譯到2.6.10的內(nèi)核當(dāng)中,然后再對其進(jìn)行邏輯上的修改。在模塊編譯該驅(qū)動(dòng)程序的時(shí)候,首先碰到的問題就是頭文件的問題,根據(jù)編譯的出錯(cuò)信息,挨個(gè)將頭文件添加好了。此時(shí)碰到的問題就是交叉編譯器(arm-s3c2410-linux-gnu-gcc)編譯到cs89x0_probe()函數(shù)的時(shí)候出錯(cuò)。指向:BWSCON這一行,出錯(cuò)信息是:
      Incorrect Lvalue in assignment
      后來查閱內(nèi)核源代碼,跟蹤BWSCON的定義,其實(shí)它是指向一個(gè)常量地址的指針。在用2.95.3的交叉編譯器對其進(jìn)行編譯的時(shí)候不會(huì)出錯(cuò),而用3.3.4的交叉編譯器進(jìn)行便宜的時(shí)候卻出錯(cuò),于是懷疑是跟編譯器有關(guān)。將對BWSCON和BANKCON3的賦值操作這兩條語句注釋掉之后就不會(huì)報(bào)錯(cuò),所以肯定了在3.3.4版本的交叉編譯器不支持這樣的操作。原來以為這兩條語句是對別的某個(gè)寄存器進(jìn)行的操作,對網(wǎng)卡驅(qū)動(dòng)沒什么影響,于是就將注釋之后的驅(qū)動(dòng)程序加入到2.6.10的內(nèi)核當(dāng)中進(jìn)行編譯,并下載到開發(fā)板當(dāng)中。這個(gè)時(shí)候從串口打回控制臺的出錯(cuò)消息是在很長時(shí)間內(nèi)都無法解決的。如下:
      Cirrus Logic CS8900A driver for Linux (Modified for SMDK2410)
      eth0: incorrect signature 0x1005
      mice: PS/2 mouse device common for all mice
      NET: Registered protocol family 2
      IP: routing cache hash table of 512 buckets, 4Kbytes
      TCP established hash table entries: 4096 (order: 3, 32768 bytes)
      TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
      TCP: Hash tables configured (established 4096 bind 4096)
      NET: Registered protocol family 1
      IP-Config: Device `eth0' not found.
      Looking up port of RPC 100003/2 on 192.168.0.1
      RPC: sendmsg returned error 101
      portmap: RPC call returned error 101
      Root-NFS: Unable to get nfsd port number from server, using default
      Looking up port of RPC 100005/1 on 192.168.0.1
      RPC: sendmsg returned error 101
      portmap: RPC call returned error 101
      Root-NFS: Unable to get mountd port number from server, using default RPC: sendmsg returned error 101
      mount: RPC call returned error 101
      Root-NFS: Server returned error -101 while mounting /friendly-arm/root
      VFS: Unable to mount root fs via NFS, trying floppy.
      VFS: Cannot open root device "nfs" or unknown-block(2,0)
      Please append a correct "root=" boot option
      Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(2,0)
      觀察串口打印的信息,發(fā)現(xiàn)vivi正確啟動(dòng)了內(nèi)核,內(nèi)核也對cpu進(jìn)行了初始化,但是網(wǎng)卡就是無法驅(qū)動(dòng)起來。核對驅(qū)動(dòng)程序源代碼,發(fā)現(xiàn)在內(nèi)核初始化網(wǎng)卡時(shí),運(yùn)行到了cs89x0_probe1()函數(shù)的時(shí)候,探測網(wǎng)卡的ProductID的時(shí)候讀回的數(shù)據(jù)不是網(wǎng)卡的ID:0x630e。也就是沒探測到網(wǎng)卡而退出了cs89x0_probe1()函數(shù)。當(dāng)時(shí)懷疑的是2.4.18的驅(qū)動(dòng)程序跟2.6.10的設(shè)備驅(qū)動(dòng)程序?qū)懛ㄓ泻芏嗖煌绻^續(xù)這樣的工作,也許工作量很大,所以馬上轉(zhuǎn)變了工作思路,決定從網(wǎng)上下載2.6的CS8900A的驅(qū)動(dòng)程序,在搜索了很長時(shí)間之后,終于在一個(gè)網(wǎng)站上下載到了2.6.7內(nèi)核下的CS8900A的驅(qū)動(dòng)程序。按照"部分"的步驟加進(jìn)了驅(qū)動(dòng)之后,下載新的內(nèi)核,串口回傳的信息跟上面的信息是一樣的。
      重新啟動(dòng)開發(fā)板,問題依然存在,但是仔細(xì)對比了cs89x0_probe1()函數(shù)讀回來的數(shù)據(jù),發(fā)現(xiàn)這個(gè)signature在變化,而且沒有找到其變化的規(guī)律。
      查看了驅(qū)動(dòng)程序以及CS8900A的Datasheet,發(fā)現(xiàn)驅(qū)動(dòng)程序的邏輯是正確的,于是首先懷疑是在驅(qū)動(dòng)程序中,網(wǎng)卡iobase的物理地址不對,于是查看開發(fā)板的原理圖,發(fā)現(xiàn)網(wǎng)卡用的是cpu的nGCS3片選信號,該片選信號對應(yīng)的地址空間起始地址是0x18000000,而在驅(qū)動(dòng)中對用的是0x19000000,于是修改arch/arm/mach-s3c2410/mach-smdk2410.c文件中的mdk2410_iodesc[]結(jié)構(gòu)對io地址的映射,將物理地址改為0x18000000,重新編譯后網(wǎng)卡仍然無法被驅(qū)動(dòng),只是這個(gè)時(shí)候驅(qū)動(dòng)程序讀來的數(shù)據(jù)也就是那個(gè)signature不會(huì)因?yàn)槊看沃仄鸲淖兊模簿褪敲看巫x回來的數(shù)據(jù)都是固定的。這時(shí)又懷疑是虛擬地址不正確。將2.6的驅(qū)動(dòng)與2.4的驅(qū)動(dòng)進(jìn)行了比較,發(fā)現(xiàn)2.4用的 虛擬地址是0xd000000,于是修改2.6內(nèi)核中的虛擬地址為0xe000000,可是網(wǎng)卡還是無法驅(qū)動(dòng),反復(fù)修改了虛擬地址和物理地址,問題依舊存在。這個(gè)時(shí)候思路幾乎停止。經(jīng)過思考之后,把工作的思路定位在比較2.4和2.6的驅(qū)動(dòng)程序的區(qū)別上,經(jīng)過仔細(xì)的比較,發(fā)現(xiàn)在2.4的驅(qū)動(dòng)程序當(dāng)中在cs89x0_probe1()函數(shù)里有對寄存器的設(shè)置,而2.6的驅(qū)動(dòng)程序則沒有,查找cpu的Datasheet,發(fā)現(xiàn)該設(shè)置是對cpu內(nèi)部兩個(gè)重要的控制器的設(shè)置。下面先介紹一下這兩個(gè)寄存器。
      在S3C2410X中BWSCON是Bus width & wait control register(總線寬度及等待控制寄存器),這個(gè)寄存器控制著系統(tǒng)地址空間內(nèi)(包括bank0-bank7)的總線數(shù)據(jù)寬度以及是否等待。BANKCONn(n=0~7)寄存器是Bank control register。這個(gè)寄存器控制著處于某個(gè)bank區(qū)間內(nèi)的總線的地址setup的時(shí)鐘周期,片選信號的保持時(shí)間,訪問周期等。這個(gè)兩個(gè)寄存器中每個(gè)位的含義可以參見S3C2410X數(shù)據(jù)手冊的5-13~5-15,在此不加以詳敘。
      查看了cpu的數(shù)據(jù)手冊、開發(fā)板原理圖以及2.4的驅(qū)動(dòng)程序之后,發(fā)現(xiàn)在2.4的驅(qū)動(dòng)程序中的以下兩條語句:
      BWSCON = (BWSCON & ~(BWSCON_ST3 | BWSCON_WS3 | BWSCON_DW3)) | (BWSCON_ST3 | BWSCON_WS3 | WSCON_DW(3, BWSCON_DW_16));
      BANKCON3= BANKCON_Tacs0 | BANKCON_Tcos4 | BANKCON_Tacc14 | BANKCON_Toch1 | BANKCON_Tcah4 | BANKCON_Tacp6 | BANKCON_PMC1;
      實(shí)際上是對地址區(qū)間BANK3(因?yàn)殚_發(fā)板用的的是nGCS3,處于BANKCON3區(qū)間內(nèi))進(jìn)行了設(shè)置。
      先看對BWSCON的設(shè)置,這條語句實(shí)際上是要使BWSCON中除了ST3、WS3和DW3這四個(gè)位的其它各位得到保護(hù),使ST3、WS3和DW3這四個(gè)位清零,然后再對ST3、WS3和DW3這四個(gè)位進(jìn)行設(shè)置,經(jīng)過這條語句之后,ST3、WS3和DW3這四個(gè)位被設(shè)置成了1101(二進(jìn)制),意思就是對BANK3采用cpu引腳(A17、B16、C15、A16,這幾個(gè)引腳都分別有三種信號表示意義)的nBE信號(具體什么意思,本人也不知道),對BANK3使用WAIT enable,使用16位的數(shù)據(jù)總線寬度。
      其次就是對BANKCON3寄存器的設(shè)置。這條語句將BANKCON3設(shè)置成了0001 1111 0111 1100。(各個(gè)位的意思,我也沒弄明白什么意思,估計(jì)就是設(shè)置各種操作的時(shí)鐘周期數(shù)目。)
      清楚了驅(qū)動(dòng)程序?qū)拇嫫鞯脑O(shè)置之后,就想到應(yīng)該在vivi里面對cpu的這幾個(gè)內(nèi)存控制寄存器進(jìn)行設(shè)置,于是找到vivi源代碼中include/platform/目錄下的smdk.h文件中對寄存器的初始化值的設(shè)置,修改之后如下:
      /*#define vBWSCON 0x22111120*/
      #define vBWSCON 0x2211d110
      #define vBANKCON0 0x00000700
      #define vBANKCON1 0x00000700
      #define vBANKCON2 0x00000700
      #define vBANKCON3 0x00001f7c
      #define vBANKCON4 0x00000700
      #define vBANKCON5 0x00001f7c
      #define vBANKCON6 0x00018005
      #define vBANKCON7 0x00018005
      #define vREFRESH 0x008e0459
      #define vBANKSIZE 0xb2
      #define vMRSRB6 0x30
      #define vMRSRB7 0x30

      重新通過JTAG口下載vivi,重新啟動(dòng)內(nèi)核后,發(fā)現(xiàn)問題依然存在,于是就想到在驅(qū)動(dòng)程序里面添加對內(nèi)存控制器的設(shè)置。開始是想模仿2.4的驅(qū)動(dòng)程序那樣,找到各個(gè)相應(yīng)的宏去代替2.4驅(qū)動(dòng)程序里的宏,在memset()函數(shù)之前添加,但是編譯的時(shí)候出錯(cuò),出錯(cuò)信息是:
      LValue incorrect in assignment
      跟蹤內(nèi)核的代碼發(fā)現(xiàn)對S3C2410_BWSCON、S3C2410_BANKCON3宏的定義分別返回的其實(shí)是一個(gè)常量,分別是0xf0100000和0xf0100010,這個(gè)常量是右值,不能當(dāng)左值。因此就想到采用如下直接對地址進(jìn)行賦值的方式對寄存器進(jìn)行設(shè)置:
      *(volatile unsigned short __force *)(0xf0100000)=(0x2211d110);
      *(volatile unsigned short __force *)(0xf0100010)=(0x00001f7c);
      后來運(yùn)行內(nèi)核時(shí)發(fā)現(xiàn),驅(qū)動(dòng)程序初始化到了memset()函數(shù)之后,上述兩條語句之前就停止不動(dòng)了(疑問:不知道這是什么原因)。查找linux內(nèi)核代碼找到了__raw_writell(v,a)這樣一個(gè)函數(shù),于是就將上述兩條語句替換成:
      __raw_writel(0x2211d110,S3C2410_BWSCON);
      __raw_writel(0x1f7c,S3C2410_BANKCON3);
      這樣經(jīng)過設(shè)置內(nèi)存控制寄存器之后,網(wǎng)卡終于被驅(qū)動(dòng)起來了。但是由于在移植的過程中沒有將內(nèi)核對devfs設(shè)備文件系統(tǒng)的支持編譯進(jìn)內(nèi)核里面去,所以當(dāng)網(wǎng)卡驅(qū)動(dòng)之后去尋找網(wǎng)絡(luò)文件系統(tǒng)的時(shí)候發(fā)現(xiàn)找不到根文件系統(tǒng),在配置內(nèi)核的時(shí)候?qū)evfs的支持加入,如下:
      File systems --->
      Pseudo filesystems --->
      [*] /dev file system support (OBSOLETE)
      之后,linux可以從主機(jī)上找到根文件系統(tǒng),并創(chuàng)建init進(jìn)程。這樣,網(wǎng)卡驅(qū)動(dòng)程序經(jīng)過接近三周的時(shí)間終于被驅(qū)動(dòng)了!

      免費(fèi)預(yù)約試聽課

      亚洲另类欧美综合久久图片区_亚洲中文字幕日产无码2020_欧美日本一区二区三区桃色视频_亚洲AⅤ天堂一区二区三区

      
      

      1. 五月婷婷精品免费视频 | 日本中文字幕在线视频 | 网爆热门视频亚洲精品在线观看 | 日韩国产二区不卡在线 | 亚洲一区二区经典在线播放 | 一本色道久久88亚洲精品综合 |