1250363Stakawata/*-
2250363Stakawata * Copyright (c) 2013 Takanori Watanabe
3250363Stakawata * All rights reserved.
4250363Stakawata *
5250363Stakawata * Redistribution and use in source and binary forms, with or without
6250363Stakawata * modification, are permitted provided that the following conditions
7250363Stakawata * are met:
8250363Stakawata * 1. Redistributions of source code must retain the above copyright
9250363Stakawata *    notice, this list of conditions and the following disclaimer.
10250363Stakawata * 2. Redistributions in binary form must reproduce the above copyright
11250363Stakawata *    notice, this list of conditions and the following disclaimer in the
12250363Stakawata *    documentation and/or other materials provided with the distribution.
13250363Stakawata *
14250363Stakawata * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15250363Stakawata * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16250363Stakawata * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17250363Stakawata * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18250363Stakawata * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19250363Stakawata * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20250363Stakawata * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21250363Stakawata * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22250363Stakawata * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23250363Stakawata * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24250363Stakawata * SUCH DAMAGE.
25250363Stakawata */
26250363Stakawata
27250363Stakawata#include <sys/cdefs.h>
28250363Stakawata__FBSDID("$FreeBSD: releng/11.0/sys/dev/acpi_support/acpi_rapidstart.c 273377 2014-10-21 07:31:21Z hselasky $");
29250363Stakawata
30250363Stakawata#include "opt_acpi.h"
31250363Stakawata#include <sys/param.h>
32250363Stakawata#include <sys/kernel.h>
33250363Stakawata#include <sys/bus.h>
34250363Stakawata
35250363Stakawata#include <contrib/dev/acpica/include/acpi.h>
36250363Stakawata
37250363Stakawata#include "acpi_if.h"
38250363Stakawata#include <sys/module.h>
39250363Stakawata#include <dev/acpica/acpivar.h>
40250363Stakawata#include <sys/sysctl.h>
41250363Stakawatastatic int sysctl_acpi_rapidstart_gen_handler(SYSCTL_HANDLER_ARGS);
42250363Stakawata
43250363Stakawata
44250363Stakawatastatic struct acpi_rapidstart_name_list
45250363Stakawata{
46250363Stakawata	char *nodename;
47250363Stakawata	char *getmethod;
48250363Stakawata	char *setmethod;
49250363Stakawata	char *comment;
50250363Stakawata} acpi_rapidstart_oids[] ={
51250363Stakawata	{"ffs","GFFS","SFFS","Flash Fast Store Flag"},
52250363Stakawata	{"ftv","GFTV","SFTV","Time value"},
53250363Stakawata	{NULL, NULL, NULL, NULL}
54250363Stakawata};
55250363Stakawata
56250363Stakawatastruct acpi_rapidstart_softc {
57250363Stakawata	struct sysctl_ctx_list	*sysctl_ctx;
58250363Stakawata	struct sysctl_oid	*sysctl_tree;
59250363Stakawata
60250363Stakawata};
61250363Stakawatastatic char    *rapidstart_ids[] = {"INT3392", NULL};
62250363Stakawatastatic int
63250363Stakawataacpi_rapidstart_probe(device_t dev)
64250363Stakawata{
65250363Stakawata	if (acpi_disabled("rapidstart") ||
66250363Stakawata	    ACPI_ID_PROBE(device_get_parent(dev), dev, rapidstart_ids) == NULL ||
67250363Stakawata	    device_get_unit(dev) != 0)
68250363Stakawata		return (ENXIO);
69250363Stakawata
70250363Stakawata	device_set_desc(dev, "Intel Rapid Start ACPI device");
71250363Stakawata
72250363Stakawata	return (0);
73250363Stakawata
74250363Stakawata}
75250363Stakawata
76250363Stakawatastatic int
77250363Stakawataacpi_rapidstart_attach(device_t dev)
78250363Stakawata{
79250363Stakawata	struct acpi_rapidstart_softc *sc;
80250363Stakawata	int i;
81250363Stakawata
82250363Stakawata	sc = device_get_softc(dev);
83250363Stakawata
84250363Stakawata	sc->sysctl_ctx = device_get_sysctl_ctx(dev);
85250363Stakawata	sc->sysctl_tree = device_get_sysctl_tree(dev);
86250363Stakawata	for (i = 0 ; acpi_rapidstart_oids[i].nodename != NULL; i++){
87273377Shselasky		if (acpi_rapidstart_oids[i].setmethod != NULL) {
88273377Shselasky			SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
89273377Shselasky			    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
90273377Shselasky			    i, acpi_rapidstart_oids[i].nodename,
91273377Shselasky			    CTLTYPE_INT | CTLFLAG_RW,
92273377Shselasky			    dev, i, sysctl_acpi_rapidstart_gen_handler, "I",
93273377Shselasky			    acpi_rapidstart_oids[i].comment);
94273377Shselasky		} else {
95273377Shselasky			SYSCTL_ADD_PROC(device_get_sysctl_ctx(dev),
96273377Shselasky			    SYSCTL_CHILDREN(device_get_sysctl_tree(dev)),
97273377Shselasky			    i, acpi_rapidstart_oids[i].nodename,
98273377Shselasky			    CTLTYPE_INT | CTLFLAG_RD,
99273377Shselasky			    dev, i, sysctl_acpi_rapidstart_gen_handler, "I",
100273377Shselasky			    acpi_rapidstart_oids[i].comment);
101273377Shselasky		}
102250363Stakawata	}
103250363Stakawata	return (0);
104250363Stakawata}
105250363Stakawata
106250363Stakawatastatic int
107250363Stakawatasysctl_acpi_rapidstart_gen_handler(SYSCTL_HANDLER_ARGS)
108250363Stakawata{
109250363Stakawata	device_t	dev = arg1;
110250363Stakawata	int 	function = oidp->oid_arg2;
111250363Stakawata	int		error = 0, val;
112250363Stakawata
113250363Stakawata	acpi_GetInteger(acpi_get_handle(dev),
114250363Stakawata	    acpi_rapidstart_oids[function].getmethod, &val);
115250363Stakawata	error = sysctl_handle_int(oidp, &val, 0, req);
116250363Stakawata	if (error || !req->newptr || !acpi_rapidstart_oids[function].setmethod)
117250363Stakawata		return (error);
118250363Stakawata	acpi_SetInteger(acpi_get_handle(dev),
119250363Stakawata	    acpi_rapidstart_oids[function].setmethod, val);
120250363Stakawata	return (0);
121250363Stakawata}
122250363Stakawata
123250363Stakawatastatic device_method_t acpi_rapidstart_methods[] = {
124250363Stakawata	/* Device interface */
125250363Stakawata	DEVMETHOD(device_probe, acpi_rapidstart_probe),
126250363Stakawata	DEVMETHOD(device_attach, acpi_rapidstart_attach),
127250363Stakawata
128250363Stakawata	DEVMETHOD_END
129250363Stakawata};
130250363Stakawata
131250363Stakawatastatic driver_t	acpi_rapidstart_driver = {
132250363Stakawata	"acpi_rapidstart",
133250363Stakawata	acpi_rapidstart_methods,
134250363Stakawata	sizeof(struct acpi_rapidstart_softc),
135250363Stakawata};
136250363Stakawata
137250363Stakawatastatic devclass_t acpi_rapidstart_devclass;
138250363Stakawata
139250363StakawataDRIVER_MODULE(acpi_rapidstart, acpi, acpi_rapidstart_driver, acpi_rapidstart_devclass,
140250363Stakawata	      0, 0);
141250363StakawataMODULE_DEPEND(acpi_rapidstart, acpi, 1, 1, 1);
142250363Stakawata
143