Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Jan 2007 02:28:01 +0900
From:      Takanori Watanabe <takawata@ns.init-main.com>
To:        freebsd-acpi@freebsd.org, sos@freebsd.org
Subject:   Generalize acpi_pci_save_handle and preliminary ATA ACPI support.
Message-ID:  <200701161728.l0GHS1li098861@sana.init-main.com>

next in thread | raw e-mail | index | archive | help
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <98858.1168968471.1@ns.init-main.com>
Content-Transfer-Encoding: 7bit

Oops, I forgot to attach files.
>I wrote preliminary support of ACPI support for PCI ATA device.
>Currently it does nothing but recognize acpi handle.
>To use some support function in PCI, I generalized acpi_pci_save_handle
>and export it as acpi device method.
>
>To support ATA channel it seems that it require some modification to
>ATA driver. 
>
>ACPI has some ATA support. for more information, Section 9.9 of
>ACPI 3.0 specification.
>
>Regards.


------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <98858.1168968471.2@ns.init-main.com>
Content-Transfer-Encoding: 7bit

Index: acpi.c
===================================================================
RCS file: /disk1/ncvs/src/sys/dev/acpica/acpi.c,v
retrieving revision 1.229
diff -u -r1.229 acpi.c
--- acpi.c	21 Sep 2006 18:56:03 -0000	1.229
+++ acpi.c	16 Jan 2007 11:26:15 -0000
@@ -127,6 +127,12 @@
 		    void *context, void **retval);
 static ACPI_STATUS acpi_device_scan_children(device_t bus, device_t dev,
 		    int max_depth, acpi_scan_cb_t user_fn, void *arg);
+
+static void acpi_update_device(ACPI_HANDLE handle, device_t newdev);
+static ACPI_STATUS acpi_device_save_handle_cb(ACPI_HANDLE h, UINT32 level,
+		    void *context, void **retval);
+static int	acpi_device_save_handle(device_t acpi, device_t dev);
+
 static int	acpi_set_powerstate_method(device_t bus, device_t child,
 		    int state);
 static int	acpi_isa_pnp_probe(device_t bus, device_t child,
@@ -188,6 +194,7 @@
     DEVMETHOD(acpi_evaluate_object,	acpi_device_eval_obj),
     DEVMETHOD(acpi_pwr_for_sleep,	acpi_device_pwr_for_sleep),
     DEVMETHOD(acpi_scan_children,	acpi_device_scan_children),
+    DEVMETHOD(acpi_save_handle,		acpi_device_save_handle),
 
     /* PCI emulation */
     DEVMETHOD(pci_set_powerstate,	acpi_set_powerstate_method),
@@ -1384,6 +1391,85 @@
 	acpi_device_scan_cb, &ctx, NULL));
 }
 
