2004-06-22 15:25:10

by Dino Klein

[permalink] [raw]
Subject: [PATCH 2.6.7] Parallel port detection via ACPI

Hi everyone,
I posted the following message on linux-parport at infradead.org; however
the list seems to be inactive. Here it is again, for anyone interested.


----------Original Message Below---------

From: "Dino Klein" <[email protected]>
To: [email protected]
Subject: [Linux-parport] [PATCH 2.6.7] Parallel port detection via ACPI
Date: Fri, 18 Jun 2004 16:46:21 -0300

Hi,
I've modified the parport_pc.c file to detect parallel ports via
ACPI; it is partially a cut & paste from the serial port (8250) acpi
code. It's kinda crude, but it works. It utilizes the ACPI subsystem
to get the resources assigned to the port, and then passes them on
to the detection routine. I've verified that it is working on my
machine by cycling between the modes in the BIOS (spp, epp,
ecp+epp), and observing proper detection in the logs.
I commented out the pnp & non-pci detection calls, since ACPI
replaces them. I also disabled the SuperIO detection, since it was
grabbing the parallel port before the ACPI detection kicked in on my
motherboard with a via686 southbridge.
Again, this is is kinda of crude, but I would really like to see
some parallel port detection via ACPI, so I won't have to manually
specify irq & dma. Perhaps there should be an option to choose
between PnP and ACPI, since there shouldn't be a reason to use both.

--- linux-2.6.7-orig/drivers/parport/parport_pc.c 2004-06-18
14:20:00.000000000 -0400
+++ linux-2.6.7/drivers/parport/parport_pc.c 2004-06-18
13:05:01.000000000 -0400
@@ -55,6 +55,9 @@
#include <linux/pci.h>
#include <linux/pnp.h>
#include <linux/sysctl.h>
+#include <linux/acpi.h>
+
+#include <acpi/acpi_bus.h>

#include <asm/io.h>
#include <asm/dma.h>
@@ -101,6 +104,7 @@
#endif
static int pci_registered_parport;
static int pnp_registered_parport;
+static int acpi_registered_parport;

/* frob_control, but for ECR */
static void frob_econtrol (struct parport *pb, unsigned char m,
@@ -2917,6 +2921,92 @@
};


+/* A stuct to help with resource allocation enumeration */
+struct parport_pc_resources
+{
+ int io_lo;
+ int io_hi;
+ int irq;
+ int dma;
+};
+
+
+
+/* Callback to process all the assigned resources to the parallel
port device */
+static acpi_status acpi_parport_pc_resource(struct acpi_resource
*res, void *data)
+{
+ struct parport_pc_resources *pcres = (struct parport_pc_resources
*) data;
+ acpi_status status;
+
+
+ if (res->id == ACPI_RSTYPE_IO)
+ {
+ struct acpi_resource_io *io = (struct acpi_resource_io *)
&res->data.io;
+ if (pcres->io_lo==0) pcres->io_lo = io->min_base_address;
+ else pcres->io_hi = io->min_base_address;
+ }
+ else if (res->id == ACPI_RSTYPE_IRQ)
+ {
+ struct acpi_resource_irq *irq = (struct acpi_resource_irq *)
&res->data.irq;
+ pcres->irq = irq->interrupts[0];
+ }
+ else if (res->id == ACPI_RSTYPE_DMA)
+ {
+ struct acpi_resource_dma *dma = (struct acpi_resource_dma *)
&res->data.dma;
+ pcres->dma = dma->channels[0];
+ }
+
+ return AE_OK;
+}
+
+
+static int acpi_parport_pc_add(struct acpi_device *device)
+{
+ acpi_status status;
+ struct parport_pc_resources pcres;
+ struct parport *pdata;
+
+
+ pcres.io_lo = 0;
+ pcres.io_hi = 0;
+ pcres.irq = PARPORT_IRQ_NONE;
+ pcres.dma = PARPORT_DMA_NONE;
+
+ status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+ acpi_parport_pc_resource, &pcres);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ printk("ACPI parport device with low IO 0x%X, high IO 0x%X, IRQ
%d, DMA %d\n", pcres.io_lo, pcres.io_hi, pcres.irq, pcres.dma);
+ if (!(pdata = parport_pc_probe_port (pcres.io_lo, pcres.io_hi,
pcres.irq, pcres.dma, NULL)))
+ {
+ printk("probe of ACPI parport device failed\n");
+ return -ENODEV;
+ }
+
+ acpi_driver_data(device) = pdata;
+ return 0;
+}
+
+static int acpi_parport_pc_remove(struct acpi_device *device, int
type)
+{
+ struct parport *pdata = (struct parport
*)acpi_driver_data(device);
+ parport_pc_unregister_port(pdata);
+ return 0;
+}
+
+
+static struct acpi_driver parport_pc_acpi_driver = {
+ .name = "parport_pc",
+ .class = "",
+ .ids = "PNP0400, PNP0401",
+ .ops = {
+ .add = acpi_parport_pc_add,
+ .remove = acpi_parport_pc_remove,
+ },
+};
+
+
/* This is called by parport_pc_find_nonpci_ports (in asm/parport.h)
*/
static int __init __attribute__((unused))
parport_pc_find_isa_ports (int autoirq, int autodma)
@@ -2953,9 +3043,12 @@
#endif

