patch-2.3.10 linux/drivers/misc/parport_share.c

Next file: linux/drivers/net/3c501.c
Previous file: linux/drivers/misc/parport_procfs.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.9/linux/drivers/misc/parport_share.c linux/drivers/misc/parport_share.c
@@ -14,11 +14,8 @@
 #undef PARPORT_DEBUG_SHARING		/* undef for production */
 
 #include <linux/config.h>
-
 #include <linux/string.h>
-
 #include <linux/tasks.h>
-
 #include <linux/parport.h>
 #include <linux/delay.h>
 #include <linux/errno.h>
@@ -31,18 +28,12 @@
 #include <asm/spinlock.h>
 #include <asm/irq.h>
 
-#ifdef CONFIG_KMOD
-#include <linux/kmod.h>
-#endif
-
 #undef PARPORT_PARANOID
 
 #define PARPORT_DEFAULT_TIMESLICE	(HZ/5)
 
 unsigned long parport_default_timeslice = PARPORT_DEFAULT_TIMESLICE;
-
-/* This doesn't do anything yet. */
-int parport_default_spintime;
+int parport_default_spintime =  DEFAULT_SPIN_TIME;
 
 static struct parport *portlist = NULL, *portlist_tail = NULL;
 spinlock_t parportlist_lock = SPIN_LOCK_UNLOCKED;
@@ -50,7 +41,7 @@
 static struct parport_driver *driver_chain = NULL;
 spinlock_t driverlist_lock = SPIN_LOCK_UNLOCKED;
 
-static void call_driver_chain (int attach, struct parport *port)
+static void call_driver_chain(int attach, struct parport *port)
 {
 	struct parport_driver *drv;
 
@@ -96,19 +87,9 @@
 	}
 }
 
-void (*parport_probe_hook)(struct parport *port) = NULL;
-
 /* Return a list of all the ports we know about. */
 struct parport *parport_enumerate(void)
 {
-#ifdef CONFIG_KMOD
-	if (portlist == NULL) {
-		request_module("parport_lowlevel");
-#ifdef CONFIG_PNP_PARPORT_MODULE
-		request_module("parport_probe");
-#endif /* CONFIG_PNP_PARPORT_MODULE */
-	}
-#endif /* CONFIG_KMOD */
 	return portlist;
 }
 