+/********************************************
+ *
+ * acpi_device_save_handle() and its helper
+ *
+ ********************************************/
+
+/*
+ * detach direct children of acpi device and attach device to acpi handle.
+ */
+static void acpi_update_device(ACPI_HANDLE handle, device_t newdev)
+{
+	ACPI_STATUS status;
+	device_t olddev;
+	
+	olddev = acpi_get_device(handle);
+        if (olddev != NULL) {
+                KASSERT(!device_is_alive(olddev), ("%s: deleting alive child %s",
+				  __func__, device_get_nameunit(olddev)));
+                KASSERT(device_get_parent(olddev) == acpidev(),
+                    ("%s: child (%s)'s parent is not acpi0", __func__,
+                    acpi_name(handle)));
+                device_delete_child(device_get_parent(olddev), olddev);
+        }
+	
+        /*
+         * Update ACPI-CA to use the enumlated device_t for this handle.
+         */
+        status = AcpiDetachData(handle, acpi_fake_objhandler);
+        if (ACPI_FAILURE(status))
+                printf("WARNING: Unable to detach object data from %s - %s\n",
+                    acpi_name(handle), AcpiFormatException(status));
+        status = AcpiAttachData(handle, acpi_fake_objhandler, newdev);
+        if (ACPI_FAILURE(status))
+                printf("WARNING: Unable to attach object data to %s - %s\n",
+                    acpi_name(handle), AcpiFormatException(status));
+	
+}
+
+
+/*
+ *  per handle process of acpi_device_save_handle
+ */
+static ACPI_STATUS
+acpi_device_save_handle_cb(ACPI_HANDLE h, UINT32 level, void *context, void **status)
+{
+	device_t *devlist;
+	int devcount, i;
+	UINT32 address;
+	ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
+	if (ACPI_FAILURE(acpi_GetInteger(h, "_ADR", &address)))
+		return_ACPI_STATUS (AE_OK);
+	
+        if (device_get_children((device_t)context, &devlist, &devcount) != 0)
+                return_ACPI_STATUS (AE_OK);
+	
+        for (i = 0; i < devcount; i++) {
+		if(acpi_get_adr(devlist[i]) == address){
+			acpi_set_handle(devlist[i], h);
+			acpi_update_device(h, devlist[i]);
+		}
+	}
+	free(devlist, M_TEMP);
+
+	return_ACPI_STATUS(AE_OK);
+}
+
+/*
+ * register acpi handle to device other than direct children of 
+ * acpi device.
+ */
+static int
+acpi_device_save_handle(device_t acpi, device_t dev)
+{
+	AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1, acpi_device_save_handle_cb, dev, NULL);
+	
+	return 0;
+}		
+
+
 /*
  * Even though ACPI devices are not PCI, we use the PCI approach for setting
  * device power states since it's close enough to ACPI.
Index: acpi_if.m
===================================================================
RCS file: /disk1/ncvs/src/sys/dev/acpica/acpi_if.m,v
retrieving revision 1.8
diff -u -r1.8 acpi_if.m
--- acpi_if.m	11 Sep 2005 18:39:01 -0000	1.8
+++ acpi_if.m	16 Jan 2007 12:36:01 -0000
@@ -222,3 +222,19 @@
 	device_t	dev;
 	struct acpi_bst	*bst;
 };
+
+#
+# Save device handles to ivars for children.
+# All children have to be attached to parent and
+# children should be able to access following ivars:
+# 1. read ACPI_IVAR_ADR to get _ADR value.
+# 2. write ACPI_IVAR_HANDLE to set ACPI handle.
+#
+# device_t acpi: ACPI device
+# device_t dev: parent device
+# 
+
+METHOD int save_handle{
+	device_t	acpi;
+	device_t	dev;
+};
Index: acpi_pci.c
===================================================================
RCS file: /disk1/ncvs/src/sys/dev/acpica/acpi_pci.c,v
retrieving revision 1.30
diff -u -r1.30 acpi_pci.c
--- acpi_pci.c	11 May 2006 22:13:20 -0000	1.30
+++ acpi_pci.c	16 Jan 2007 12:11:14 -0000
@@ -73,11 +73,8 @@
 		    uintptr_t *result);
 static int	acpi_pci_write_ivar(device_t dev, device_t child, int which,
 		    uintptr_t value);
-static ACPI_STATUS acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level,
-		    void *context, void **status);
 static int	acpi_pci_set_powerstate_method(device_t dev, device_t child,
 		    int state);
-static void	acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child);
 
 static device_method_t acpi_pci_methods[] = {
 	/* Device interface */
@@ -116,6 +113,10 @@
     case ACPI_IVAR_FLAGS:
 	*result = (uintptr_t)dinfo->ap_flags;
 	return (0);
+    case ACPI_IVAR_ADR:
+	*result = (uintptr_t) (dinfo->ap_dinfo.cfg.slot<<16
+			       |dinfo->ap_dinfo.cfg.func);
+	return (0);
     }
     return (pci_read_ivar(dev, child, which, result));
 }
@@ -196,69 +197,6 @@
 	return (error);
 }
 
