#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/sched.h>
#include <asm/io.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#ifdef LINUX26
#include <linux/moduleparam.h>
#endif
#include "plx.h"
#define DEVICE_NAME "Plxdriver"
#define Plx_8311
static int imajor;
static int plx_major = 0;
struct Cdev Cdev;
dev_t Devno;
struct class *plx_class;
static struct PLX *cards[plx_max_ifaces];
BOOL Found_card_flag = 0;
static void Plx_release (struct PLX *PLX)
{
unsigned short Val;
val = 0x0;
if (PLX->FREEREGION_PLX)
Release_mem_region (Plx->region, Plx->len);
if (PLX->ADDR)
Iounmap (PLX->ADDR);
if (PLX)
Kfree (PLX);
PRINTK ("Freed a plx card\n");
}
static int Shrec_open (struct inode *inode, struct file *file)
{
Try_module_get (This_module);
PRINTK ("Open driver\n");
return 0;
}
static int shrec_release (struct inode *inode, struct file *file)
{
Module_put (This_module);
if (WC->FREEREGION_PLX)
Release_mem_region (Wc->plx_region, Wc->plx_len);
if (WC->FREEREGION_DSP)
Release_mem_region (Wc->dsp_region, Wc->dsp_len);
if (WC->PLX)
Iounmap (WC->PLX);
if (WC->DSP)
Iounmap (WC->DSP);
if (WC)
Vfree (WC);
return 0;
}
static struct File_operations Shrec_fops = {
Owner:this_module,
Open:shrec_open,
Read:shrec_read,
Write:shrec_write,
Release:shrec_release,
};
static int __devinit plx_init_one (struct pci_dev *pdev, const struct PCI_DEVICE_ID *ent)
{
int x;
int ret;
int res;
struct PLX *PLX;
for (x=0;x<plx_max_ifaces;x++)
{
if (!cards[x])
Break
}
if (x >= plx_max_ifaces)
{
PRINTK ("Too many interfaces\n");
Return-eio;
}
if (Pci_enable_device (Pdev))
{
res =-eio;
}
Else
{
PLX = kmalloc (sizeof (struct PLX), gfp_kernel);
if (!PLX) Return-enomem;
memset (PLX, 0x0, sizeof (struct PLX));
if (Pdev->irq < 1)
{
if (PLX)
Kfree (PLX);
PRINTK (kern_err "No IRQ allocated for device\n");
Return-enodev;
}
CARDS[X] = PLX;
Plx->dev = Pdev;
Plx->region = Pci_resource_start (pdev,0); 1, get PLX address space base address 0, the address is the physical address, by the system boot is saved in the PDEV structure
Plx->len = Pci_resource_len (pdev,0); Get the space size of base address 0
if (Check_mem_region (Plx->region, Plx->len))//2, check if the area is available
{
PRINTK ("PLX region%LX-%LX already in use\n", plx->region, Plx->region + Plx->len);
if (PLX)
Kfree (PLX);
Return-eio;
}
if (Request_mem_region (plx->region, Plx->len, "PLX"))//3, apply for use of the area
{
PLX->FREEREGION_PLX = 1;
}
PLX->ADDR = Ioremap (plx->region, Plx->len); 4, the physical address of the region is mapped to a virtual address, the program can only read and write to the virtual address
if (!PLX->ADDR)
{
PRINTK ("Cannot ioremap memory space at 0x%lx\n", plx->region);
Goto ERR_OUT_FREE_PLX;
}
Pci_set_drvdata (Pdev, PLX);
PRINTK ("Found PLX card%d\n", x);
Found_card_flag = 1;
res = 0;
}
return res;
ERR_OUT_FREE_PLX:
if (PLX->FREEREGION_PLX)
Release_mem_region (Plx->region, Plx->len);
if (PLX->ADDR)
Iounmap (PLX->ADDR);
if (PLX)
Kfree (PLX);
Return-eio;
}
static void __devexit Plx_remove_one (struct Pci_dev *pdev)
{
struct PLX *PLX = Pci_get_drvdata (Pdev);
unsigned short reg;
if (PLX)
{
reg = 0x0;
Wait_ms (5000);
if (!plx->usecount)
Plx_release (PLX);
Else
Plx->dead = 1;
}
}
static struct pci_device_id plx_pci_tbl[] =
{
/*probe PCIe cards*/
{0x10b5, pci_any_id, pci_any_id, pci_any_id, 0, 0, 0},
/*probe PCI cards*/
/*tejxapci*/
{0x10b5, 0X00FA, pci_any_id, pci_any_id, 0, 0, 0},
{0x10b5, 0X00FB, pci_any_id, pci_any_id, 0, 0, 0},
{0x10b5, 0X00FC, pci_any_id, pci_any_id, 0, 0, 0},
};
Module_device_table (PCI, PLX_PCI_TBL);
static struct Pci_driver Plx_driver =
{
Name: "Plx_driver",
Probe:plx_init_one,
Remove:plx_remove_one,
Suspend:null,
Resume:null,
ID_TABLE:PLX_PCI_TBL,/* When the driver is loaded, the nodes in the PCI list are probed, if there is a PCI device with
If the PLX_PCI_TBL information matches, the Plx_init_one is called and the device is configured and initialized */
};
static int __init plx_driver_init (void)
{
int res;
res = Pci_register_driver (&plx_driver);/* Register PCI driver */
if (res)
Return-enodev;
if (plx_major)
{
Devno = MKDEV (plx_major,0);/* Gets the main device number */
res = register_chrdev_region (devno,1,device_name);
}
Else
{
res = alloc_chrdev_region (&devno,0,1,device_name);
Plx_major = Major (Devno);
PRINTK ("major =%d\n", plx_major);
}
if (Found_card_flag)
{
/* Register your device */
Cdev_init (&cdev,&shrec_fops);
Cdev.owner = This_module;
res = Cdev_add (&cdev,devno,1);
if (res)
PRINTK ("Error%d adding PLX", res);
/* Create a Device file node */
Plx_class = Class_create (This_module, device_name);
if (Is_err (Plx_class))
{PRINTK ("err:failed in creating class.\n");
return-1;
}
Device_create (Plx_class, NULL, Devno, device_name);
}
Else
PRINTK ("Not found Synway card!\n");
return 0;
}
static void __exit plx_driver_cleanup (void)
{
Unregister_chrdev_region (devno,1);/* Unregister device number */
Pci_unregister_driver (&plx_driver);/* Unregister PCI driver, call plx_remove_one function */
/* Unregister file Node */
if (Found_card_flag)
{
Device_destroy (Plx_class, Devno);
Class_destroy (Plx_class);
Cdev_del (&cdev);/* Unregister character device */
}
}
Module_init (Plx_driver_init);
Module_exit (Plx_driver_cleanup);
Linux PCI Driver Source code