Linux 2.6内核关于 platform 机制

Linux 2.6起引入了一套新的驱动管理和注册机制:platform_device和platform_driver。Linux中大部分的设备驱动,都可以使用这套机制,设备用platform_device表示,驱动用platform_driver进行注册。Linux 2.6起引入了一套新的驱动管理和注册机制:platform_device和platform_driver。Linux中大部分的设备驱动,都可以使用这套机制,设备用platform_device表示,驱动用platform_driver进行注册。

---------------------------------------引子网友的帖子 ,忘了连接。当时学习的时候看了他的文章

platform_device结构体用来描述设备的名称、资源信息等。

这里分析在dm9000中的platform的调用流程
1、dm9000 的probe 函数中
static int
dm9000_probe(struct platform_device *pdev)
{
struct net_device *ndev;
ndev = alloc_etherdev(sizeof (struct board_info));
/*
 * ether_setup针对以太网卡的的函数,用来填充剩下的函数指针(内核已经实现好的) 
 * 前提是你是以太网卡
 * 会自动填充init函数
 */ 会自动填充 init函数
 ether_setup(ndev);
}
而init的函数定义如下
static int __init
dm9000_init(void)  
{
printk(KERN_INFO "%s Ethernet Driver\n", CARDNAME);
 
/*函数使用的参数看下文*/
return platform_driver_register(& dm9000_drive r); /* search board and register */
}
这里是  platform_driver_register中传入的参数的定义
先了解 数据类型的定义:
struct platform_driver { 
 int (*probe)(struct platform_device *);
 int (*remove)(struct platform_device *);
 void (*shutdown)(struct platform_device *); 
 int (*suspend)(struct platform_device *, pm_message_t state);
 int (*suspend_late)(struct platform_device *, pm_message_t state);
 int (*resume_early)(struct platform_device *);
 int (*resume)(struct platform_device *); 
 struct device_driver driver;   // 在platfrom_driver注册的时候 实际注册的是这个驱动
};
static struct platform_driver dm9000_driver =
 { 
// 说明应该有个设备 名字也应该是dm9000
.driver = { .name = "dm9000", .owner = THIS_MODULE, },
/*
* 认真看会发现  dm9000_probe的参数是  struct platform_device *pdev
* 所以这个probe 函数是由这个机制调用的
  .probe = dm9000_probe,  
.remove = dm9000_drv_remove,
.suspend = dm9000_drv_suspend,
.resume = dm9000_drv_resume,
 };
但是定义驱动之前是不是应该有设备呢 ? 所以还要有设备驱动的定义:

首先先了解下 platfrom 设备是如何定义的:
struct  platform_device
{
 const char * name;  //设备名字 设备的名字,这将代替device->dev_id,用作sys/device下显示的目录名 
 int id;  //用于给插入到该总线并且具有相同name的设备编号,如果只有一个设备的话填-1。 
 struct device dev;  //结构体中内嵌的device结构体。 
 u32 num_resources;  //资源数 
 struct resource * resource; //资源 
    };        
 
// 该变量位于arch/arm/pat-s3c24xx
static struct platform_device s3c_device_dm9k
 .name = "dm9000", 
 .id = 0, 
 .num_resources = ARRAY_SIZE(s3c_dm9k_resource),
 .resource = s3c_dm9k_resource,
 .dev = { 
 .platform_data = &s3c_dm9k_platdata,
 } 
};
    
以上添加了两个变量第一个是 s3c_dm9k_resource   platfrom 机制的变量都有统一的描述。其数据结构我将在下面给出:
static struct  resource  s3c_dm9k_resource[] = 
 [0] = { 
.start = S3C2410_CS4,  /* ADDR2=0,发送地址时使用这个地址 */
.end = S3C2410_CS4 + 3,
.flags = IORESOURCE_MEM,
 },
 [1] = {
 .start = S3C2410_CS4 + 4, /* ADDR2=1,传输数据时使用这个地址 */ 
 .end = S3C2410_CS4 + 4 + 3,
 .flags = IORESOURCE_MEM,
 }, 
 [2] = { 
 .start = IRQ_EINT7,  /* 中断号 */
 .end = IRQ_EINT7, 
 .flags = IORESOURCE_IRQ, 
 } 
 };

static struct  dm9000_plat_data   s3c_dm9k_platdata  = 
.flags = DM9000_PLATF_16BITONLY, //由此可知dm9000使用的是16位的传输模式
 };

struct dm9000_plat_data
 { 
 unsigned int flags; /* 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);
 };
 
2、我们跟着进入 platform_driver_register 函数一看:
其传入的参数为:  struct   platform_driver,   dm9000_driver 并且我们队其中的函数指针做了初始化。(该变量的定义是在 驱动程序里面,所以才可以对使用存在的函数来初始化 paltform_driver变量里面的函数指针)
int platform_driver_register(struct platform_driver *drv)
{
 drv->driver.bus = &platform_bus_type;  //系统实现好的
 if (drv->probe) //probe存在在定义的时候已经初始化了 所以这里是真
  drv->driver.probe = platform_drv_probe;  // 从driver的定义可以里面内嵌了一个device变量
 if (drv->remove)
  drv->driver.remove = platform_drv_remove; 
 if (drv->shutdown) 
  drv->driver.shutdown = platform_drv_shutdown; 
 if (drv->suspend) 
 drv->driver.suspend = platform_drv_suspend; 
 if (drv->resume) 
 drv->driver.resume = platform_drv_resume; 
 return driver_register(&drv->driver);
 }

platform_drv_probe函数代码如下:
static int platform_drv_probe(struct device *_dev) 
/*
#define to_platform_driver(drv) (container_of((drv), struct platform_driver,    driver))
将一般的driver结构体封装或者是获得platform_driver类型的结构体指针,这个显然是根据driver指针算出相应的 * platform_driver指针
*/
 struct platform_driver *drv  = to_platform_driver(_dev->driver);  
 struct platform_device *dev  = to_platform_device(_dev);
 return drv->probe(dev);  //接着调用上面赋值的 probe函数。
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值