/* Onboard SuperIO chipsets that show themselves on the PCI bus. */
+ /*
count += parport_pc_init_superio (autoirq, autodma);
+ */

/* PnP ports, skip detection if SuperIO already found them */
+ /*
if (!count) {
r = pnp_register_driver (&parport_pc_pnp_driver);
if (r >= 0) {
@@ -2963,9 +3056,12 @@
count += r;
}
}
+ */

/* ISA ports and whatever (see asm/parport.h). */
+ /*
count += parport_pc_find_nonpci_ports (autoirq, autodma);
+ */

r = pci_register_driver (&parport_pc_pci_driver);
if (r >= 0) {
@@ -2973,6 +3069,13 @@
count += r;
}

+ r = acpi_bus_register_driver (&parport_pc_acpi_driver);
+ if (ACPI_SUCCESS(r))
+ {
+ acpi_registered_parport = 1;
+ /* should we increase count? */
+ }
+
return count;
}

@@ -3190,6 +3293,8 @@
pci_unregister_driver (&parport_pc_pci_driver);
if (pnp_registered_parport)
pnp_unregister_driver (&parport_pc_pnp_driver);
+ if (acpi_registered_parport)
+ acpi_bus_unregister_driver(&parport_pc_acpi_driver);

spin_lock(&ports_lock);
while (!list_empty(&ports_list)) {

_________________________________________________________________
MSN Messenger: instale gr?tis e converse com seus amigos.
http://messenger.msn.com.br


2004-06-23 03:52:05

by Dino Klein

[permalink] [raw]
Subject: Re: [PATCH 2.6.7] Parallel port detection via ACPI

Hey,
I'll CC the list since someone might have some comments about your
situation.
I took a quick look at parport_pc.c from 2.4.26, and it looked pretty much
the same; my guess is tha the changes should be just about identical. I'll
give it a try and if it compiles, I'll post something; unfortunately I won't
be able to try it out, since I don't have an available machine one which to
boot 2.4.

>From: DervishD <[email protected]>
>To: Dino Klein <[email protected]>
>Subject: Re: [PATCH 2.6.7] Parallel port detection via ACPI
>Date: Tue, 22 Jun 2004 17:53:23 +0200
>
> Hi Dino :)
>
> * Dino Klein <[email protected]> dixit:
> > I posted the following message on linux-parport at infradead.org;
>however
> > the list seems to be inactive. Here it is again, for anyone interested.
>
> I'm interested, and as soon as one of my linux machines is boot
>again I can test your patch (if the sysadmin allows me...).
>
> I'm interested because I have a long standing problem with the
>parallel port, and it happens in all machines I have at hand. The
>problem is that, no matter how is configured the parallel port in the
>BIOS, Linux always says it is in SPP mode. No matter the motherboard,
>no matter the BIOS vendor, no matter anything. This is the dmesg
>output from one machine, the others are more or less the same:
>
>kernel: parport0: PC-style at 0x378 (0x778), irq 7 [PCSPP,TRISTATE]
>kernel: parport0: Printer, Lexmark International Lexmark Optra E312
>kernel: lp0: using parport0 (interrupt-driven).
>kernel: Trying to free free DMA3
>
> Other times I have this other message:
>
>kernel: parport0: PC-style at 0x378 (0x778) [PCSPP,TRISTATE]
>kernel: parport_pc: Via 686A parallel port: io=0x378
>kernel: lp0: using parport0 (polling).
>
> Most of the machines have Lexmark printers attached, but I've
>tested with different printer brands and that doesn't make a
>difference.
>
> All parallel ports are ECP & EPP capable. I contacted a time ago
>with the maintainers of the parport code, but I had only an answer,
>saying that I should put the ports in the BIOS as ECP or EPP, not as
>'ECP+EPP'. No problem, I did it and it didn't make a difference.
>
> > It utilizes the ACPI subsystem
> > to get the resources assigned to the port, and then passes them on
> > to the detection routine. I've verified that it is working on my
> > machine by cycling between the modes in the BIOS (spp, epp,
> > ecp+epp), and observing proper detection in the logs.
>
> That's exactly what I want! My problem now is that I cannot use
>the parports in any mode different from SPP, and that is very slow,
>and if the printer hangs, breaks, turns off or whatever, the software
>doesn't notice and waits forever!
>
> Abusing of you: is any way of, using the current code in 2.4.x,
>to make my parallel port work in ECP or EPP mode?
>
> Thanks a lot in advance, and thanks for the patch :)
>
> Ra?l N??ez de Arenas Coronado
>
>--
>Linux Registered User 88736
>http://www.pleyades.net & http://raul.pleyades.net/

