PCI Express设备驱动 (2)

#include "card.h"
#include
<linux/time.h>
#include
<linux/spinlock.h>

#define DMA_MASK 0xffffffff
#define test_dri_major 249 // 主设备号
//#define INT_ASSERT_W 0x02 // DMA Write Complete
//#define INT_ASSERT_R 0x10 // DMA Read Complete

/* PCI 驱动基本框架 */
static struct pci_device_id card_ids[] = {
{PCI_DEVICE(PCI_VENDOR_ID_XILINX,PCI_DEVICE_ID_EP_PIPE),},
{
0,}
};
MODULE_DEVICE_TABLE(pci,card_ids);

static int card_probe(struct pci_dev *pci_dev, const struct pci_device_id *id);
static void card_remove(struct pci_dev *pdev);


static struct pci_driver card_driver = {
.name
= DEV_NAME,
.id_table
= card_ids,
.probe
= card_probe,
.remove
= card_remove,
};

static int __init card_init(void)
{
int result;
result
= pci_register_driver(&card_driver);
return result;
}

static void __exit card_exit(void)
{
pci_unregister_driver(
&card_driver);
}

module_init(card_init);
module_exit(card_exit);

/* PCI 驱动基本框架 */

/* 特定设备私有数据结构 */
struct card_private {
struct pci_dev* pci_dev;
void* pci_bar0;
//wait_queue_head_t * dma_write_wait;
//wait_queue_head_t * dma_read_wait;
};
/* 特定设备私有数据结构 */

static struct card_private *adapter;

//static DECLARE_WAIT_QUEUE_HEAD(dma_write_wait);
//static int flag = 1;


// 将文件操作与分配的设备号相连
static const struct file_operations card_fops =
{
.owner
= THIS_MODULE,
//.ioctl = card_ioctl,
.open = card_open,
.release
= card_release,
.read
= card_read,
.write
= card_write,
};



static int card_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
unsigned
long phymem;
void __iomem *mem;
u_int8_t csz;
u32 val;
int result;


if (pci_enable_device(pdev))
return -EIO;

/* XXX 32-bit addressing only */
if (pci_set_dma_mask(pdev, 0xffffffff)) {
printk(KERN_ERR
"ath_pci: 32-bit DMA not available\n");
goto bad;
}

//pci_write_config_word(pdev, 0x04, 0x0007);

/*
* Cache line size is used to size and align various
* structures used to communicate with the hardware.
*/
pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE,
&csz);
if (csz == 0) {
/*
* Linux 2.4.18 (at least) writes the cache line size
* register as a 16-bit wide register which is wrong.
* We must have this setup properly for rx buffer
* DMA to work so force a reasonable value here if it
* comes up zero.
*/
csz
= L1_CACHE_BYTES / sizeof(u_int32_t);
pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz);
}
/*
* The default setting of latency timer yields poor results,
* set it to the value used by other systems. It may be worth
* tweaking this setting more.
*/
pci_write_config_byte(pdev, PCI_LATENCY_TIMER,
0xa8);

pci_set_master(pdev);

/*
* Disable the RETRY_TIMEOUT register (0x41) to keep
* PCI Tx retries from interfering with C3 CPU state.
*
* Code taken from ipw2100 driver - jg
*/
pci_read_config_dword(pdev,
0x40, &val);
if ((val & 0x0000ff00) != 0)
pci_write_config_dword(pdev,
0x40, val & 0xffff00ff);

// 获得BAR0空间的基地址,该地址为存储器域的物理地址;
phymem = pci_resource_start(pdev, 0);
if (!request_mem_region(phymem, pci_resource_len(pdev, 0), DEV_NAME)) {
printk(KERN_ERR
"card_driver: cannot reserve PCI memory region\n");
goto bad;
}

// 将存储器域的物理地址映射为虚拟地址;
mem = ioremap(phymem, pci_resource_len(pdev, 0));
if (!mem) {
printk(KERN_ERR
"card_driver: cannot remap PCI memory region\n") ;
goto bad1;
}

adapter
= kmalloc(sizeof(struct card_private), GFP_KERNEL);

if (unlikely(!adapter)){
return -ENOMEM;
}

adapter
-> pci_dev = pdev;

adapter
-> pci_bar0 = mem;

// 注册设备驱动程序
result = register_chrdev(test_dri_major, DEV_NAME, &card_fops);

if (unlikely(result)){
printk(KERN_ERR
"card_driver: no memory for device state\n");
goto bad2;
}

/*
//init_waitqueue_head(adapter->dma_write_wait);
//init_waitqueue_head(adapter->dma_read_wait);

result = pci_enable_msi(pdev);
if (unlikely(result)){

//PDEBUG("cannot enable msi ... \n");
goto bad3;
}

result = request_irq(pdev -> irq, card_interrupt, 0, DEV_NAME, NULL);
if (unlikely(result)){

//PDEBUG("request interrupt failed ... \n");
goto bad3;
printk(KERN_DEBUG "request_irq(pdev -> irq, card_interrupt, 0, DEV_NAME, NULL);");
}
*/

return 0;

//bad3:
// unregister_chrdev(test_dri_major, DEV_NAME);
bad2:
iounmap(mem);
bad1:
release_mem_region(phymem, pci_resource_len(pdev,
0));
bad:
pci_disable_device(pdev);
return (-ENODEV);

}


static void card_remove(struct pci_dev *pdev)
{
//pci_disable_msi(pdev);
//if(pdev->irq)
// free_irq(pdev->irq, pdev);
iounmap(adapter -> pci_bar0);
release_mem_region(pci_resource_start(pdev,
0), pci_resource_len(pdev, 0));
pci_disable_device(pdev);
unregister_chrdev(test_dri_major, DEV_NAME);
}

  

posted on 2011-08-22 15:16  zzwworld  阅读(3046)  评论(1)    收藏  举报

导航