先提个问题:看到有的网卡是连在ISA总线或者是PCI总线上的,那在mini2440上dm9000和CPU是直接相连的,这个算是什么总线? 没弄明白这个问题


首先是平台设备的register和unregister. 


static int __init

dm9000_init(void)

{

#if defined(CONFIG_ARCH_S3C2410)

unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON;

unsigned int oldval_bankcon4 = *(volatile unsigned int *)S3C2410_BANKCON4;

*((volatile unsigned int *)S3C2410_BWSCON) =

(oldval_bwscon & ~(3<<16)) | S3C2410_BWSCON_DW4_16 | S3C2410_BWSCON_WS4 | S3C2410_BWSCON_ST4;

*((volatile unsigned int *)S3C2410_BANKCON4) = 0x1f7c;

#endif

printk(KERN_INFO "%s Ethernet Driver, V%sn", CARDNAME, DRV_VERSION);

 

return platform_driver_register(&dm9000_driver);

}

 

static void __exit

dm9000_cleanup(void)

{

platform_driver_unregister(&dm9000_driver);

}

dm9000_init中,#if defined 中间的内容是什么意思我不清楚。以上两个函数就是平台设备的注册和取消。


一、下面分析dm9000_probe函数,这个是平台设备主要的初始化函数


/*

 * Search DM9000 board, allocate space and register it

 */

static int __devinit

dm9000_probe(struct platform_device *pdev)

{

struct dm9000_plat_data *pdata = pdev->dev.platform_data;

struct board_info *db; /* Point a board information structure */

struct net_device *ndev;

const unsigned char *mac_src;

int ret = 0;

int iosize;

int i;

u32 id_val;

 

/* Init network device */

ndev = alloc_etherdev(sizeof(struct board_info));

if (!ndev) {

dev_err(&pdev->dev, "could not allocate device.n");

return -ENOMEM;

}

 

SET_NETDEV_DEV(ndev, &pdev->dev);

 

dev_dbg(&pdev->dev, "dm9000_probe()n");

 

/* setup board info structure */

db = netdev_priv(ndev);

 

db->dev = &pdev->dev;

db->ndev = ndev;

 

spin_lock_init(&db->lock);

mutex_init(&db->addr_lock);

 

INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);

 

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);

 

if (db->addr_res == NULL || db->data_res == NULL ||

    db->irq_res == NULL) {

dev_err(db->dev, "insufficient resourcesn");

ret = -ENOENT;

goto out;

}

 

iosize = resource_size(db->addr_res);

db->addr_req = request_mem_region(db->addr_res->start, iosize,

  pdev->name);

 

if (db->addr_req == NULL) {

dev_err(db->dev, "cannot claim address reg arean");

ret = -EIO;

goto out;

}

 

db->io_addr = ioremap(db->addr_res->start, iosize);

 

if (db->io_addr == NULL) {

dev_err(db->dev, "failed to ioremap address regn");

ret = -EINVAL;

goto out;

}

 

iosize = resource_size(db->data_res);

db->data_req = request_mem_region(db->data_res->start, iosize,

  pdev->name);

 

if (db->data_req == NULL) {

dev_err(db->dev, "cannot claim data reg arean");

ret = -EIO;

goto out;

}

 

db->io_data = ioremap(db->data_res->start, iosize);

 

if (db->io_data == NULL) {

dev_err(db->dev, "failed to ioremap data regn");

ret = -EINVAL;

goto out;

}

 

/* fill in parameters for net-dev structure */

ndev->base_addr = (unsigned long)db->io_addr;

ndev->irq = db->irq_res->start;

 

/* ensure at least we have a default set of IO routines */

dm9000_set_io(db, iosize);

 

/* check to see if anything is being over-ridden */

