历史上的今天

今天是:2024年10月25日(星期五)

正在发生

2021年10月25日 | mini2440上dm9000驱动分析(一)

发布者:qpb1234 来源: eefocus关键字:mini2440  dm9000  驱动分析 手机看文章 扫描二维码
随时随地手机看文章

先提个问题:看到有的网卡是连在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卡驱动分析(二)

推荐阅读

中芯国际关于近日不实报道的声明对于近日有媒体发文和转载称,传中芯国际联合首席执行官梁孟松博士将离开公司,中芯国际郑重声明:该消息绝非属实。任何中芯国际最高管理层人事变动,以公司发布公告为准。对于杜撰及传播谣言的媒体以及个人,公司表示强烈谴责,将保留诉诸法律追责的权力。特此声明。中芯国际集成电路制造有限公司2018年10月24日
“做一辆好车,做一辆获得市场认可、有生命力、有核心竞争力的好车。”这是王云中的职业理想,朴实无华却充满能量。作为东风公司技术中心新能源汽车项目的总师,他长期从事于新能源汽车行业,历经了东风新能源汽车的整个发展过程。从他的讲述中,我们可以清楚地了解那些艰苦却干劲满满的日子。我从1994年就入职了技术中心。2003年因与日产合资,集团对研发...
PS5 即将全面上市,但目前 PS5 只有白色外壳的版本供消费者购买。好在索尼之前确认 PS5 外壳可以轻松地拆开,这也意味着外壳可以替换。日前有第三方正式推出了 PS5 的自定义外壳,已经可以预订。商家 PlateStation5 当前提供五种不同颜色的自定义面板,每套售价 39.99 美元,约 266 元。配有完整的后壳和前壳,这些面板适用于 PlayStation ...
2021年10月*日,中国上海讯——国内EDA、滤波器行业的领军企业芯和半导体,近日在上海成功举办了其2021年全国用户大会。 这场由上海市集成电路行业协会,上海集成电路技术与产业促进中心联合协办的大会,集结了芯和半导体及其生态系统中的众多合作伙伴:中兴通讯、紫光展锐、新思科技、罗德与施瓦茨、微软Azure、概伦电子等企业高层及专家,以“拥抱异构...

史海拾趣

问答坊 | AI 解惑

郁闷PD反向电阻过小,导致APC控制电路失效

2008-7-21        在试做OLT样品时发现两只光器件中有一只无法正常工作,出光但是无法进行调试,APC控制电路失效。上LD测试仪测试一切指标正常。经过分析后发现为器件的PD管反向击穿,电阻值只有4.9k。…

查看全部问答∨

如何控制屏幕切换?

设备从横屏模式切换到竖屏模式, 是怎么控制的? 可不可以自己去控制, 比如说点击确定键, 从横屏到竖屏?…

查看全部问答∨

请人做vxworks下多网卡驱动

  在做一个项目时,遇到这样的问题:设备上有4个PCI网卡,型号为rtl8139,10\\100M,在vxworks下,原来同样的网卡驱动程序在只有一个网卡的另外一台设备上工作正常,更换为4个网卡的设备后,按照书上的方法修改了网络的驱动,添加了对其 ...…

查看全部问答∨

NDIS学习问题 关于《防火墙与网络封包截获技术》里面的xpassthru例子问题

我要做一个基于NDIS的防火墙当作毕设,原来从没有接触过驱动程序的开发,看了看网上说《防火墙与网络封包截获技术》这本书不错就买了,里面有一个叫做xpassthru的例子,但是现在刚看就有一个问题来了,这个例子里面的XFTOWIN.INF xpassthru.inf ...…

查看全部问答∨

谁能修改打印机驱动程序

打印机驱动程序应实现的功能如下: 1.不管我是使用bartender软件还是nicelabel以及labematrix在里面排版好条形码,文字,图片等,装上我特定的打印机驱动程序,在软件里会自动体现我安装的打印机驱动型号,我只要选择它,点击打印就会开始打印任 ...…

查看全部问答∨

求教:如何使用exe文件安装自己编写的USB驱动

RT 制作exe文件来安装USB驱动,请高手指点迷津…

查看全部问答∨

如何存储float和dou××e数据

我在flash里存储dou××e 数据如何存储 我这样写的 void flashw_dou××e(dou××e *data,unsigned int adr) { unsigned char *padr; padr=(unsigned char *)adr; FCTL1=FWKEY+WRT;//开启FLASH写入模式 FCTL3=FWKEY;//解除FLASH LO ...…

查看全部问答∨

USB接口简易频谱分析仪

USB接口简易频谱分析仪,基本原理如下图所示。 [ 本帖最后由 kata 于 2011-7-4 01:31 编辑 ]…

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

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

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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