Linux驱动----PCI 驱动开发实例

本文通过qemu-kvm模拟PCI物理设备,介绍Linux系统下的驱动程序开发。使用qemu-system-x86_64启动虚拟机,并加载vblk驱动,设备映射文件为hxxx.img,内核版本2.6.32-71.el6。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


详细原理不介绍, 参照《Linux 设备驱动 Edition 3》中第16章块设备驱动,第12章 PCI 驱动开发,以及KVM虚拟化设备模拟,以及其他设备中断,端口读写等等, 涉及知识较多,应该是一个综合实例。多余不必叙述,可参考下面代码。由于该实例涉及知识较多,建议首先学习《Linux 设备驱动 Edition 3》中第16章块设备驱动,第12章 PCI 驱动开发,再尝试该实例。

因为需要PCI物理设备,学习一下qemu-kvm设备模拟,采用qemu-kvm模拟PCI物理设备,而虚拟机采用Linux系统,编写该物理驱动程序vblk.c,设备模拟代码参见hw/vblk.c.

虚拟机运行:

#x86_64-softmmu/qemu-system-x86_64 -hda /var/lib/libvirt/images/hxxx.img -m 1024 -device vblk

//模拟pci设备为vblk

//hxxx.img为 发行版CentOS Linux release 6.0 (Final),内核2.6.32-71.el6

注意:
1.内核版本:
# uname -r
2.6.32-71.el6

2.发行版:
# cat /etc/redhat-release
CentOS Linux release 6.0 (Final)

3.qemu-kvm版本
# rpm -qa | grep qemu-kvm
qemu-kvm-0.12.1.2-2.209.el6.x86_64


一.编写Linux PCI设备驱动
#vi vblk.c
######################################
##include <linux/init.h>
#include <linux/module.h>
#include <linux/blkdev.h>
#include <linux/spinlock.h>
#include <linux/genhd.h>
#include <linux/blkdev.h>
#include <linux/buffer_head.h>  /* invalidate_bdev */
#include <linux/bio.h>
#include <linux/pci.h>
#include <linux/interrupt.h>
static int major, index=0;
static int hardsect_size = 512;
static int nsectors = 1024*2*10;     /* How big the drive is */
#define TRANSFER_OK     1
struct virt_dev {
    spinlock_t lock;
    int size;                       /* Device size in sectors */
        u8 *data;                       /* The data array */
    unsigned long ioaddr;
    u8* mmioaddr;
    unsigned int irq;
    struct gendisk *disk;
};

static struct virt_dev *vbd;
static const struct block_device_operations vbd_fops = {
        .owner  = THIS_MODULE,
};

static struct pci_device_id vblk_pci_id_table[] = {
    { 0x1af4, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
    {0},
};
/*
 *  * Handle an I/O request.
 *   */
static void sbull_transfer(struct virt_dev *dev, unsigned long sector,
                unsigned long nsect, char *buffer, int write)
{
        unsigned long offset = sector*512;
        unsigned long nbytes = nsect*512;

        if ((offset + nbytes) > dev->size) {
                printk (KERN_NOTICE "Beyond-end write (%ld %ld)\n", offset, nbytes);
                return;
        }
        if (write)
                memcpy(dev->data + offset, buffer, nbytes);
        else
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值