if (pdata != NULL) {

/* check to see if the driver wants to over-ride the

* default IO width */

 

if (pdata->flags & DM9000_PLATF_8BITONLY)

dm9000_set_io(db, 1);

 

if (pdata->flags & DM9000_PLATF_16BITONLY)

dm9000_set_io(db, 2);

 

if (pdata->flags & DM9000_PLATF_32BITONLY)

dm9000_set_io(db, 4);

 

/* check to see if there are any IO routine

* over-rides */

 

if (pdata->inblk != NULL)

db->inblk = pdata->inblk;

 

if (pdata->outblk != NULL)

db->outblk = pdata->outblk;

 

if (pdata->dumpblk != NULL)

db->dumpblk = pdata->dumpblk;

 

db->flags = pdata->flags;

}

 

#ifdef CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL

db->flags |= DM9000_PLATF_SIMPLE_PHY;

#endif

 

dm9000_reset(db);

 

/* try multiple times, DM9000 sometimes gets the read wrong */

for (i = 0; i < 8; i++) {

id_val  = ior(db, DM9000_VIDL);

id_val |= (u32)ior(db, DM9000_VIDH) << 8;

id_val |= (u32)ior(db, DM9000_PIDL) << 16;

id_val |= (u32)ior(db, DM9000_PIDH) << 24;

 

if (id_val == DM9000_ID)

break;

dev_err(db->dev, "read wrong id 0x%08xn", id_val);

}

 

if (id_val != DM9000_ID) {

dev_err(db->dev, "wrong id: 0x%08xn", id_val);

ret = -ENODEV;

goto out;

}

 

/* Identify what type of DM9000 we are working on */

 

id_val = ior(db, DM9000_CHIPR);

dev_dbg(db->dev, "dm9000 revision 0x%02xn", id_val);

 

switch (id_val) {

case CHIPR_DM9000A:

db->type = TYPE_DM9000A;

break;

case CHIPR_DM9000B:

db->type = TYPE_DM9000B;

break;

default:

dev_dbg(db->dev, "ID %02x => defaulting to DM9000En", id_val);

db->type = TYPE_DM9000E;

}

 

/* dm9000a/b are capable of hardware checksum offload */

if (db->type == TYPE_DM9000A || db->type == TYPE_DM9000B) {

db->can_csum = 1;

db->rx_csum = 1;

ndev->features |= NETIF_F_IP_CSUM;

}

 

/* from this point we assume that we have found a DM9000 */

 

/* driver system function */

ether_setup(ndev);

 

ndev->netdev_ops = &dm9000_netdev_ops;

ndev->watchdog_timeo = msecs_to_jiffies(watchdog);

ndev->ethtool_ops = &dm9000_ethtool_ops;

 

// db->msg_enable       = NETIF_MSG_LINK;

db->msg_enable       = 0xffff;

db->mii.phy_id_mask  = 0x1f;

db->mii.reg_num_mask = 0x1f;

db->mii.force_media  = 0;

db->mii.full_duplex  = 0;

db->mii.dev      = ndev;

db->mii.mdio_read    = dm9000_phy_read;

db->mii.mdio_write   = dm9000_phy_write;

 

mac_src = "eeprom";

 

/* try reading the node address from the attached EEPROM */

for (i = 0; i < 6; i += 2)

dm9000_read_eeprom(db, i / 2, ndev->dev_addr+i);

 

if (!is_valid_ether_addr(ndev->dev_addr) && pdata != NULL) {

mac_src = "platform data";

memcpy(ndev->dev_addr, pdata->dev_addr, 6);

}

 

if (!is_valid_ether_addr(ndev->dev_addr)) {

/* try reading from mac */

mac_src = "chip";

for (i = 0; i < 6; i++)

ndev->dev_addr[i] = ior(db, i+DM9000_PAR);

}

 

memcpy(ndev->dev_addr, "x08x90x90x90x90x90", 6);

 

if (!is_valid_ether_addr(ndev->dev_addr))

dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "

"set using ifconfign", ndev->name);

 

platform_set_drvdata(pdev, ndev);

ret = register_netdev(ndev);

 

if (ret == 0)

printk(KERN_INFO "%s: dm9000%c at %p,%p IRQ %d MAC: %pM (%s)n",

       ndev->name, dm9000_type_to_char(db->type),

       db->io_addr, db->io_data, ndev->irq,

       ndev->dev_addr, mac_src);