-static void
-acpi_pci_update_device(ACPI_HANDLE handle, device_t pci_child)
-{
-	ACPI_STATUS status;
-	device_t child;
-
-	/*
-	 * Lookup and remove the unused device that acpi0 creates when it walks
-	 * the namespace creating devices.
-	 */
-	child = acpi_get_device(handle);
-	if (child != NULL) {
-		KASSERT(!device_is_alive(child), ("%s: deleting alive child %s",
-		    __func__, device_get_nameunit(child)));
-		KASSERT(device_get_parent(child) ==
-		    devclass_get_device(devclass_find("acpi"), 0),
-		    ("%s: child (%s)'s parent is not acpi0", __func__,
-		    acpi_name(handle)));
-		device_delete_child(device_get_parent(child), child);
-	}
-
-	/*
-	 * Update ACPI-CA to use the PCI enumerated device_t for this handle.
-	 */
-	status = AcpiDetachData(handle, acpi_fake_objhandler);
-	if (ACPI_FAILURE(status))
-		printf("WARNING: Unable to detach object data from %s - %s\n",
-		    acpi_name(handle), AcpiFormatException(status));
-	status = AcpiAttachData(handle, acpi_fake_objhandler, pci_child);
-	if (ACPI_FAILURE(status))
-		printf("WARNING: Unable to attach object data to %s - %s\n",
-		    acpi_name(handle), AcpiFormatException(status));
-}
-
-static ACPI_STATUS
-acpi_pci_save_handle(ACPI_HANDLE handle, UINT32 level, void *context,
-    void **status)
-{
-	struct acpi_pci_devinfo *dinfo;
-	device_t *devlist;
-	int devcount, i, func, slot;
-	UINT32 address;
-
-	ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
-
-	if (ACPI_FAILURE(acpi_GetInteger(handle, "_ADR", &address)))
-		return_ACPI_STATUS (AE_OK);
-	slot = ACPI_ADR_PCI_SLOT(address);
-	func = ACPI_ADR_PCI_FUNC(address);
-	if (device_get_children((device_t)context, &devlist, &devcount) != 0)
-		return_ACPI_STATUS (AE_OK);
-	for (i = 0; i < devcount; i++) {
-		dinfo = device_get_ivars(devlist[i]);
-		if (dinfo->ap_dinfo.cfg.func == func &&
-		    dinfo->ap_dinfo.cfg.slot == slot) {
-			dinfo->ap_handle = handle;
-			acpi_pci_update_device(handle, devlist[i]);
-			break;
-		}
-	}
-	free(devlist, M_TEMP);
-	return_ACPI_STATUS (AE_OK);
-}
 
 static int
 acpi_pci_probe(device_t dev)
@@ -298,8 +236,7 @@
 	 * these devices.
 	 */
 	pci_add_children(dev, busno, sizeof(struct acpi_pci_devinfo));
-	AcpiWalkNamespace(ACPI_TYPE_DEVICE, acpi_get_handle(dev), 1,
-	    acpi_pci_save_handle, dev, NULL);
+	ACPI_SAVE_HANDLE(acpidev(), dev);
 
 	return (bus_generic_attach(dev));
 }
Index: acpivar.h
===================================================================
RCS file: /disk1/ncvs/src/sys/dev/acpica/acpivar.h,v
retrieving revision 1.102
diff -u -r1.102 acpivar.h
--- acpivar.h	29 Jul 2006 21:46:15 -0000	1.102
+++ acpivar.h	16 Jan 2007 12:33:22 -0000
@@ -204,6 +204,7 @@
 #define ACPI_IVAR_MAGIC		0x101
 #define ACPI_IVAR_PRIVATE	0x102
 #define ACPI_IVAR_FLAGS		0x103
+#define ACPI_IVAR_ADR		0x104
 
 /*
  * Accessor functions for our ivars.  Default value for BUS_READ_IVAR is
@@ -230,6 +231,7 @@
 __ACPI_BUS_ACCESSOR(acpi, magic, ACPI, MAGIC, int)
 __ACPI_BUS_ACCESSOR(acpi, private, ACPI, PRIVATE, void *)
 __ACPI_BUS_ACCESSOR(acpi, flags, ACPI, FLAGS, int)
+__ACPI_BUS_ACCESSOR(acpi, adr, ACPI, ADR, UINT32)
 
 void acpi_fake_objhandler(ACPI_HANDLE h, UINT32 fn, void *data);
 static __inline device_t
@@ -336,6 +338,11 @@
     void	(*set_end_dependent)(device_t dev, void *context);
 };
 
+
+
+#define acpidev() devclass_get_device(devclass_find("acpi"),0)
+
+
 extern struct	acpi_parse_resource_set acpi_res_parse_set;
 
 void		acpi_config_intr(device_t dev, ACPI_RESOURCE *res);

------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <98858.1168968471.3@ns.init-main.com>
Content-Transfer-Encoding: 7bit

/*-
 * Copyright (c) 2006 Takanori Watanabe
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/dev/ata/ata-pci.c,v 1.117 2006/05/12 05:04:40 jhb Exp $");

#include "opt_ata.h"
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <sys/ata.h>
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/malloc.h>
#include <sys/sema.h>
#include <sys/taskqueue.h>
#include <vm/uma.h>
#include <machine/stdarg.h>
#include <machine/resource.h>
#include <machine/bus.h>
#include <sys/rman.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
#include <dev/ata/ata-all.h>
#include <dev/ata/ata-pci.h>
#include <ata_if.h>

#define ATA_ACPI_PROBE_OK -8

#include <contrib/dev/acpica/acpi.h>
#include <dev/acpica/acpivar.h>
#include "acpi_if.h"
static int  ata_pci_acpi_probe(device_t);
static int ata_pci_acpi_attach(device_t);
static int ata_pci_acpi_read_ivar(device_t, device_t, int , uintptr_t *);
static int ata_pci_acpi_write_ivar(device_t, device_t, int , uintptr_t );
struct ata_pci_controller_acpi {
	struct ata_pci_controller core; /*Must be here.*/
	ACPI_HANDLE acpi_handle[8];
};