@@ -117,16 +98,9 @@
 {
 	struct parport *tmp;
 	int portnum;
+	int device;
 	char *name;
 
-	/* Check for a previously registered port.
-	   NOTE: we will ignore irq and dma if we find a previously
-	   registered device.  */
-	for (tmp = portlist; tmp; tmp = tmp->next) {
-		if (tmp->base == base)
-			return tmp;
-	}
-
 	tmp = kmalloc(sizeof(struct parport), GFP_KERNEL);
 	if (!tmp) {
 		printk(KERN_WARNING "parport: memory squeeze\n");
@@ -154,16 +128,22 @@
 	tmp->base = base;
 	tmp->irq = irq;
 	tmp->dma = dma;
+	tmp->muxport = tmp->daisy = tmp->muxsel = -1;
 	tmp->modes = 0;
  	tmp->next = NULL;
 	tmp->devices = tmp->cad = NULL;
 	tmp->flags = 0;
 	tmp->ops = ops;
-	tmp->number = portnum;
-	memset (&tmp->probe_info, 0, sizeof (struct parport_device_info));
+	tmp->portnum = tmp->number = portnum;
+	tmp->physport = tmp;
+	memset (tmp->probe_info, 0, 5 * sizeof (struct parport_device_info));
 	tmp->cad_lock = RW_LOCK_UNLOCKED;
 	spin_lock_init(&tmp->waitlist_lock);
 	spin_lock_init(&tmp->pardevice_lock);
+	tmp->ieee1284.mode = IEEE1284_MODE_COMPAT;
+	tmp->ieee1284.phase = IEEE1284_PH_FWD_IDLE;
+	init_MUTEX_LOCKED (&tmp->ieee1284.irq); /* actually a semaphore at 0 */
+	tmp->spintime = parport_default_spintime;
 
 	name = kmalloc(15, GFP_KERNEL);
 	if (!name) {
@@ -188,7 +168,10 @@
 		portlist = tmp;
 	spin_unlock(&parportlist_lock);
 
-	tmp->probe_info.class = PARPORT_CLASS_LEGACY;  /* assume the worst */
+	for (device = 0; device < 5; device++)
+		/* assume the worst */
+		tmp->probe_info[device].class = PARPORT_CLASS_LEGACY;
+
 	tmp->waithead = tmp->waittail = NULL;
 
 	return tmp;
@@ -196,6 +179,11 @@
 
 void parport_announce_port (struct parport *port)
 {
+#ifdef CONFIG_PARPORT_1284
+	/* Analyse the IEEE1284.3 topology of the port. */
+	parport_daisy_init (port);
+#endif
+
 	/* Let drivers know that a new port has arrived. */
 	call_driver_chain (1, port);
 }
@@ -203,10 +191,16 @@
 void parport_unregister_port(struct parport *port)
 {
 	struct parport *p;
+	int d;
 
 	/* Spread the word. */
 	call_driver_chain (0, port);
 
+#ifdef CONFIG_PARPORT_1284
+	/* Forget the IEEE1284.3 topology of the port. */
+	parport_daisy_fini (port);
+#endif
+
 	spin_lock(&parportlist_lock);
 	if (portlist == port) {
 		if ((portlist = port->next) == NULL)
@@ -222,16 +216,20 @@
 			     "%s not found in port list!\n", port->name);
 	}
 	spin_unlock(&parportlist_lock);
-	if (port->probe_info.class_name)
-		kfree (port->probe_info.class_name);
-	if (port->probe_info.mfr)
-		kfree (port->probe_info.mfr);
-	if (port->probe_info.model)
-		kfree (port->probe_info.model);
-	if (port->probe_info.cmdset)
-		kfree (port->probe_info.cmdset);
-	if (port->probe_info.description)
-		kfree (port->probe_info.description);
+
+	for (d = 0; d < 5; d++) {
+		if (port->probe_info[d].class_name)
+			kfree (port->probe_info[d].class_name);
+		if (port->probe_info[d].mfr)
+			kfree (port->probe_info[d].mfr);
+		if (port->probe_info[d].model)
+			kfree (port->probe_info[d].model);
+		if (port->probe_info[d].cmdset)
+			kfree (port->probe_info[d].cmdset);
+		if (port->probe_info[d].description)
+			kfree (port->probe_info[d].description);
+	}
+
 	kfree(port->name);
 	kfree(port);
 }
@@ -243,7 +241,7 @@
 {
 	struct pardevice *tmp;
 
-	if (port->flags & PARPORT_FLAG_EXCL) {
+	if (port->physport->flags & PARPORT_FLAG_EXCL) {
 		/* An exclusive device is registered. */
 		printk (KERN_DEBUG "%s: no more devices allowed\n",
 			port->name);
@@ -272,13 +270,14 @@
 
 	tmp->name = name;
 	tmp->port = port;
+	tmp->daisy = -1;
 	tmp->preempt = pf;
 	tmp->wakeup = kf;
 	tmp->private = handle;
 	tmp->flags = flags;
 	tmp->irq_func = irq_func;
-	port->ops->init_state(tmp->state);
 	tmp->waiting = 0;
+	tmp->timeout = 5 * HZ;
 
 	/* Chain this onto the list */
 	tmp->prev = NULL;
@@ -286,11 +285,11 @@
 	 * This function must not run from an irq handler so we don' t need
 	 * to clear irq on the local CPU. -arca
 	 */
-	spin_lock(&port->pardevice_lock);
+	spin_lock(&port->physport->pardevice_lock);
 
 	if (flags & PARPORT_DEV_EXCL) {
-		if (port->devices) {
-			spin_unlock (&port->pardevice_lock);
+		if (port->physport->devices) {
+			spin_unlock (&port->physport->pardevice_lock);
 			kfree (tmp->state);
 			kfree (tmp);
 			printk (KERN_DEBUG
@@ -301,11 +300,11 @@
 		port->flags |= PARPORT_FLAG_EXCL;
 	}
 
-	tmp->next = port->devices;
-	if (port->devices)
-		port->devices->prev = tmp;
-	port->devices = tmp;
-	spin_unlock(&port->pardevice_lock);
+	tmp->next = port->physport->devices;
+	if (port->physport->devices)
+		port->physport->devices->prev = tmp;
+	port->physport->devices = tmp;
+	spin_unlock(&port->physport->pardevice_lock);
 
 	inc_parport_count();
 	port->ops->inc_use_count();
@@ -314,6 +313,12 @@
 	tmp->timeslice = parport_default_timeslice;
 	tmp->waitnext = tmp->waitprev = NULL;
 
+	/*
+	 * This has to be run as last thing since init_state may need other
+	 * pardevice fields. -arca
+	 */
+	port->ops->init_state(tmp, tmp->state);
+	parport_device_proc_register(tmp);
 	return tmp;
 }
 
@@ -328,7 +333,9 @@
 	}
 #endif
 
-	port = dev->port;
+	parport_device_proc_unregister(dev);
+
+	port = dev->port->physport;
 
 	if (port->cad == dev) {
 		printk(KERN_DEBUG "%s: %s forgot to release port\n",
@@ -354,19 +361,17 @@
 
 	dec_parport_count();
 	port->ops->dec_use_count();
-
-	return;
 }
 
 int parport_claim(struct pardevice *dev)
 {
 	struct pardevice *oldcad;
-	struct parport *port = dev->port;
+	struct parport *port = dev->port->physport;
 	unsigned long flags;
 
 	if (port->cad == dev) {
 		printk(KERN_INFO "%s: %s already owner\n",
-			   dev->port->name,dev->name);
+		       dev->port->name,dev->name);
 		return 0;
 	}
 
@@ -407,24 +412,27 @@
 		dev->waitprev = dev->waitnext = NULL;
 	}
 
-	if (oldcad && port->irq != PARPORT_IRQ_NONE && !oldcad->irq_func)
-		/*
-		 * If there was an irq pending it should hopefully happen
-		 * before return from enable_irq(). -arca
-		 */
-		enable_irq(port->irq);
-
-	/*
-	 * Avoid running irq handlers if the pardevice doesn' t use it. -arca
-	 */
-	if (port->irq != PARPORT_IRQ_NONE && !dev->irq_func)
-		disable_irq(port->irq);
-
 	/* Now we do the change of devices */
 	write_lock_irqsave(&port->cad_lock, flags);
 	port->cad = dev;
 	write_unlock_irqrestore(&port->cad_lock, flags);
 
+#ifdef CONFIG_PARPORT_1284
+	/* If it's a mux port, select it. */
+	if (dev->port->muxport >= 0) {
+		/* FIXME */
+		port->muxsel = dev->port->muxport;
+	}
+
+	/* If it's a daisy chain device, select it. */
+	if (dev->daisy >= 0) {
+		/* This could be lazier. */
+		if (!parport_daisy_select (port, dev->daisy,
+					   IEEE1284_MODE_COMPAT))
+			port->daisy = dev->daisy;
+	}
+#endif /* IEEE1284.3 support */
+
 	/* Restore control registers */
 	port->ops->restore_state(port, dev->state);
 	dev->time = jiffies;
@@ -487,8 +495,11 @@
 		}
 		restore_flags(flags);
 #ifdef PARPORT_DEBUG_SHARING
-		if (dev->port->cad != dev)
-			printk(KERN_DEBUG "%s: exiting parport_claim_or_block but %s owns port!\n", dev->name, dev->port->cad?dev->port->cad->name:"nobody");
+		if (dev->port->physport->cad != dev)
+			printk(KERN_DEBUG "%s: exiting parport_claim_or_block "
+			       "but %s owns port!\n", dev->name,
+			       dev->port->physport->cad ?
+			       dev->port->physport->cad->name:"nobody");
 #endif
 	}
 	dev->waiting = 0;
@@ -497,7 +508,7 @@
 
 void parport_release(struct pardevice *dev)
 {
-	struct parport *port = dev->port;
+	struct parport *port = dev->port->physport;
 	struct pardevice *pd;
 	unsigned long flags;
 
@@ -507,16 +518,24 @@
 		       "when not owner\n", port->name, dev->name);
 		return;
 	}
+
+#ifdef CONFIG_PARPORT_1284
+	/* If this is on a mux port, deselect it. */
+	if (dev->port->muxport >= 0) {
+		/* FIXME */
+		port->muxsel = -1;
+	}
+
+	/* If this is a daisy device, deselect it. */
+	if (dev->daisy >= 0) {
+		parport_daisy_deselect_all (port);
+		port->daisy = -1;
+	}
+#endif
+
 	write_lock_irqsave(&port->cad_lock, flags);
 	port->cad = NULL;
 	write_unlock_irqrestore(&port->cad_lock, flags);
-
-	/*
-	 * Reenable irq and so discard the eventually pending irq while
-	 * cad is NULL. -arca
-	 */
-	if (port->irq != PARPORT_IRQ_NONE && !dev->irq_func)
-		enable_irq(port->irq);
 
 	/* Save control registers */
 	port->ops->save_state(port, dev->state);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)