return 0;

 

out:

dev_err(db->dev, "not found (%d).n", ret);

 

dm9000_release_board(pdev, db);

free_netdev(ndev);

 

return ret;

}

上面这段代码中, 有几个地方说明一下:


1.  struct dm9000_plat_data *pdata = pdev->dev.platform_data;这个 pdata得到的内容是在文件   arch/arm/mach-s3c2440/mach-mini2440.c 中定义的,定义如下


/* DM9000AEP 10/100 ethernet controller */

#define MACH_MINI2440_DM9K_BASE (S3C2410_CS4 + 0x300)

 

static struct resource mini2440_dm9k_resource[] = {

        [0] = {

                .start = MACH_MINI2440_DM9K_BASE,

                .end   = MACH_MINI2440_DM9K_BASE + 3,

                .flags = IORESOURCE_MEM

        },

        [1] = {

                .start = MACH_MINI2440_DM9K_BASE + 4,

                .end   = MACH_MINI2440_DM9K_BASE + 7,

                .flags = IORESOURCE_MEM

        },

        [2] = {

                .start = IRQ_EINT7,

                .end   = IRQ_EINT7,

                .flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,

        }

};

 

/*

 *  * The DM9000 has no eeprom, and it's MAC address is set by

 *   * the bootloader before starting the kernel.

 *    */

static struct dm9000_plat_data mini2440_dm9k_pdata = {

        .flags          = (DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM),

};

 

static struct platform_device mini2440_device_eth = {

        .name           = "dm9000",

        .id             = -1,

        .num_resources  = ARRAY_SIZE(mini2440_dm9k_resource),

        .resource       = mini2440_dm9k_resource,

        .dev            = {

                .platform_data  = &mini2440_dm9k_pdata,

        },

};


从上面的27行,就可以知道pdata的值是什么。驱动移植时,一般就是修改mach-mini2440.c这个文件,当然也有些版本将dm9000的resource包含在文件 archarmplat-s3c24xx这个文件中,我觉得这两个文件应该是特殊与一般的关系,最通用的resource就定义在plat-s3c24xx文件中,而因开发板各异的resource就包含在mach-mini2440.c文件中。


2.  probe函数第23行中, SET_NETDEV_DEV(ndev, &pdev->dev)  这个宏展开之后, /* Set the sysfs physical device reference for the network logical device * if set prior to registration will cause a symlink during initialization. */#define SET_NETDEV_DEV(net, pdev) ((net)->dev.parent = (pdev))应该是与sysfs有关,但是目前不是很理解这句话的作用。当把这句话去掉之后,驱动是可以正常运行的,唯一的区别是去掉之后,目录/sys/devices/platform/dm9000/net 将不存在。sysfs的用法还没有彻底弄明白。

[1] [2]
关键字:mini2440  dm9000  驱动分析 引用地址:mini2440上dm9000驱动分析(一)

上一篇:mini2440上dm9000驱动分析(二)
下一篇:S3C2440上MMC/SD卡驱动分析(二)

推荐阅读

集微网消息 10月24日晚间,手机ODM龙头闻泰科技发布预案,计划通过发行股份及支付现金与募集配套资金的方式收购安世集团所有GP和LP份额,交易完成后,闻泰科技将间接持有安世集团的控制权。安世集团为半导体标准器件供应商,前身为恩智浦标准产品事业部,集设计、制造、封装测试于一体,其产品广泛应用于汽车、工业控制、计算机、消费电子等领域。安世集...
在STM32开发过程中必然需要串口打印参与调试,而往往STM32调试分配串口不会固定,可能是在串口1,也有可能为串口2。该如何对printf进行重新映射串口呢?只需要在生成的工程代码中添加如下代码:#include "stdio.h"#ifdef __GNUC__#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)#else#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *...
一加Nord N10 5G的价格预计将低于原始 Nord,该机预计将于10月26日与一加 Nord N100一同在美国推出。一加Nord N10 5G曝光:骁龙690处理器+90Hz刷新率一加 Nord N10 5G 配备了6.49英寸 FHD+ 显示屏,刷新率为90Hz。这款手机搭载高通骁龙690芯片,配备6GB RAM 和128GB 存储空间,内置4300mAh 电池,但是还没有关于快充的消息。其他方面,一...
RS-485通信常用于工业控制、电力通信和智能仪表等领域。该通信方式主要具备以下5种能力:①适应复杂施工现场②抗电磁干扰③联网④较远的传输距离⑤允许多个收发设备连接到同一总线RS-485具备以下特点:❶采用差分信号。可抑制共模干扰。RS-485采用2条通信线,通常用A和B或D+和D-来表示。逻辑‘1’,表示为两线间电压差为+(0.26)V,逻辑‘0’,表示为两线...

