[虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(六)
目的:
1. 为我们自己的watchdog写一个驱动
步骤:
通过之前的介绍,我们很容易猜想到写我们基于PCI的watchdog驱动,可以分2个步骤。
1. 探测加载PCI设备
这部分代码跟我们的设备本身没有任何关系。
我们通过这部分代码,找到 厂商ID为 0x1af4, 设备ID为0x0101的设备。这个设备是我们用qemu中定义我们的watchdog中指定的。
#define PCI_VENDOR_ID_REDHAT 0x1af4
#define PCI_DEVICE_ID_CWD 0x0101
很自然的可以先到我们需要一个probe的函数来探测PCI设备。 事实确实如此。
我们通过一个pci_driver定义这部分。
static struct pci_driver cwd_driver = {
.name = ESB_MODULE_NAME,
.id_table = cwd_pci_tbl,
.probe = cwd_probe,
.remove = cwd_remove,
.shutdown = cwd_shutdown,
};
我们可以直接参考一下其他的PCI设备驱代码来实现这部分代码,比如: drivers/watchdog/i6300esb.c
代码如下。
cwd_demo.c
#include <linux/init.h> //初始换函数
#include <linux/kernel.h> //内核头文件
#include <linux/module.h> //模块的头文件
#include <linux/pci.h>
#include <linux/miscdevice.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/mm.h>
#include <linux/watchdog.h>
#include <linux/ioport.h>
#include <linux/uaccess.h>
#include <linux/io.h> #define ESB_MODULE_NAME "cstl watchdog" /* We only use 1 card for cwd_demo */
static int cards_found;
static struct pci_dev *cwd_pci; MODULE_LICENSE("GPL"); #define CWD_VERSION "0.1"
#define PCI_VENDOR_ID_REDHAT 0x1af4
#define PCI_DEVICE_ID_CWD 0x0101
/* internal variables */
static void __iomem *BASEADDR; /*
* Data for PCI driver interface
*/
static DEFINE_PCI_DEVICE_TABLE(cwd_pci_tbl) = {
{ PCI_DEVICE(PCI_VENDOR_ID_REDHAT, PCI_DEVICE_ID_CWD), },
{ , }, /* End of list */
};
MODULE_DEVICE_TABLE(pci, cwd_pci_tbl); static unsigned char cwd_getdevice(struct pci_dev *pdev)
{
if (pci_enable_device(pdev)) {
printk(KERN_ERR "failed to enable device\n");
goto err_devput;
} if (pci_request_region(pdev, , ESB_MODULE_NAME)) {
printk(KERN_ERR "failed to request region\n");
goto err_disable;
} BASEADDR = pci_ioremap_bar(pdev, );
if (BASEADDR == NULL) {
/* Something's wrong here, BASEADDR has to be set */
printk(KERN_ERR "failed to get BASEADDR\n");
goto err_release;
} /* Done */
cwd_pci = pdev;
return ; err_release:
pci_release_region(pdev, );
err_disable:
pci_disable_device(pdev);
err_devput:
return ;
} static int cwd_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
int ret; cards_found++;
if (cards_found == )
printk(KERN_INFO "Cstl WatchDog Timer Driver v%s\n",
CWD_VERSION); if (cards_found > ) {
printk(KERN_ERR "Cstl driver only supports 1 device\n");
return -ENODEV;
} /* Check whether or not the hardware watchdog is there */
if (!cwd_getdevice(pdev) || cwd_pci == NULL)
return -ENODEV;
return ;
} static int cwd_timer_stop(void)
{
/* Returns 0 if the timer was disabled, non-zero otherwise */
return ;
}
static void cwd_remove(struct pci_dev *pdev)
{
/* Stop the timer before we leave */
cwd_timer_stop(); /* Deregister */
// misc_deregister(&cwd_miscdev);
iounmap(BASEADDR);
pci_release_region(cwd_pci, );
pci_disable_device(cwd_pci);
cwd_pci = NULL;
} static void cwd_shutdown(struct pci_dev *pdev)
{
cwd_timer_stop();
} static struct pci_driver cwd_driver = {
.name = ESB_MODULE_NAME,
.id_table = cwd_pci_tbl,
.probe = cwd_probe,
.remove = cwd_remove,
.shutdown = cwd_shutdown,
}; static int __init cwd_demo_start(void)
{
printk(KERN_ALERT "Loading cwd_demo module...\n");
printk(KERN_ALERT "Hello, I'm cwd_demo\n");
return pci_register_driver(&cwd_driver);
} static void __exit cwd_demo_end(void)
{
pci_unregister_driver(&cwd_driver);
printk(KERN_ALERT "cwd demo Module Unloaded, Goodbye!\n"); } module_init(cwd_demo_start);
module_exit(cwd_demo_end);
Makefile
ifeq ($(KERNELRELEASE),)
KVERSION = $(shell uname -r)
all:
make -C /lib/modules/$(KVERSION)/build M=$(shell pwd) modules
echo $(shell pwd)
clean:
make -C /lib/modules/$(KVERSION)/build M=$(shell pwd) clean
else
obj-m :=cwd_demo.o
endif
编译加载:
$ make
$ sudo insmod cwd_demo.ko
查看加载结果:
发现加载失败
$ tail -n 40 -f /var/log/syslog
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759632] Hello, I'm cwd_demo
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759666] Cstl WatchDog Timer Driver v0.1
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759740] ------------[ cut here ]------------
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759749] WARNING: CPU: 0 PID: 15113 at /build/buil
dd/linux-lts-saucy-3.11.0/drivers/pci/pci.c:130 pci_ioremap_bar+0x71/0x80()
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759750] Modules linked in: cwd_demo(OF+) btrfs ra
id6_pq zlib_deflate xor ufs qnx4 hfsplus hfs minix ntfs msdos jfs xfs reiserfs ext2 usblp hello(POF)
rfcomm bnep bluetooth cirrus ttm drm_kms_helper drm sysimgblt sysfillrect syscopyarea ppdev mac_hid p
arport_pc i2c_piix4 psmouse serio_raw lp parport floppy [last unloaded: cwd_demo]
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759775] CPU: 0 PID: 15113 Comm: insmod Tainted: P
F W O 3.11.0-15-generic #25~precise1-Ubuntu
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759777] Hardware name: QEMU Standard PC (i440FX +
PIIX, 1996), BIOS Bochs 01/01/2011
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759778] 0000000000000082 ffff8800367b5b38 ffffff
ff8173bc5e 0000000000000007
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759781] 0000000000000000 ffff8800367b5b78 ffffff
ff810653ac ffff88003dba1098
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759783] ffff88003dba1000 ffff8800367b5c20 ffffff
ffa01e0000 ffff88003dba1098
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759785] Call Trace:
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759792] [<ffffffff8173bc5e>] dump_stack+0x46/0x58
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759797] [<ffffffff810653ac>] warn_slowpath_common+0x8c/0xc0
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759799] [<ffffffff810653fa>] warn_slowpath_null+0x1a/0x20
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759801] [<ffffffff813aaf91>] pci_ioremap_bar+0x71/0x80
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759805] [<ffffffffa01de12f>] cwd_probe+0x6f/0x1d0 [cwd_demo]
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759808] [<ffffffff813acd2b>] local_pci_probe+0x4b/0x80
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759810] [<ffffffff813ae5a9>] __pci_device_probe+0xd9/0xe0
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759813] [<ffffffff813ae5ea>] pci_device_probe+0x3a/0x60
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759817] [<ffffffff814948bc>] really_probe+0x6c/0x330
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759819] [<ffffffff81494d07>] driver_probe_device+0x47/0xa0
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759821] [<ffffffff81494e0b>] __driver_attach+0xab/0xb0
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759823] [<ffffffff81494d60>] ? driver_probe_device+0xa0/0xa0
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759825] [<ffffffff81492aee>] bus_for_each_dev+0x5e/0x90
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759827] [<ffffffff8149447e>] driver_attach+0x1e/0x20
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759829] [<ffffffff81493f0c>] bus_add_driver+0x10c/0x290
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759831] [<ffffffff8149538d>] driver_register+0x7d/0x160
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759834] [<ffffffffa0032000>] ? 0xffffffffa0031fff
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759836] [<ffffffff813ad56c>] __pci_register_driver+0x4c/0x50
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759838] [<ffffffffa003203a>] cwd_demo_start+0x3a/0x1000 [cwd_demo]
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759842] [<ffffffff8100212a>] do_one_initcall+0xfa/0x1b0
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759846] [<ffffffff810578e3>] ? set_memory_nx+0x43/0x50
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759852] [<ffffffff81730257>] do_init_module+0x80/0x1d1
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759857] [<ffffffff810d1af9>] load_module+0x4c9/0x5f0
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759859] [<ffffffff810cf270>] ? show_initstate+0x50/0x50
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759862] [<ffffffff810d1cd4>] SyS_init_module+0xb4/0x100
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759866] [<ffffffff8175099d>] system_call_fastpath+0x1a/0x1f
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759868] ---[ end trace 4d45fe543fa54a73 ]---
Jun 30 15:14:30 fsh-virtual-machine kernel: [612625.759869] failed to get BASEADDR
分析错误:
通过内核栈信息,我们知道,代码在调用 pci_ioremap_bar 出现了问题。
我们之前已经了解到,对PCI设备IO的操作,有两种方式,一种,是IO空间,一种是内存空间。我们这里抄袭了i6300esb的代码,esb采用的是内存空间。
很容易的想到,我们的外设是不支持内存空间的。
查看我们的qemu的代码,发现我们确实没有实现相关的代码。
这个可以通过我们的qemu monitor的 info qtree 来查看。
dev: cstl-watchdog, id ""
expiration-ticks = 10 (0xa)
addr = 05.0
romfile = ""
rombar = 1 (0x1)
multifunction = false
command_serr_enable = true
class Class 0880, addr 00:05.0, pci id 1af4:0101 (sub 1af4:1100)
bar 0: i/o at 0xc090 [0xc09f]
果真是不支持内存空间。
其实在PCI的spec文件中,有说明,如果从baro~bar5寄存器中读出来的地址是奇数,表示这是个IO空间,这是的地址要与~0x03UL做与运算,如果是偶数,则表示是内存空间。
/* here we are testing it is a io space or mem space */
unsigned int addr = 0;
pci_read_config_dword(pdev, 0x10, &addr);
printk(KERN_ERR "get BASEADDR: 0x%x\n", addr);
在我们的log中将会输出以下的结果:
Jun 30 16:14:30 fsh-virtual-machine kernel: [612625.759872] failed to get get BASEADDR: 0xc91
[虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(六)的更多相关文章
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(九)
目的 1. 使用verilog/vhdl设计一个PCI的watchdog设备. 2. 通过systemverilog 写testbench. 很久之前研究过AC97的verilog代码.但是很久没用v ...
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(四)
通过前面的操作,我们已经可以创建一个带有我们自己的PCI的watchdog外设qemu 虚拟机了. 目的: 1. 了解我们的外设情况. 2. 为在guest中开发我们自己的linux PCI驱动程序做 ...
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(一)
目的: 结合现在比较流行的技术,通过一个demo 展示一个全栈式设计的各种技能. 一个全栈式的工程师,应该能设计通过verilog/VHDL做logical设计.能写内核驱动,能架站. 要熟悉veri ...
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(二)
这篇文章的理解,需要一些专业知识了. 我们可以创建模拟自己的外设吗? 我们已经知道什么是qemu了,我们可以通过qmeu的提供的外设,DIY一个计算机了. 但是我们可能还不满足,我们可以自己制造一个外 ...
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(八)
目的: 1. 通过网页读取watchdog的信息 2. 通过网页设置watchdog 准备工作: 1. 选择一个web框架,选用 cherrypy $ sudo apt-get install pyt ...
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(五)
目的: 1. 了解PCI的基本知识,为完成watchdog的设备做准备. 准备知识: 简单的说,PCI 设备分3个空间. 配置空间,IO空间,内存地址空间. PCI设备厂家决定了外设是使用IO空间还是 ...
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(七)
目标: 1. 完成最终的设备驱动,增加具体的watchdog设备操作的代码. 测试代码: 代码最终实现见cwd_demo.c 代码只实现了read与write. 没有实现ioctl. 因此,我们可以 ...
- [虚拟化/云][全栈demo] 为qemu增加一个PCI的watchdog外设(三)
我们已经设计了一个基于qemu的watchdog了.下一步工作就是创建一个含有我们的watchdog的虚拟计算机器了. 准备工作: 1. 使用virt-manager或者virsh创建一个虚拟机器. ...
- 从零开始的全栈工程师——利用CSS3画一个正方体 ( css3 )
transform属性 CSS3的变形(transform)属性让元素在一个坐标系统中变形.transform属性的基本语法如下: transform:none | <transform-fun ...
随机推荐
- a 标签的四个伪类
link 有链接属性时visited 链接地址已被访问过active 被用户激活(在鼠标点击与释放之间发生的事件)hover 其鼠标悬停 <!DOCTYPE ...
- mysqli连接数据库函数
<?php $mysqli=@new mysqli("localhost", "root", "123456", "xsph ...
- ASP.NET页面继承关系
用过ASP.NET(以下简称ASP)的都知道ASP以一种Code Behind的方式给咱展现了一种类似Winform的开发模型,同样也是以"事件触发"的方式进行各种请求处理.其中A ...
- VS2012编译错误信息,错误列表却没显示
今天在写代码的时候,发现VS有编译错误,在错误列表里面却没有显示错误信息,百思不得其解. 后来终于发现,错误列表弄了个筛选,所以就看不到错误信息了,晕死.有遇到该问题的,可以参考下.
- C语言的本质(8)——副作用与顺序点
C 语言中,术语副作用是指对数据对象或者文件的修改.例如以下语句 var = 99; 的副作用是把 var 的值修改成 99.对表达式求值也可能产生副作用,例如: se = 100 对这个表达式求值所 ...
- Android UI ActionBar功能-自定义Tab功能
还可以使用ActionBar实现Tab选项卡功能: 官方帮助文档:http://wear.techbrood.com/training/basics/actionbar/styling.html#Cu ...
- wx.Frame
wx.Frame A frame is a window whose size and position can (usually) be changed by the user. It usuall ...
- tomcat学习(-)windows 7 x64 配置tomcat服务
下载Tomcat 下载地址:http://tomcat.apache.org/ 安装版本:Tomcat 9.0 安装环境:windows 7 x64 阅读Tomcat文档 文档路径:http://lo ...
- UITextField总结--博主总结的真好
忍不住copy过来http://www.cnblogs.com/wengzilin/archive/2012/03/13/2393985.html 还有些不错的博客推荐给大家http://blog.c ...
- json(转)
转自:http://www.cnblogs.com/mcgrady/archive/2013/06/08/3127781.html 阅读目录 JSON的两种结构 认识JSON字符串 在JS中如何使用J ...