1 /*- 2 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org> 3 * Copyright (c) 2000 Michael Smith <msmith@freebsd.org> 4 * Copyright (c) 2000 BSDi 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 * 28 * $FreeBSD$ 29 */ 30 31 #include "bus_if.h" 32 #include <sys/eventhandler.h> 33 34 extern devclass_t acpi_devclass; 35 36 struct acpi_softc { 37 device_t acpi_dev; 38 dev_t acpi_dev_t; 39 40 struct resource *acpi_irq; 41 int acpi_irq_rid; 42 void *acpi_irq_handle; 43 44 int acpi_enabled; 45 int acpi_sstate; 46 47 #define ACPI_POWER_BUTTON_DEFAULT_SX ACPI_STATE_S5; 48 #define ACPI_SLEEP_BUTTON_DEFAULT_SX ACPI_STATE_S1; 49 #define ACPI_LID_SWITCH_DEFAULT_SX ACPI_STATE_S1; 50 int acpi_power_button_sx; 51 int acpi_sleep_button_sx; 52 int acpi_lid_switch_sx; 53 }; 54 55 struct acpi_device { 56 /* ACPI ivars */ 57 ACPI_HANDLE ad_handle; 58 int ad_magic; 59 void *ad_private; 60 61 /* resources */ 62 struct resource_list ad_rl; 63 }; 64 65 /* 66 * This is a cheap and nasty way to get around the horrid counted list 67 * argument format that AcpiEvalateMethod uses. 68 */ 69 #define ACPI_OBJECTLIST_MAX 16 70 struct acpi_object_list { 71 UINT32 count; 72 ACPI_OBJECT *pointer[ACPI_OBJECTLIST_MAX]; 73 ACPI_OBJECT object[ACPI_OBJECTLIST_MAX]; 74 }; 75 76 static __inline struct acpi_object_list * 77 acpi_AllocObjectList(int nobj) { 78 struct acpi_object_list *l; 79 int i; 80 81 if (nobj > ACPI_OBJECTLIST_MAX) 82 return(NULL); 83 if ((l = AcpiOsAllocate(sizeof(*l))) == NULL) 84 return(NULL); 85 bzero(l, sizeof(*l)); 86 for (i = 0; i < ACPI_OBJECTLIST_MAX; i++) 87 l->pointer[i] = &l->object[i]; 88 l->count = nobj; 89 return(l); 90 } 91 92 #define ACPI_IVAR_HANDLE 0x100 93 #define ACPI_IVAR_MAGIC 0x101 94 #define ACPI_IVAR_PRIVATE 0x102 95 96 static __inline ACPI_HANDLE 97 acpi_get_handle(device_t dev) { 98 ACPI_HANDLE h; 99 100 if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_HANDLE, (uintptr_t *)&h)) 101 return(NULL); 102 return(h); 103 } 104 105 static __inline int 106 acpi_set_handle(device_t dev, ACPI_HANDLE h) { 107 return(BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_HANDLE, (uintptr_t)h)); 108 } 109 110 static __inline int 111 acpi_get_magic(device_t dev) { 112 int m; 113 114 if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_MAGIC, (uintptr_t *)&m)) 115 return(0); 116 return(m); 117 } 118 119 static __inline int 120 acpi_set_magic(device_t dev, int m) { 121 return(BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_MAGIC, (uintptr_t)m)); 122 } 123 124 static __inline void * 125 acpi_get_private(device_t dev) { 126 void *p; 127 128 if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_PRIVATE, (uintptr_t *)&p)) 129 return(NULL); 130 return(p); 131 } 132 133 static __inline int 134 acpi_set_private(device_t dev, void *p) { 135 return(BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_PRIVATE, (uintptr_t)p)); 136 } 137 138 static __inline ACPI_OBJECT_TYPE 139 acpi_get_type(device_t dev) { 140 ACPI_HANDLE h; 141 ACPI_OBJECT_TYPE t; 142 143 if ((h = acpi_get_handle(dev)) == NULL) 144 return(ACPI_TYPE_NOT_FOUND); 145 if (AcpiGetType(h, &t) != AE_OK) 146 return(ACPI_TYPE_NOT_FOUND); 147 return(t); 148 } 149 150 #ifdef ENABLE_DEBUGGER 151 extern void acpi_EnterDebugger(void); 152 #endif 153 154 extern BOOLEAN acpi_MatchHid(device_t dev, char *hid); 155 extern ACPI_STATUS acpi_GetIntoBuffer(ACPI_HANDLE handle, 156 ACPI_STATUS (*func)(ACPI_HANDLE, ACPI_BUFFER *), 157 ACPI_BUFFER *buf); 158 extern ACPI_BUFFER *acpi_AllocBuffer(int size); 159 extern ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state); 160 extern ACPI_STATUS acpi_Enable(struct acpi_softc *sc); 161 extern ACPI_STATUS acpi_Disable(struct acpi_softc *sc); 162 extern BOOLEAN acpi_DeviceIsPresent(device_t dev); 163 extern ACPI_STATUS acpi_EvaluateNumber(ACPI_HANDLE handle, char *path, int *number); 164 165 struct acpi_parse_resource_set { 166 void (* set_init)(device_t dev, void **context); 167 void (* set_done)(device_t dev, void *context); 168 void (* set_ioport)(device_t dev, void *context, u_int32_t base, u_int32_t length); 169 void (* set_iorange)(device_t dev, void *context, u_int32_t low, u_int32_t high, 170 u_int32_t length, u_int32_t align); 171 void (* set_memory)(device_t dev, void *context, u_int32_t base, u_int32_t length); 172 void (* set_memoryrange)(device_t dev, void *context, u_int32_t low, u_int32_t high, 173 u_int32_t length, u_int32_t align); 174 void (* set_irq)(device_t dev, void *context, u_int32_t irq); 175 void (* set_drq)(device_t dev, void *context, u_int32_t drq); 176 void (* set_start_dependant)(device_t dev, void *context, int preference); 177 void (* set_end_dependant)(device_t dev, void *context); 178 }; 179 180 extern struct acpi_parse_resource_set acpi_res_parse_set; 181 extern ACPI_STATUS acpi_parse_resources(device_t dev, ACPI_HANDLE handle, 182 struct acpi_parse_resource_set *set); 183 184 /* XXX this is ugly */ 185 extern char *acpi_strerror(ACPI_STATUS excep); 186 187 /* 188 * ACPI event handling 189 */ 190 extern UINT32 acpi_eventhandler_power_button_for_sleep(void *context); 191 extern UINT32 acpi_eventhandler_power_button_for_wakeup(void *context); 192 extern UINT32 acpi_eventhandler_sleep_button_for_sleep(void *context); 193 extern UINT32 acpi_eventhandler_sleep_button_for_wakeup(void *context); 194 195 #define ACPI_EVENT_PRI_FIRST 0 196 #define ACPI_EVENT_PRI_DEFAULT 10000 197 #define ACPI_EVENT_PRI_LAST 20000 198 199 typedef void (*acpi_event_handler_t) __P((void *, int)); 200 201 EVENTHANDLER_DECLARE(acpi_sleep_event, acpi_event_handler_t); 202 EVENTHANDLER_DECLARE(acpi_wakeup_event, acpi_event_handler_t); 203 204 /* 205 * Misc. 206 */ 207 static __inline struct acpi_softc * 208 acpi_device_get_parent_softc(device_t child) 209 { 210 device_t parent; 211 212 parent = device_get_parent(child); 213 if (parent == NULL) { 214 return(NULL); 215 } 216 return(device_get_softc(parent)); 217 } 218 219 extern char *acpi_name(ACPI_HANDLE handle); 220 extern int acpi_avoid(ACPI_HANDLE handle); 221 222