Annotation of sys/dev/acpi/acpidock.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: acpidock.c,v 1.25 2007/04/23 19:29:03 mk Exp $ */
2: /*
3: * Copyright (c) 2006,2007 Michael Knudsen <mk@openbsd.org>
4: *
5: * Permission to use, copy, modify, and distribute this software for any
6: * purpose with or without fee is hereby granted, provided that the above
7: * copyright notice and this permission notice appear in all copies.
8: *
9: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16: */
17:
18: #include <sys/param.h>
19: #include <sys/systm.h>
20: #include <sys/device.h>
21: #include <sys/malloc.h>
22: #include <sys/sensors.h>
23:
24: #include <machine/bus.h>
25:
26: #include <dev/acpi/acpireg.h>
27: #include <dev/acpi/acpivar.h>
28: #include <dev/acpi/acpidev.h>
29: #include <dev/acpi/amltypes.h>
30: #include <dev/acpi/dsdt.h>
31:
32: struct aml_nodelist {
33: struct aml_node *node;
34: TAILQ_ENTRY(aml_nodelist) entries;
35: };
36:
37: int acpidock_match(struct device *, void *, void *);
38: void acpidock_attach(struct device *, struct device *, void *);
39:
40: struct cfattach acpidock_ca = {
41: sizeof(struct acpidock_softc), acpidock_match, acpidock_attach
42: };
43:
44: struct cfdriver acpidock_cd = {
45: NULL, "acpidock", DV_DULL
46: };
47:
48:
49: int acpidock_docklock(struct acpidock_softc *, int);
50: int acpidock_dockctl(struct acpidock_softc *, int);
51: int acpidock_eject(struct acpidock_softc *, struct aml_node *);
52: int acpidock_notify(struct aml_node *, int, void *);
53: int acpidock_status(struct acpidock_softc *);
54:
55: void acpidock_foundejd(struct aml_node *, void *);
56:
57: int
58: acpidock_match(struct device *parent, void *match, void *aux)
59: {
60: struct acpi_attach_args *aaa = aux;
61: struct cfdata *cf = match;
62:
63: /* sanity */
64: if (aaa->aaa_name == NULL ||
65: strcmp(aaa->aaa_name, cf->cf_driver->cd_name) != 0 ||
66: aaa->aaa_table != NULL)
67: return (0);
68:
69: return (1);
70: }
71:
72: void
73: acpidock_attach(struct device *parent, struct device *self, void *aux)
74: {
75: struct acpidock_softc *sc = (struct acpidock_softc *)self;
76: struct acpi_attach_args *aa = aux;
77: extern struct aml_node aml_root;
78:
79: sc->sc_acpi = (struct acpi_softc *)parent;
80: sc->sc_devnode = aa->aaa_node->child;
81:
82: printf(": %s", sc->sc_devnode->parent->name);
83:
84: acpidock_status(sc);
85: if (sc->sc_docked == ACPIDOCK_STATUS_DOCKED) {
86: acpidock_docklock(sc, 1);
87: acpidock_dockctl(sc, 1);
88: } else {
89: acpidock_dockctl(sc, 0);
90: acpidock_docklock(sc, 0);
91: }
92:
93: acpidock_status(sc);
94: printf(":%s docked (%d)\n",
95: sc->sc_docked == ACPIDOCK_STATUS_DOCKED ? "" : " not",
96: sc->sc_sta);
97:
98: strlcpy(sc->sc_sensdev.xname, DEVNAME(sc),
99: sizeof(sc->sc_sensdev.xname));
100: if (sc->sc_docked)
101: strlcpy(sc->sc_sens.desc, "docked",
102: sizeof(sc->sc_sens.desc));
103: else
104: strlcpy(sc->sc_sens.desc, "not docked",
105: sizeof(sc->sc_sens.desc));
106:
107: sc->sc_sens.type = SENSOR_INDICATOR;
108: sc->sc_sens.value = sc->sc_docked == ACPIDOCK_STATUS_DOCKED;
109: sensor_attach(&sc->sc_sensdev, &sc->sc_sens);
110: sensordev_install(&sc->sc_sensdev);
111:
112: TAILQ_INIT(&sc->sc_deps_h);
113: aml_find_node(aml_root.child, "_EJD", acpidock_foundejd, sc);
114:
115: aml_register_notify(sc->sc_devnode->parent, aa->aaa_dev,
116: acpidock_notify, sc, ACPIDEV_NOPOLL);
117:
118: }
119:
120: int
121: acpidock_status(struct acpidock_softc *sc)
122: {
123: struct aml_value res;
124: int rv;
125:
126: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_STA", 0, NULL,
127: &res) != 0)
128: rv = 0;
129: else
130: rv = 1;
131:
132: sc->sc_sta = aml_val2int(&res);
133:
134: sc->sc_docked = sc->sc_sta & STA_PRESENT;
135:
136: aml_freevalue(&res);
137:
138: return (rv);
139: }
140:
141: int
142: acpidock_docklock(struct acpidock_softc *sc, int lock)
143: {
144: struct aml_value cmd;
145: struct aml_value res;
146: int rv;
147:
148: memset(&cmd, 0, sizeof cmd);
149: cmd.v_integer = lock;
150: cmd.type = AML_OBJTYPE_INTEGER;
151: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_LCK", 1, &cmd,
152: &res) != 0) {
153: dnprintf(20, "%s: _LCK %d failed\n", DEVNAME(sc), lock);
154:
155: rv = 0;
156: } else {
157: dnprintf(20, "%s: _LCK %d successful\n", DEVNAME(sc), lock);
158:
159: rv = 1;
160: }
161:
162: aml_freevalue(&res);
163:
164: return rv;
165: }
166:
167: int
168: acpidock_dockctl(struct acpidock_softc *sc, int dock)
169: {
170: struct aml_value cmd;
171: struct aml_value res;
172: int rv;
173:
174: memset(&cmd, 0, sizeof cmd);
175: cmd.v_integer = dock;
176: cmd.type = AML_OBJTYPE_INTEGER;
177: if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_DCK", 1, &cmd,
178: &res) != 0) {
179: /* XXX */
180: dnprintf(15, "%s: _DCK %d failed\n", DEVNAME(sc), dock);
181:
182: rv = 0;
183: } else {
184: dnprintf(15, "%s: _DCK %d successful\n", DEVNAME(sc), dock);
185:
186: rv = 1;
187: }
188:
189: aml_freevalue(&res);
190:
191: return rv;
192: }
193:
194: int
195: acpidock_eject(struct acpidock_softc *sc, struct aml_node *node)
196: {
197: struct aml_value cmd;
198: struct aml_value res;
199: int rv;
200:
201: memset(&cmd, 0, sizeof cmd);
202: cmd.v_integer = 1;
203: cmd.type = AML_OBJTYPE_INTEGER;
204: if (aml_evalname(sc->sc_acpi, node, "_EJ0", 1, &cmd,
205: &res) != 0) {
206: /* XXX */
207: dnprintf(15, "%s: _EJ0 failed\n", DEVNAME(sc));
208:
209: rv = 0;
210: } else {
211: dnprintf(15, "%s: _EJ0 successful\n", DEVNAME(sc));
212:
213: rv = 1;
214: }
215:
216: aml_freevalue(&res);
217:
218: return rv;
219: }
220:
221: int
222: acpidock_notify(struct aml_node *node, int notify_type, void *arg)
223: {
224: struct acpidock_softc *sc = arg;
225:
226: dnprintf(5, "%s: acpidock_notify: notify %d\n", DEVNAME(sc),
227: notify_type);
228:
229: switch (notify_type) {
230: case ACPIDOCK_EVENT_INSERT:
231: printf("%s: dock", DEVNAME(sc));
232: acpidock_docklock(sc, 1);
233: acpidock_dockctl(sc, 1);
234:
235: break;
236: case ACPIDOCK_EVENT_EJECT: {
237: struct aml_nodelist *n;
238:
239: TAILQ_FOREACH(n, &sc->sc_deps_h, entries)
240: acpidock_eject(sc, n->node);
241:
242: acpidock_dockctl(sc, 0);
243: acpidock_docklock(sc, 0);
244:
245: /* now actually undock */
246: acpidock_eject(sc, sc->sc_devnode);
247:
248: printf("%s: undock", DEVNAME(sc));
249:
250: break;
251: }
252: }
253:
254: acpidock_status(sc);
255: sc->sc_sens.value = sc->sc_docked == ACPIDOCK_STATUS_DOCKED;
256: if (sc->sc_docked)
257: strlcpy(sc->sc_sens.desc, "docked",
258: sizeof(sc->sc_sens.desc));
259: else
260: strlcpy(sc->sc_sens.desc, "not docked",
261: sizeof(sc->sc_sens.desc));
262:
263: printf(": status %s\n",
264: sc->sc_docked == ACPIDOCK_STATUS_DOCKED ? "docked" : "undocked");
265:
266: return (0);
267: }
268:
269: void
270: acpidock_foundejd(struct aml_node *node, void *arg)
271: {
272: struct acpidock_softc *sc = (struct acpidock_softc *)arg;
273: struct aml_value res;
274:
275: dnprintf(15, "%s: %s", DEVNAME(sc), node->parent->name);
276:
277: if (aml_evalnode(sc->sc_acpi, node, 0, NULL, &res) == -1) {
278: printf(": error\n");
279: } else {
280: struct aml_nodelist *n;
281:
282: /* XXX debug */
283: dnprintf(10, "%s: %s depends on %s\n", DEVNAME(sc),
284: node->parent->name, res.v_string);
285:
286: /* XXX more than one dock? */
287:
288: n = malloc(sizeof(struct aml_nodelist), M_DEVBUF, M_WAITOK);
289: n->node = node->parent;
290:
291: TAILQ_INSERT_TAIL(&sc->sc_deps_h, n, entries);
292: }
293:
294: aml_freevalue(&res);
295: }
CVSweb