標籤:fs210 dm9000 dm9000原理 嵌入式
dm9000的原理圖如下:
650) this.width=650;" src="http://s3.51cto.com/wyfs02/M00/38/40/wKioL1OzmQGAEEtZAAL59MpEn5M140.jpg" title="Column871.jpg" alt="wKioL1OzmQGAEEtZAAL59MpEn5M140.jpg" />
網卡的移植工作很簡單,首先是需要添加目標版的平台裝置資訊,就可以實現網卡的移植工作,平台裝置資訊如何添加很重要
添加平台資訊的第一步是添加一個platform_device裝置資訊
首先在arch/arm/mach-s5pv210/mach-smdkv210.c
添加標頭檔:
#include <linux/dm9000.h>
#include <linux/irq.h>
添加platform_device平台裝置資訊
struct platform_device {
const char * name; // 平台裝置名稱
int id; // 裝置的ID 如果是唯一裝置,ID = -1,如果裝置不是唯一的,ID = 0,1,2,3,4,5
struct device dev; //
u32 num_resources; //所擁有資源結構體的個數
struct resource * resource; //資源結構體指標
const struct platform_device_id *id_entry;
struct pdev_archdata archdata;
};
例如:
static struct platform_device s5pc100_device_dm9000 = {
.name = "dm9000",
.id = -1,
.num_resources = ARRAY_SIZE(dm9000_resources),
.resource = dm9000_resources,
.dev = {
. platform_data = &s5pc100_dm9000_platdata,
}
};
struct device 在 include/linux/device.h中的platform_data只是一個指標,可以傳送一個地址
用這個地址可以給驅動傳動一些特殊的資料,對於dm9000這個網卡晶片需要傳送dm9000_plat_data
在網卡驅動中使用了如下的定義: struct dm9000_plat_data *pdata = pdev->dev.platform_data;
因此我們要傳遞這個這個platform_data結構體,結構體的定義如下:
/* platform data for platform device structure‘s platform_data field */
struct dm9000_plat_data {
unsigned int flags;
unsigned char dev_addr[6]; // 網卡的mac地址 ,可以不寫,如果不寫的話,是隨機產生一個
/* allow replacement IO routines */
void (*inblk)(void __iomem *reg, void *data, int len);
void (*outblk)(void __iomem *reg, void *data, int len);
void (*dumpblk)(void __iomem *reg, int len);
};
這個是網卡驅動使用的結構體
flags = DM9000_PLATF_16BITONLY, 表示dm9000工作在16位的模式下
在這個檔案中定義 include/linux/dm9000.h
/* IO control flags */
#define DM9000_PLATF_8BITONLY (0x0001)
#define DM9000_PLATF_16BITONLY (0x0002)
#define DM9000_PLATF_32BITONLY (0x0004)
#define DM9000_PLATF_EXT_PHY (0x0008)
#define DM9000_PLATF_NO_EEPROM (0x0010)
#define DM9000_PLATF_SIMPLE_PHY (0x0020) /* Use NSR to find LinkStatus */
dev_addr是網卡的mac地址,
.dev_addr[0] = 0x00,
.dev_addr[1] = 0x00,
.dev_addr[2] = 0x3e,
.dev_addr[3] = 0x26,
.dev_addr[4] = 0x0a,
.dev_addr[5] = 0x00,
例如:.dev = {
.platform_data = & s5pc100_dm9000_plat data, //表示驅動中要用的資料
}
struct resource {
resource_size_t start; // 表示資源的開始值
resource_size_t end; // 表示資源的結束值
const char *name;
unsigned long flags; // 資源的類型
struct resource *parent, *sibling, *child;
};
我們一般只關心這3個欄位 start ,end ,flags
flags:
/*
* IO resources have these defined flags.
*/
#define IORESOURCE_BITS 0x000000ff /* Bus-specific bits */
#define IORESOURCE_TYPE_BITS 0x00001f00 /* Resource type */
#define IORESOURCE_IO 0x00000100
#define IORESOURCE_MEM 0x00000200 //記憶體資源
#define IORESOURCE_IRQ 0x00000400 //中斷資源
#define IORESOURCE_DMA 0x00000800
#define IORESOURCE_BUS 0x00001000
因為在驅動中使用了如下的函數:
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
db->irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
因此我們必須要對成員設定如下:
static struct resource dm9000_resources[] = {
[0] = {
.start = 0x88000000,
.end = 0x88000000+0x3,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0x88000000+0x4,
.end = 0x88000000+0x4+0x3,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = IRQ_EINT(10),
.end = IRQ_EINT(10),
.flags = IORESOURCE_IRQ|IRQ_TYPE_LEVEL_HIGH,
},
};
為什麼驅動要這樣設定呢?
因為網卡dm9000這個裝置有一個介面, 是dm9000的cmd引腳, 如果cmd = 0 表示的是地址, cmd=1 表示的資料
cmd這個引腳接到了addr2 ,接到了地址匯流排, 也就是說我們只需要對addr2的地址產生影響就可以了,因此addr2 =0 表示是index是地址,
addr2 =1 表示對index索引指向的寄存器的內的值data ,因此我們只需要對這兩個寄存器設定就可以實現網卡的驅動.
int platform_device_register(struct platform_device *pdev); //註冊一個裝置
int platform_add_devices(struct platform_device **pdevs, int ndev); //註冊多個裝置
pdevs: platform_device類型的指標
ndev : 一共有多少個裝置
本文出自 “嵌入式學習天地” 部落格,請務必保留此出處http://farsight.blog.51cto.com/1821374/1433472