_________________________________________________________________
MSN Messenger: instale gr?tis e converse com seus amigos.
http://messenger.msn.com.br

2004-06-23 20:37:49

by Dino Klein

[permalink] [raw]
Subject: Re: [PATCH 2.6.7] Parallel port detection via ACPI

ok, here's an adaptation of the same crude patch to 2.4.26; I did not give
it a try, but it does compile. let me know if it works properly.

--- linux-2.4.26-orig/drivers/parport/parport_pc.c 2003-06-13
10:51:35.000000000 -0400
+++ linux-2.4.26/drivers/parport/parport_pc.c 2004-06-23
16:33:03.959674872 -0400
@@ -53,6 +53,9 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/sysctl.h>
+#include <linux/acpi.h>
+
+#include <acpi/acpi_bus.h>

#include <asm/io.h>
#include <asm/dma.h>
@@ -2916,6 +2919,91 @@
static int __init parport_pc_init_superio(int autoirq, int autodma) {return
0;}
#endif /* CONFIG_PCI */

+struct parport_pc_resources
+{
+ int io_lo;
+ int io_hi;
+ int irq;
+ int dma;
+};
+
+
+
+/* Callback to process all the assigned resources to the parallel port
device */
+static acpi_status acpi_parport_pc_resource(struct acpi_resource *res, void
*data)
+{
+ struct parport_pc_resources *pcres = (struct parport_pc_resources *)
data;
+ acpi_status status;
+
+
+ if (res->id == ACPI_RSTYPE_IO)
+ {
+ struct acpi_resource_io *io = (struct acpi_resource_io *)
&res->data.io;
+ if (pcres->io_lo==0) pcres->io_lo = io->min_base_address;
+ else pcres->io_hi = io->min_base_address;
+ }
+ else if (res->id == ACPI_RSTYPE_IRQ)
+ {
+ struct acpi_resource_irq *irq = (struct acpi_resource_irq *)
&res->data.irq;
+ pcres->irq = irq->interrupts[0];
+ }
+ else if (res->id == ACPI_RSTYPE_DMA)
+ {
+ struct acpi_resource_dma *dma = (struct acpi_resource_dma *)
&res->data.dma;
+ pcres->dma = dma->channels[0];
+ }
+
+ return AE_OK;
+}
+
+
+static int acpi_parport_pc_add(struct acpi_device *device)
+{
+ acpi_status status;
+ struct parport_pc_resources pcres;
+ struct parport *pdata;
+
+
+ pcres.io_lo = 0;
+ pcres.io_hi = 0;
+ pcres.irq = PARPORT_IRQ_NONE;
+ pcres.dma = PARPORT_DMA_NONE;
+
+ status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+ acpi_parport_pc_resource, &pcres);
+ if (ACPI_FAILURE(status))
+ return -ENODEV;
+
+ printk("ACPI parport device with low IO 0x%X, high IO 0x%X, IRQ %d,
DMA %d\n", pcres.io_lo, pcres.io_hi, pcres.irq, pcres.dma);
+ if (!(pdata = parport_pc_probe_port (pcres.io_lo, pcres.io_hi,
pcres.irq, pcres.dma, NULL)))
+ {
+ printk("probe of ACPI parport device failed\n");
+ return -ENODEV;
+ }
+
+ acpi_driver_data(device) = pdata;
+ return 0;
+}
+
+static int acpi_parport_pc_remove(struct acpi_device *device, int type)
+{
+ struct parport *pdata = (struct parport *)acpi_driver_data(device);
+ parport_pc_unregister_port(pdata);
+ return 0;
+}
+
+
+static struct acpi_driver parport_pc_acpi_driver = {
+ .name = "parport_pc",
+ .class = "",
+ .ids = "PNP0400, PNP0401",
+ .ops = {
+ .add = acpi_parport_pc_add,
+ .remove = acpi_parport_pc_remove,
+ },
+};
+
+
/* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */
static int __init __attribute__((unused))
parport_pc_find_isa_ports (int autoirq, int autodma)
@@ -2952,10 +3040,14 @@
#endif

/* Onboard SuperIO chipsets that show themselves on the PCI bus. */
+ /*
count += parport_pc_init_superio (autoirq, autodma);
+ */

/* ISA ports and whatever (see asm/parport.h). */
+ /*
count += parport_pc_find_nonpci_ports (autoirq, autodma);
+ */

r = pci_register_driver (&parport_pc_pci_driver);
if (r >= 0) {
@@ -2963,6 +3055,13 @@
count += r;
}

+ r = acpi_bus_register_driver (&parport_pc_acpi_driver);
+ if (ACPI_SUCCESS(r))
+ {
+ registered_parport = 1;
+ /* should we increase count? */
+ }
+
return count;
}

@@ -3060,10 +3159,15 @@
}

ret = !parport_pc_init (io, io_hi, irqval, dmaval);
+ /*
if (ret && registered_parport)
pci_unregister_driver (&parport_pc_pci_driver);

return ret;
+ */
+
+ /* Do not fail if no port is found (perhaps one might be available
through a docking station?) */
+ return 0;
}

void cleanup_module(void)
@@ -3072,7 +3176,10 @@
struct parport *p = parport_enumerate(), *tmp;

if (!user_specified)
+ {
pci_unregister_driver (&parport_pc_pci_driver);
+ acpi_bus_unregister_driver(&parport_pc_acpi_driver);
+ }

