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>