[PATCH 2.6.7] Parallel port detection via ACPI

From: Dino Klein
Date: Tue Jun 22 2004 - 10:30:22 EST


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" <dinoklein@xxxxxxxxxxx>
To: linux-parport@xxxxxxxxxxxxxxxxxxx
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

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/