while (p) {
tmp = p->next;





>From: DervishD <[email protected]>
>To: Dino Klein <[email protected]>
>Subject: Re: [PATCH 2.6.7] Parallel port detection via ACPI
>Date: Tue, 22 Jun 2004 17:53:23 +0200
>
> Hi Dino :)
>
> * Dino Klein <[email protected]> dixit:
> > I posted the following message on linux-parport at infradead.org;
>however
> > the list seems to be inactive. Here it is again, for anyone interested.
>
> I'm interested, and as soon as one of my linux machines is boot
>again I can test your patch (if the sysadmin allows me...).
>
> I'm interested because I have a long standing problem with the
>parallel port, and it happens in all machines I have at hand. The
>problem is that, no matter how is configured the parallel port in the
>BIOS, Linux always says it is in SPP mode. No matter the motherboard,
>no matter the BIOS vendor, no matter anything. This is the dmesg
>output from one machine, the others are more or less the same:
>
>kernel: parport0: PC-style at 0x378 (0x778), irq 7 [PCSPP,TRISTATE]
>kernel: parport0: Printer, Lexmark International Lexmark Optra E312
>kernel: lp0: using parport0 (interrupt-driven).
>kernel: Trying to free free DMA3
>
> Other times I have this other message:
>
>kernel: parport0: PC-style at 0x378 (0x778) [PCSPP,TRISTATE]
>kernel: parport_pc: Via 686A parallel port: io=0x378
>kernel: lp0: using parport0 (polling).
>
> Most of the machines have Lexmark printers attached, but I've
>tested with different printer brands and that doesn't make a
>difference.
>
> All parallel ports are ECP & EPP capable. I contacted a time ago
>with the maintainers of the parport code, but I had only an answer,
>saying that I should put the ports in the BIOS as ECP or EPP, not as
>'ECP+EPP'. No problem, I did it and it didn't make a difference.
>
> > It utilizes the ACPI subsystem
> > to get the resources assigned to the port, and then passes them on
> > to the detection routine. I've verified that it is working on my
> > machine by cycling between the modes in the BIOS (spp, epp,
> > ecp+epp), and observing proper detection in the logs.
>
> That's exactly what I want! My problem now is that I cannot use
>the parports in any mode different from SPP, and that is very slow,
>and if the printer hangs, breaks, turns off or whatever, the software
>doesn't notice and waits forever!
>
> Abusing of you: is any way of, using the current code in 2.4.x,
>to make my parallel port work in ECP or EPP mode?
>
> Thanks a lot in advance, and thanks for the patch :)
>
> Ra?l N??ez de Arenas Coronado
>
>--
>Linux Registered User 88736
>http://www.pleyades.net & http://raul.pleyades.net/

_________________________________________________________________
MSN Messenger: instale gr?tis e converse com seus amigos.
http://messenger.msn.com.br

2004-06-23 22:26:46

by DervishD

[permalink] [raw]
Subject: Re: [PATCH 2.6.7] Parallel port detection via ACPI

Hi Dino :)

* Dino Klein <[email protected]> dixit:
> ok, here's an adaptation of the same crude patch to 2.4.26; I did not give
> it a try, but it does compile. let me know if it works properly.

Thanks a lot, I'll give it a try as soon as possible :)

Ra?l N??ez de Arenas Coronado

--
Linux Registered User 88736
http://www.pleyades.net & http://raul.pleyades.net/

2004-06-28 02:23:41

by Dino Klein

[permalink] [raw]
Subject: Re: [PATCH 2.6.7] Parallel port detection via ACPI

Hey,
I have one question about using acpi_register_gsi() - this is an ia64 only
thing, right?
Thing is, that I remember an exchange on the acpi mailing list mentioning
that there is no legacy hardware on ia64 systems; wouldn't that also include
the parallel port?




>From: Bjorn Helgaas <[email protected]>
>To: Dino Klein <[email protected]>
>Subject: Re: [PATCH 2.6.7] Parallel port detection via ACPI
>Date: Tue, 22 Jun 2004 17:42:36 -0600
>
>Nice start at this! As you note, it needs a little work. Here are
>a couple things I noticed:
>
> - the ACPI stuff should be under #ifdef CONFIG_ACPI
> - the IRQ should be fed through acpi_register_gsi() (a new
> interface that showed up in BK a few days ago)
> - there are IRQ and extended IRQ structures -- maybe
> should be extended to handle both?
> - seems like it'd be nice to arrange it so we look in
> ACPI first, then fall back to previous detection if
> that fails (probably with a boot-time option to disable
> the ACPI detection in case the firmware is buggy)
>
>Again, good work! I'm glad to see us starting to take advantage
>of this stuff.
>
>Bjorn

_________________________________________________________________
MSN Messenger: instale gr?tis e converse com seus amigos.
http://messenger.msn.com.br