Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/i86pc/io/ppm/acpippm.c
+++ new/usr/src/uts/i86pc/io/ppm/acpippm.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 * Copyright (c) 2011 Bayard G. Bell. All rights reserved.
26 26 */
27 27
28 28 #include <sys/types.h>
29 29 #include <sys/conf.h>
30 30 #include <sys/open.h>
31 31 #include <sys/modctl.h>
32 32 #include <sys/promif.h>
33 33 #include <sys/stat.h>
34 34 #include <sys/ddi_impldefs.h>
35 35 #include <sys/ddi.h>
36 36 #include <sys/sunddi.h>
37 37 #include <sys/epm.h>
38 38 #include <sys/acpi/acpi.h>
39 39 #include <sys/acpica.h>
40 40 #include <sys/psm_types.h>
41 41
42 42 /*
43 43 * ACPI Power Management Driver
44 44 *
45 45 * acpippm deals with those bits of ppm functionality that
46 46 * must be mediated by ACPI
47 47 *
48 48 * The routines in this driver is referenced by Platform
49 49 * Power Management driver of X86 workstation systems.
50 50 * acpippm driver is loaded because it is listed as a platform driver
51 51 * It is initially configured as a pseudo driver.
52 52 */
53 53 extern void pc_tod_set_rtc_offsets(ACPI_TABLE_FADT *);
54 54 extern int acpica_use_safe_delay;
55 55
56 56 /*
57 57 * Configuration Function prototypes and data structures
58 58 */
59 59 static int appm_attach(dev_info_t *, ddi_attach_cmd_t);
60 60 static int appm_detach(dev_info_t *, ddi_detach_cmd_t);
61 61 static int appm_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
62 62 static int appm_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p);
63 63 static int appm_close(dev_t dev, int flag, int otyp, cred_t *cred_p);
64 64 static int appm_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
65 65
66 66 /*
67 67 * Configuration data structures
68 68 */
69 69 static struct cb_ops appm_cbops = {
70 70 appm_open, /* open */
71 71 appm_close, /* close */
72 72 nodev, /* strategy */
73 73 nodev, /* print */
74 74 nodev, /* dump */
75 75 nodev, /* read */
76 76 nodev, /* write */
77 77 appm_ioctl, /* ioctl */
78 78 nodev, /* devmap */
79 79 nodev, /* mmap */
80 80 nodev, /* segmap */
81 81 nochpoll, /* chpoll */
82 82 ddi_prop_op, /* prop_op */
83 83 NULL, /* stream */
84 84 D_MP | D_NEW, /* flag */
85 85 CB_REV, /* rev */
86 86 nodev, /* aread */
87 87 nodev, /* awrite */
88 88 };
89 89
90 90 static struct dev_ops appm_ops = {
91 91 DEVO_REV, /* devo_rev */
92 92 0, /* refcnt */
93 93 appm_getinfo, /* getinfo */
94 94 nulldev, /* identify */
95 95 nulldev, /* probe */
96 96 appm_attach, /* attach */
97 97 appm_detach, /* detach */
98 98 nodev, /* reset */
99 99 &appm_cbops, /* cb_ops */
100 100 NULL, /* bus_ops */
101 101 NULL, /* power */
102 102 ddi_quiesce_not_needed, /* quiesce */
103 103 };
104 104
↓ open down ↓ |
104 lines elided |
↑ open up ↑ |
105 105 extern struct mod_ops mod_driverops;
106 106
107 107 static struct modldrv modldrv = {
108 108 &mod_driverops,
109 109 "ACPI ppm driver",
110 110 &appm_ops,
111 111 };
112 112
113 113 static struct modlinkage modlinkage = {
114 114 MODREV_1,
115 - &modldrv,
116 - NULL
115 + { &modldrv, NULL }
117 116 };
118 117
119 118 /*
120 119 * Driver state structure
121 120 */
122 121 typedef struct {
123 122 dev_info_t *dip;
124 123 ddi_acc_handle_t devid_hndl;
125 124 ddi_acc_handle_t estar_hndl;
126 125 int lyropen; /* ref count */
127 126 } appm_unit;
128 127
129 128 /*
130 129 * Driver global variables
131 130 *
132 131 * appm_lock synchronize the access of lyr handle to each appm
133 132 * minor device, therefore write to tomatillo device is
134 133 * sequentialized. Lyr protocol requires pairing up lyr open
135 134 * and close, so only a single reference is allowed per minor node.
136 135 */
137 136 static void *appm_statep;
138 137 static kmutex_t appm_lock;
139 138
140 139 /*
141 140 * S3 stuff:
142 141 */
143 142 extern int acpi_enter_sleepstate(s3a_t *);
144 143 extern int acpi_exit_sleepstate(s3a_t *);
145 144
146 145
147 146 int
148 147 _init(void)
149 148 {
150 149 int error;
151 150
152 151 if ((error = ddi_soft_state_init(&appm_statep,
153 152 sizeof (appm_unit), 0)) != DDI_SUCCESS) {
154 153 return (error);
155 154 }
156 155
157 156 mutex_init(&appm_lock, NULL, MUTEX_DRIVER, NULL);
158 157
159 158 if ((error = mod_install(&modlinkage)) != DDI_SUCCESS) {
160 159 mutex_destroy(&appm_lock);
161 160 ddi_soft_state_fini(&appm_statep);
162 161 return (error);
163 162 }
164 163
165 164 return (error);
166 165 }
167 166
168 167 int
169 168 _fini(void)
170 169 {
171 170 int error;
172 171
173 172 if ((error = mod_remove(&modlinkage)) == DDI_SUCCESS) {
174 173 mutex_destroy(&appm_lock);
175 174 ddi_soft_state_fini(&appm_statep);
176 175 }
177 176
178 177 return (error);
179 178
180 179 }
181 180
182 181 int
183 182 _info(struct modinfo *modinfop)
184 183 {
185 184 return (mod_info(&modlinkage, modinfop));
186 185 }
187 186
188 187
189 188
190 189 /*
191 190 * Driver attach(9e) entry point
192 191 */
193 192 static int
194 193 appm_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
195 194 {
196 195 char *str = "appm_attach";
197 196 int instance;
198 197 appm_unit *unitp;
199 198 ACPI_TABLE_FADT *fadt = NULL;
200 199 int rv = DDI_SUCCESS;
201 200
202 201 switch (cmd) {
203 202 case DDI_ATTACH:
204 203 break;
205 204 case DDI_RESUME:
206 205 return (DDI_SUCCESS);
207 206 default:
208 207 cmn_err(CE_WARN, "%s: cmd %d unsupported.\n", str, cmd);
209 208 return (DDI_FAILURE);
210 209 }
211 210
212 211 instance = ddi_get_instance(dip);
213 212 rv = ddi_soft_state_zalloc(appm_statep, instance);
214 213 if (rv != DDI_SUCCESS) {
215 214 cmn_err(CE_WARN, "%s: failed alloc for dev(%s@%s)",
216 215 str, ddi_binding_name(dip),
217 216 ddi_get_name_addr(dip) ? ddi_get_name_addr(dip) : " ");
218 217 return (rv);
219 218 }
220 219
221 220 if ((unitp = ddi_get_soft_state(appm_statep, instance)) == NULL) {
222 221 rv = DDI_FAILURE;
223 222 goto doerrs;
224 223 }
225 224
226 225 /*
227 226 * Export "ddi-kernel-ioctl" property - prepared to support
228 227 * kernel ioctls (driver layering).
229 228 * XXX is this still needed?
230 229 * XXXX (RSF) Not that I am aware of.
231 230 */
232 231 rv = ddi_prop_create(DDI_DEV_T_NONE, dip, DDI_PROP_CANSLEEP,
233 232 DDI_KERNEL_IOCTL, NULL, 0);
234 233 if (rv != DDI_PROP_SUCCESS)
235 234 goto doerrs;
236 235
237 236 ddi_report_dev(dip);
238 237 unitp->dip = dip;
239 238
240 239 /*
241 240 * XXX here we would do whatever we need to to determine if the
242 241 * XXX platform supports ACPI, and fail the attach if not.
243 242 * XXX If it does, we do whatever setup is needed to get access to
244 243 * XXX ACPI register space.
245 244 */
246 245
247 246 unitp->lyropen = 0;
248 247
249 248 /*
250 249 * create minor node for kernel_ioctl calls
251 250 */
252 251 rv = ddi_create_minor_node(dip, "acpi-ppm", S_IFCHR, instance, 0, 0);
253 252 if (rv != DDI_SUCCESS)
254 253 goto doerrs;
255 254
256 255 /* Get the FADT */
257 256 if (AcpiGetTable(ACPI_SIG_FADT, 1,
258 257 (ACPI_TABLE_HEADER **)&fadt) != AE_OK)
259 258 return (rv);
260 259
261 260 /* Init the RTC offsets */
262 261 if (fadt != NULL)
263 262 pc_tod_set_rtc_offsets(fadt);
264 263
265 264 return (rv);
266 265
267 266 doerrs:
268 267
269 268 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS |
270 269 DDI_PROP_NOTPROM, DDI_KERNEL_IOCTL))
271 270 ddi_prop_remove_all(dip);
272 271
273 272 ddi_soft_state_free(appm_statep, instance);
274 273
275 274 return (rv);
276 275 }
277 276
278 277
279 278 /*
280 279 * Driver getinfo(9e) entry routine
281 280 */
282 281 /* ARGSUSED */
283 282 static int
284 283 appm_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
285 284 {
286 285 appm_unit *unitp;
287 286 int instance;
288 287
289 288 switch (cmd) {
290 289 case DDI_INFO_DEVT2DEVINFO:
291 290 instance = getminor((dev_t)arg);
292 291 unitp = ddi_get_soft_state(appm_statep, instance);
293 292 if (unitp == NULL) {
294 293 return (DDI_FAILURE);
295 294 }
296 295 *result = (void *) unitp->dip;
297 296 return (DDI_SUCCESS);
298 297
299 298 case DDI_INFO_DEVT2INSTANCE:
300 299 instance = getminor((dev_t)arg);
301 300 *result = (void *)(uintptr_t)instance;
302 301 return (DDI_SUCCESS);
303 302
304 303 default:
305 304 return (DDI_FAILURE);
306 305 }
307 306 }
308 307
309 308
310 309 /*
311 310 * detach(9e)
312 311 */
313 312 /* ARGSUSED */
314 313 static int
315 314 appm_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
316 315 {
317 316 char *str = "appm_detach";
318 317
319 318 switch (cmd) {
320 319 case DDI_DETACH:
321 320 return (DDI_FAILURE);
322 321 case DDI_SUSPEND:
323 322 return (DDI_SUCCESS);
324 323 default:
325 324 cmn_err(CE_WARN, "%s: cmd %d unsupported", str, cmd);
326 325 return (DDI_FAILURE);
327 326 }
328 327 }
329 328
330 329
331 330 /* ARGSUSED */
332 331 static int
333 332 appm_open(dev_t *dev_p, int flag, int otyp, cred_t *cred_p)
334 333 {
335 334 appm_unit *unitp;
336 335
337 336 /* not intended to allow sysadmin level root process to open it */
338 337 if (drv_priv(cred_p) != DDI_SUCCESS)
339 338 return (EPERM);
340 339
341 340 if ((unitp = ddi_get_soft_state(
342 341 appm_statep, getminor(*dev_p))) == NULL) {
343 342 cmn_err(CE_WARN, "appm_open: failed to get soft state!");
344 343 return (DDI_FAILURE);
345 344 }
346 345
347 346 mutex_enter(&appm_lock);
348 347 if (unitp->lyropen != 0) {
349 348 mutex_exit(&appm_lock);
350 349 return (EBUSY);
351 350 }
352 351 unitp->lyropen++;
353 352 mutex_exit(&appm_lock);
354 353
355 354 return (DDI_SUCCESS);
356 355 }
357 356
358 357
359 358 /* ARGSUSED */
360 359 static int
361 360 appm_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
362 361 {
363 362 appm_unit *unitp;
364 363
365 364 if ((unitp =
366 365 ddi_get_soft_state(appm_statep, getminor(dev))) == NULL)
367 366 return (DDI_FAILURE);
368 367
369 368 mutex_enter(&appm_lock);
370 369 unitp->lyropen = 0;
371 370 mutex_exit(&appm_lock);
372 371
373 372 return (DDI_SUCCESS);
374 373 }
375 374
376 375
377 376 /*
378 377 * must match ppm.conf
379 378 */
380 379 #define APPMIOC ('A' << 8)
381 380 #define APPMIOC_ENTER_S3 (APPMIOC | 1) /* arg *s3a_t */
382 381 #define APPMIOC_EXIT_S3 (APPMIOC | 2) /* arg *s3a_t */
383 382
384 383 /* ARGSUSED3 */
385 384 static int
386 385 appm_ioctl(dev_t dev, int cmd, intptr_t arg, int flag,
387 386 cred_t *cred_p, int *rval_p)
388 387 {
389 388 static boolean_t acpi_initted = B_FALSE;
390 389 char *str = "appm_ioctl";
391 390 int ret;
392 391 s3a_t *s3ap = (s3a_t *)arg;
393 392
394 393 PMD(PMD_SX, ("%s: called with %x\n", str, cmd))
395 394
396 395 if (drv_priv(cred_p) != 0) {
397 396 PMD(PMD_SX, ("%s: EPERM\n", str))
398 397 return (EPERM);
399 398 }
400 399
401 400 if (ddi_get_soft_state(appm_statep, getminor(dev)) == NULL) {
402 401 PMD(PMD_SX, ("%s: no soft state: EIO\n", str))
403 402 return (EIO);
404 403 }
405 404
406 405 if (!acpi_initted) {
407 406 PMD(PMD_SX, ("%s: !acpi_initted\n", str))
408 407 if (acpica_init() == 0) {
409 408 acpi_initted = B_TRUE;
410 409 } else {
411 410 if (rval_p != NULL) {
412 411 *rval_p = EINVAL;
413 412 }
414 413 PMD(PMD_SX, ("%s: EINVAL\n", str))
415 414 return (EINVAL);
416 415 }
417 416 }
418 417
419 418 PMD(PMD_SX, ("%s: looking for cmd %x\n", str, cmd))
420 419 switch (cmd) {
421 420 case APPMIOC_ENTER_S3:
422 421 /*
423 422 * suspend to RAM (ie S3)
424 423 */
425 424 PMD(PMD_SX, ("%s: cmd %x, arg %p\n", str, cmd, (void *)arg))
426 425 acpica_use_safe_delay = 1;
427 426 ret = acpi_enter_sleepstate(s3ap);
428 427 break;
429 428
430 429 case APPMIOC_EXIT_S3:
431 430 /*
432 431 * return from S3
433 432 */
434 433 PMD(PMD_SX, ("%s: cmd %x, arg %p\n", str, cmd, (void *)arg))
435 434 ret = acpi_exit_sleepstate(s3ap);
436 435 acpica_use_safe_delay = 0;
437 436 break;
438 437
439 438 default:
440 439 PMD(PMD_SX, ("%s: cmd %x unrecognized: ENOTTY\n", str, cmd))
441 440 return (ENOTTY);
442 441 }
443 442
444 443 /*
445 444 * upon failure return EINVAL
446 445 */
447 446 if (ret != 0) {
448 447 if (rval_p != NULL) {
449 448 *rval_p = EINVAL;
450 449 }
451 450 return (EINVAL);
452 451 }
453 452
454 453 return (0);
455 454 }
↓ open down ↓ |
329 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX