[PATCH] Continue pcnet probing. Introduce driver's private block
Denis Kirjanov
kirjanov at gmail.com
Fri Sep 17 11:02:38 EDT 2010
Signed-off-by: Denis Kirjanov <kirjanov at gmail.com>
---
src/pcnet.c | 87 ++++++++++++++++++++++++++++++++++++++++++++++++----------
1 files changed, 72 insertions(+), 15 deletions(-)
diff --git a/src/pcnet.c b/src/pcnet.c
index bdb463c..93fd4d1 100644
--- a/src/pcnet.c
+++ b/src/pcnet.c
@@ -9,6 +9,9 @@
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/pci.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/spinlock.h>
#define DRV_NAME "pcnet_dummy"
#define DRV_VERSION "dev"
@@ -24,38 +27,86 @@ static DEFINE_PCI_DEVICE_TABLE(pcnet_dummy_pci_tbl) = {
{ }
};
-static int pcnet_dummy_init_netdev(struct pci_dev *pdev, unsigned int ioaddr);
+enum {
+ PCNET_IOSIZE_LEN = 0x20,
+};
+
+struct pcnet_private {
+ /* TODO:
+ * DMA buffer management operations
+ */
+ spinlock_t lock;
+ struct pci_dev *pci_dev;
+ void __iomem *base;
+};
+
+/* Why do we need to create protos like this? */
+static int pcnet_dummy_init_netdev(struct pci_dev *pdev, unsigned long ioaddr);
static int __devinit pcnet_dummy_init_one(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
- unsigned int ioaddr;
- int err;
+ struct pcnet_private *pp;
+ struct net_device *ndev;
+ void __iomem *ioaddr;
+#ifdef USE_IO_OPS
+ int bar = 0;
+#else
+ int bar = 1;
+#endif
if (pci_enable_device(pdev))
return -ENODEV;
/* enables bus-mastering for device pdev */
pci_set_master(pdev);
- if (pci_request_regions(pdev, DRV_NAME)) {
- pci_disable_device(pdev);
- return -EBUSY;
+ ndev = alloc_etherdev(sizeof(*pp));
+ if (!ndev) {
+ goto out;
}
+ /* register ourself under /sys/class/net/ */
+ SET_NETDEV_DEV(ndev, &pdev->dev);
- ioaddr = pci_resource_start(pdev, 0);
+ if (pci_request_regions(pdev, DRV_NAME))
+ goto out_netdev;
- err = pcnet_dummy_init_netdev(pdev, ioaddr);
- if (err) {
- pci_disable_device(pdev);
- pci_release_regions(pdev);
- }
+ ioaddr = pci_iomap(pdev, bar, PCNET_IOSIZE_LEN);
+ if (!ioaddr)
+ goto out_res;
+ pci_set_drvdata(pdev, ndev);
+
+ if (pcnet_dummy_init_netdev(pdev, (unsigned long)ioaddr))
+ goto out_res_unmap;
- return err;
+ return 0;
+
+out_res_unmap:
+ pci_iounmap(pdev, ioaddr);
+out_res:
+ pci_release_regions(pdev);
+out_netdev:
+ free_netdev(ndev);
+out:
+ pci_disable_device(pdev);
+ return -ENODEV;
}
static int __devinit pcnet_dummy_init_netdev(struct pci_dev *pdev,
- unsigned int ioaddr)
+ unsigned long ioaddr)
{
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct pcnet_private *pp;
+ int irq;
+
+ irq = pdev->irq;
+ pp = netdev_priv(ndev);
+ ndev->base_addr = ioaddr;
+ ndev->irq = irq;
+ pp->pci_dev = pdev;
+ spin_lock_init(&pp->lock);
+
+ /* init DMA rings */
+ /* init net_dev_ops */
/* registers net_device and returns err */
/* TODO: reset the chip at the end */
@@ -64,10 +115,16 @@ static int __devinit pcnet_dummy_init_netdev(struct pci_dev *pdev,
static void __devexit pcnet_dummy_remove_one(struct pci_dev *pdev)
{
- /* TODO: ensure pdev is enabled */
+ struct net_device *ndev = pci_get_drvdata(pdev);
+ struct pcnet_private *pp;
+ pp = netdev_priv(ndev);
+ pci_iounmap(pdev, pp->base);
+ free_netdev(ndev);
+ /* TODO: ensure pdev is enabled */
pci_disable_device(pdev);
pci_release_regions(pdev);
+ pci_set_drvdata(pdev, NULL);
}
static struct pci_driver pcnet_dummy_driver = {
--
1.7.0.4
More information about the Kernel-russian
mailing list