[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