struct ata_pci_channel_acpi {
	struct ata_channel core; /*Must be here.*/
	ACPI_HANDLE acpi_handle[8];
};

int ata_pci_acpi_probe(device_t dev)
{
	if(acpi_get_handle(dev) == NULL){
		return ENXIO;
	}
	if(ata_pci_probe(dev)<= 0){
		return ATA_ACPI_PROBE_OK;
	}

	return ENXIO;
}


int ata_pci_acpi_attach(device_t dev)
{
	int result;

	result = ata_pci_attach(dev);
	if(result != 0){
		return result;
	}

	ACPI_SAVE_HANDLE(acpidev(), dev);
	return 0;
}

int ata_pci_acpi_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
{
	struct ata_pci_controller_acpi *sc = device_get_softc(dev);
	struct ata_channel *ch = device_get_softc(child);
	switch (which){	
	case ACPI_IVAR_HANDLE:
		sc->acpi_handle[ch->unit]  = (ACPI_HANDLE) value;
		return 0;
	}
	
	return ENXIO;
}

int ata_pci_acpi_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
{
	struct ata_pci_controller_acpi *sc = device_get_softc(dev);
	struct ata_channel *ch = device_get_softc(child);

	/*Multiple channel device got wrong result,
	  when it is called before calling parent attach*/

	switch (which){	
	case ACPI_IVAR_HANDLE:
		*result = (uintptr_t) sc->acpi_handle[ch->unit];
		return 0;

	case ACPI_IVAR_ADR:
		*result = (uintptr_t) ch->unit;
		return 0;
	}
	/*GENERIC CODE DON'T HAVE THIS METHOD*/
	return ENXIO;
}

static int
ata_pci_acpi_location_str(device_t cbdev, device_t child, char *buf,
    size_t buflen)
{
	struct ata_channel *ch = device_get_softc(child);
	struct ata_pci_controller_acpi *sc = device_get_softc(cbdev);
	
	snprintf(buf, buflen, "channel=%d", ch->unit);

	/*acpi_name should be exported.*/
	if(sc->acpi_handle[ch->unit]){
		strlcat(buf, " handle=", buflen);
		strlcat(buf, acpi_name(sc->acpi_handle[ch->unit]), buflen);
	}
	
	return 0;
}

static device_method_t ata_pci_methods[] = {
    /* device interface */
    DEVMETHOD(device_probe,             ata_pci_acpi_probe),
    DEVMETHOD(device_attach,            ata_pci_acpi_attach),
    DEVMETHOD(device_detach,            ata_pci_detach),
    DEVMETHOD(device_shutdown,          bus_generic_shutdown),
    DEVMETHOD(device_suspend,           bus_generic_suspend),
    DEVMETHOD(device_resume,            bus_generic_resume),

    /* bus methods */
    DEVMETHOD(bus_alloc_resource,       ata_pci_alloc_resource),
    DEVMETHOD(bus_release_resource,     ata_pci_release_resource),
    DEVMETHOD(bus_activate_resource,    bus_generic_activate_resource),
    DEVMETHOD(bus_deactivate_resource,  bus_generic_deactivate_resource),
    DEVMETHOD(bus_setup_intr,           ata_pci_setup_intr),
    DEVMETHOD(bus_teardown_intr,        ata_pci_teardown_intr),

    DEVMETHOD(bus_read_ivar,        ata_pci_acpi_read_ivar),
    DEVMETHOD(bus_write_ivar,       ata_pci_acpi_write_ivar),
    DEVMETHOD(bus_child_location_str,        ata_pci_acpi_location_str),
    { 0, 0 }
};

static driver_t ata_pci_acpi_driver = {
    "atapci",
    ata_pci_methods,
    sizeof(struct ata_pci_controller_acpi),
};

static devclass_t atapciacpi_devclass;

DRIVER_MODULE(atapciacpi, pci, ata_pci_acpi_driver, atapciacpi_devclass, 0, 0);
MODULE_VERSION(atapciacpi, 1);
MODULE_DEPEND(atapciacpi, atapci, 1, 1, 1);

/*Temporally: this should be removed after acpi_name can be accessed without
loading acpi module */
MODULE_DEPEND(atapciacpi, acpi, 1, 1, 1);


------- =_aaaaaaaaaa0--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200701161728.l0GHS1li098861>