史海拾趣

问答坊 | AI 解惑

Protel 99从入门到精通教程(上)

送给大家一本比较完美的99教程 中册:https://bbs.eeworld.com.cn/thread-52306-1-4.html 下册:https://bbs.eeworld.com.cn/thread-52318-1-8.html …

查看全部问答∨

中国将于2010年推出千万亿次超级计算机

本帖最后由 jameswangsynnex 于 2015-3-3 20:00 编辑 曙光信息产业有限公司总裁历军日前在曙光天津产业基地接受新华社记者采访时表示,2010年,曙光将推出基于“龙芯四号”处理器的千万亿次高性能服务器“曙光6000”超级计算机。   200 ...…

查看全部问答∨

【藏书阁】谐波抑制和无功功率补偿

     抑制谐波和提高功率因数是涉及电力电子技术、电气自动化技术和电力系统的一个重大课题。随着电力电子技术的不断进步,新型有源谐波抑制技术和无功补偿技术得到了迅速的发展。本书主要介绍有源电力滤波器、混合型电力滤波器 ...…

查看全部问答∨

各种复位IC的介绍及复位电路的设计(周工强悍资料)

对于单片机系统来说,复位电路应该是最为最要的一个环节。往往被很多人忽略,因为一般简单的复位电路在开发试验阶段是没有问题的,只有在工作环境中才容易出现问题。所以在此推荐这份资料希望大家重视,复位IC并不会增加太多成本,但是更有保障。 ...…

查看全部问答∨

CE50的GWES组件有没公开源码?LCD驱动里面的触摸屏坐标(已经知道怎么修正它了)怎么转成系统的坐标?这两个之间的转换关系是?

CE50的GWES组件有没公开源码?LCD驱动里面的触摸屏坐标(已经知道怎么修正它了)怎么转成系统的坐标?这两个之间的转换关系是?…

查看全部问答∨

晶震频率从哪可以看到?

请问在keil c的"Option for target"选项中的"taget选项卡",有项叫xtal(晶震频率)的,我在教程中看到,编译代码前我们要在这里改成跟我们单片机相同的效率才行,但是我怎么知道我的51板子的晶震频率是多少呢?可以从板子或芯片中的某个地方看到 ...…

查看全部问答∨

Arm中分散加载文件的问题??

我想将定义的一个const型的数组村到固定的flash地址如0x00006000; 怎么实现啊。我用的是2132…

查看全部问答∨

程序烧入FLASH 复位不能运行的问题?

本帖最后由 dontium 于 2015-1-23 13:31 编辑 看看论坛,好象很多战友都遇到了这个问题,不知道大家是怎么解决的, 我遇到的问题是这样的,我用汇编编写了一个小程序,小于1K,作用是把GPIO拉高, 在调试时候运行正确,烧入FLASH中的数据,对应 ...…

查看全部问答∨

自恢复保险丝(PPTC)的保护功能在LED技术中在此大展身手

自恢复保险丝(PPTC)的保护功能在LED技术中在此大展身手   自恢复保险丝(PPTC)全称聚合物正温度系数器件(PolymerPositiveTemperatureCoefficients),它的工作情况类似一个开关,故障出现时,自恢复保险丝(PPTC)变热、电阻增加,从而保 ...…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved