1157774Siwasaki/*- 2157774Siwasaki * Copyright (c) 2005-2006 Mitsuru IWASAKI <iwasaki@FreeBSD.org> 3157774Siwasaki * All rights reserved. 4157774Siwasaki * 5157774Siwasaki * Redistribution and use in source and binary forms, with or without 6157774Siwasaki * modification, are permitted provided that the following conditions 7157774Siwasaki * are met: 8157774Siwasaki * 1. Redistributions of source code must retain the above copyright 9157774Siwasaki * notice, this list of conditions and the following disclaimer. 10157774Siwasaki * 2. Redistributions in binary form must reproduce the above copyright 11157774Siwasaki * notice, this list of conditions and the following disclaimer in the 12157774Siwasaki * documentation and/or other materials provided with the distribution. 13157774Siwasaki * 14157774Siwasaki * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15157774Siwasaki * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16157774Siwasaki * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17157774Siwasaki * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18157774Siwasaki * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19157774Siwasaki * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20157774Siwasaki * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21157774Siwasaki * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22157774Siwasaki * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23157774Siwasaki * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24157774Siwasaki * SUCH DAMAGE. 25157774Siwasaki * 26157774Siwasaki * $FreeBSD$ 27157774Siwasaki */ 28157774Siwasaki 29157774Siwasaki#include "opt_acpi.h" 30157774Siwasaki#include <sys/param.h> 31159855Snjl#include <sys/bus.h> 32157774Siwasaki#include <sys/kernel.h> 33157774Siwasaki#include <sys/module.h> 34157774Siwasaki 35193530Sjkim#include <contrib/dev/acpica/include/acpi.h> 36193530Sjkim#include <contrib/dev/acpica/include/accommon.h> 37193530Sjkim 38157774Siwasaki#include <dev/acpica/acpivar.h> 39157774Siwasaki#include <dev/acpica/acpiio.h> 40157774Siwasaki 41157774Siwasaki/* Hooks for the ACPI CA debugging infrastructure */ 42157774Siwasaki#define _COMPONENT ACPI_DOCK 43157774SiwasakiACPI_MODULE_NAME("DOCK") 44157774Siwasaki 45157774Siwasaki/* For Docking status */ 46157774Siwasaki#define ACPI_DOCK_STATUS_UNKNOWN -1 47157774Siwasaki#define ACPI_DOCK_STATUS_UNDOCKED 0 48157774Siwasaki#define ACPI_DOCK_STATUS_DOCKED 1 49157774Siwasaki 50161065Snjl#define ACPI_DOCK_UNLOCK 0 /* Allow device to be ejected */ 51161065Snjl#define ACPI_DOCK_LOCK 1 /* Prevent dev from being removed */ 52159855Snjl 53161065Snjl#define ACPI_DOCK_ISOLATE 0 /* Isolate from dock connector */ 54161065Snjl#define ACPI_DOCK_CONNECT 1 /* Connect to dock */ 55161065Snjl 56157774Siwasakistruct acpi_dock_softc { 57157774Siwasaki int _sta; 58157774Siwasaki int _bdn; 59157774Siwasaki int _uid; 60157774Siwasaki int status; 61157774Siwasaki struct sysctl_ctx_list *sysctl_ctx; 62157774Siwasaki struct sysctl_oid *sysctl_tree; 63157774Siwasaki}; 64157774Siwasaki 65159855SnjlACPI_SERIAL_DECL(dock, "ACPI Docking Station"); 66157774Siwasaki 67157774Siwasaki/* 68159855Snjl * Utility functions 69157774Siwasaki */ 70157774Siwasaki 71157774Siwasakistatic void 72157774Siwasakiacpi_dock_get_info(device_t dev) 73157774Siwasaki{ 74157774Siwasaki struct acpi_dock_softc *sc; 75157774Siwasaki ACPI_HANDLE h; 76157774Siwasaki 77157774Siwasaki sc = device_get_softc(dev); 78157774Siwasaki h = acpi_get_handle(dev); 79157774Siwasaki 80159855Snjl if (ACPI_FAILURE(acpi_GetInteger(h, "_STA", &sc->_sta))) 81157774Siwasaki sc->_sta = ACPI_DOCK_STATUS_UNKNOWN; 82159855Snjl if (ACPI_FAILURE(acpi_GetInteger(h, "_BDN", &sc->_bdn))) 83157774Siwasaki sc->_bdn = ACPI_DOCK_STATUS_UNKNOWN; 84159855Snjl if (ACPI_FAILURE(acpi_GetInteger(h, "_UID", &sc->_uid))) 85157774Siwasaki sc->_uid = ACPI_DOCK_STATUS_UNKNOWN; 86157774Siwasaki ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 87159855Snjl "_STA: %04x, _BDN: %04x, _UID: %04x\n", sc->_sta, 88159855Snjl sc->_bdn, sc->_uid); 89157774Siwasaki} 90157774Siwasaki 91157774Siwasakistatic int 92157774Siwasakiacpi_dock_execute_dck(device_t dev, int dock) 93157774Siwasaki{ 94157774Siwasaki ACPI_HANDLE h; 95157774Siwasaki ACPI_OBJECT argobj; 96157774Siwasaki ACPI_OBJECT_LIST args; 97157774Siwasaki ACPI_BUFFER buf; 98157774Siwasaki ACPI_OBJECT retobj; 99157774Siwasaki ACPI_STATUS status; 100157774Siwasaki 101157774Siwasaki h = acpi_get_handle(dev); 102157774Siwasaki 103157774Siwasaki argobj.Type = ACPI_TYPE_INTEGER; 104157774Siwasaki argobj.Integer.Value = dock; 105157774Siwasaki args.Count = 1; 106157774Siwasaki args.Pointer = &argobj; 107157774Siwasaki buf.Pointer = &retobj; 108157774Siwasaki buf.Length = sizeof(retobj); 109157774Siwasaki status = AcpiEvaluateObject(h, "_DCK", &args, &buf); 110157774Siwasaki 111159855Snjl /* 112159855Snjl * When _DCK is called with 0, OSPM will ignore the return value. 113159855Snjl */ 114161065Snjl if (dock == ACPI_DOCK_ISOLATE) 115157774Siwasaki return (0); 116157774Siwasaki 117159855Snjl /* If _DCK returned 1, the request succeeded. */ 118159855Snjl if (ACPI_SUCCESS(status) && retobj.Type == ACPI_TYPE_INTEGER && 119159855Snjl retobj.Integer.Value == 1) 120159855Snjl return (0); 121157774Siwasaki 122157774Siwasaki return (-1); 123157774Siwasaki} 124157774Siwasaki 125161065Snjl/* Lock devices while docked to prevent surprise removal. */ 126157774Siwasakistatic void 127157774Siwasakiacpi_dock_execute_lck(device_t dev, int lock) 128157774Siwasaki{ 129157774Siwasaki ACPI_HANDLE h; 130157774Siwasaki 131157774Siwasaki h = acpi_get_handle(dev); 132157774Siwasaki acpi_SetInteger(h, "_LCK", lock); 133157774Siwasaki} 134157774Siwasaki 135161065Snjl/* Eject a device (i.e., motorized). */ 136157774Siwasakistatic int 137157774Siwasakiacpi_dock_execute_ejx(device_t dev, int eject, int state) 138157774Siwasaki{ 139157774Siwasaki ACPI_HANDLE h; 140157774Siwasaki ACPI_STATUS status; 141157774Siwasaki char ejx[5]; 142157774Siwasaki 143157774Siwasaki h = acpi_get_handle(dev); 144157774Siwasaki snprintf(ejx, sizeof(ejx), "_EJ%d", state); 145157774Siwasaki status = acpi_SetInteger(h, ejx, eject); 146159855Snjl if (ACPI_SUCCESS(status)) 147157774Siwasaki return (0); 148157774Siwasaki 149157774Siwasaki return (-1); 150157774Siwasaki} 151157774Siwasaki 152161065Snjl/* Find dependent devices. When their parent is removed, so are they. */ 153157774Siwasakistatic int 154157774Siwasakiacpi_dock_is_ejd_device(ACPI_HANDLE dock_handle, ACPI_HANDLE handle) 155157774Siwasaki{ 156157774Siwasaki int ret; 157157774Siwasaki ACPI_STATUS ret_status; 158157774Siwasaki ACPI_BUFFER ejd_buffer; 159157774Siwasaki ACPI_OBJECT *obj; 160157774Siwasaki 161157774Siwasaki ret = 0; 162157774Siwasaki 163157774Siwasaki ejd_buffer.Pointer = NULL; 164157774Siwasaki ejd_buffer.Length = ACPI_ALLOCATE_BUFFER; 165157774Siwasaki ret_status = AcpiEvaluateObject(handle, "_EJD", NULL, &ejd_buffer); 166159855Snjl if (ACPI_FAILURE(ret_status)) 167157774Siwasaki goto out; 168157774Siwasaki 169157774Siwasaki obj = (ACPI_OBJECT *)ejd_buffer.Pointer; 170159855Snjl if (dock_handle == acpi_GetReference(NULL, obj)) 171159855Snjl ret = 1; 172157774Siwasaki 173157774Siwasakiout: 174157774Siwasaki if (ejd_buffer.Pointer != NULL) 175157774Siwasaki AcpiOsFree(ejd_buffer.Pointer); 176157774Siwasaki 177157774Siwasaki return (ret); 178157774Siwasaki} 179157774Siwasaki 180157774Siwasaki/* 181159855Snjl * Docking functions 182157774Siwasaki */ 183157774Siwasaki 184157774Siwasakistatic void 185157774Siwasakiacpi_dock_attach_later(void *context) 186157774Siwasaki{ 187157774Siwasaki device_t dev; 188157774Siwasaki 189157774Siwasaki dev = (device_t)context; 190157774Siwasaki 191159855Snjl if (!device_is_enabled(dev)) 192157774Siwasaki device_enable(dev); 193157774Siwasaki 194196403Sjhb mtx_lock(&Giant); 195157774Siwasaki device_probe_and_attach(dev); 196196403Sjhb mtx_unlock(&Giant); 197157774Siwasaki} 198157774Siwasaki 199157774Siwasakistatic ACPI_STATUS 200159855Snjlacpi_dock_insert_child(ACPI_HANDLE handle, UINT32 level, void *context, 201159855Snjl void **status) 202157774Siwasaki{ 203157774Siwasaki device_t dock_dev, dev; 204157774Siwasaki ACPI_HANDLE dock_handle; 205157774Siwasaki 206157774Siwasaki dock_dev = (device_t)context; 207157774Siwasaki dock_handle = acpi_get_handle(dock_dev); 208157774Siwasaki 209159855Snjl if (!acpi_dock_is_ejd_device(dock_handle, handle)) 210157774Siwasaki goto out; 211157774Siwasaki 212157774Siwasaki ACPI_VPRINT(dock_dev, acpi_device_get_parent_softc(dock_dev), 213157774Siwasaki "inserting device for %s\n", acpi_name(handle)); 214157774Siwasaki 215157774Siwasaki#if 0 216157774Siwasaki /* 217157774Siwasaki * If the system boot up w/o Docking, the devices under the dock 218157774Siwasaki * still un-initialized, also control methods such as _INI, _STA 219157774Siwasaki * are not executed. 220157774Siwasaki * Normal devices are initialized at booting by calling 221157774Siwasaki * AcpiInitializeObjects(), however the devices under the dock 222157774Siwasaki * need to be initialized here on the scheme of ACPICA. 223157774Siwasaki */ 224157774Siwasaki ACPI_INIT_WALK_INFO Info; 225157774Siwasaki 226157774Siwasaki AcpiNsWalkNamespace(ACPI_TYPE_ANY, handle, 227199337Sjkim 100, TRUE, AcpiNsInitOneDevice, NULL, &Info, NULL); 228157774Siwasaki#endif 229157774Siwasaki 230157774Siwasaki dev = acpi_get_device(handle); 231157774Siwasaki if (dev == NULL) { 232159855Snjl device_printf(dock_dev, "error: %s has no associated device\n", 233157774Siwasaki acpi_name(handle)); 234157774Siwasaki goto out; 235157774Siwasaki } 236157774Siwasaki 237167814Sjkim AcpiOsExecute(OSL_NOTIFY_HANDLER, acpi_dock_attach_later, dev); 238157774Siwasaki 239157774Siwasakiout: 240157774Siwasaki return (AE_OK); 241157774Siwasaki} 242157774Siwasaki 243157774Siwasakistatic void 244157774Siwasakiacpi_dock_insert_children(device_t dev) 245157774Siwasaki{ 246159855Snjl ACPI_STATUS status; 247157774Siwasaki ACPI_HANDLE sb_handle; 248157774Siwasaki 249159855Snjl status = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &sb_handle); 250159855Snjl if (ACPI_SUCCESS(status)) { 251157774Siwasaki AcpiWalkNamespace(ACPI_TYPE_DEVICE, sb_handle, 252199337Sjkim 100, acpi_dock_insert_child, NULL, dev, NULL); 253157774Siwasaki } 254157774Siwasaki} 255157774Siwasaki 256157774Siwasakistatic void 257157774Siwasakiacpi_dock_insert(device_t dev) 258157774Siwasaki{ 259157774Siwasaki struct acpi_dock_softc *sc; 260157774Siwasaki 261157774Siwasaki ACPI_SERIAL_ASSERT(dock); 262157774Siwasaki 263157774Siwasaki sc = device_get_softc(dev); 264157774Siwasaki 265161065Snjl if (sc->status == ACPI_DOCK_STATUS_UNDOCKED || 266161065Snjl sc->status == ACPI_DOCK_STATUS_UNKNOWN) { 267159855Snjl acpi_dock_execute_lck(dev, ACPI_DOCK_LOCK); 268161065Snjl if (acpi_dock_execute_dck(dev, ACPI_DOCK_CONNECT) != 0) { 269157774Siwasaki device_printf(dev, "_DCK failed\n"); 270157774Siwasaki return; 271157774Siwasaki } 272157774Siwasaki 273159855Snjl if (!cold) 274157774Siwasaki acpi_dock_insert_children(dev); 275161065Snjl sc->status = ACPI_DOCK_STATUS_DOCKED; 276157774Siwasaki } 277157774Siwasaki} 278157774Siwasaki 279157774Siwasaki/* 280157774Siwasaki * Undock 281157774Siwasaki */ 282157774Siwasaki 283157774Siwasakistatic ACPI_STATUS 284159855Snjlacpi_dock_eject_child(ACPI_HANDLE handle, UINT32 level, void *context, 285159855Snjl void **status) 286157774Siwasaki{ 287157774Siwasaki device_t dock_dev, dev; 288157774Siwasaki ACPI_HANDLE dock_handle; 289157774Siwasaki 290157774Siwasaki dock_dev = *(device_t *)context; 291157774Siwasaki dock_handle = acpi_get_handle(dock_dev); 292157774Siwasaki 293159855Snjl if (!acpi_dock_is_ejd_device(dock_handle, handle)) 294157774Siwasaki goto out; 295157774Siwasaki 296157774Siwasaki ACPI_VPRINT(dock_dev, acpi_device_get_parent_softc(dock_dev), 297159855Snjl "ejecting device for %s\n", acpi_name(handle)); 298157774Siwasaki 299157774Siwasaki dev = acpi_get_device(handle); 300157774Siwasaki if (dev != NULL && device_is_attached(dev)) { 301196403Sjhb mtx_lock(&Giant); 302157774Siwasaki device_detach(dev); 303196403Sjhb mtx_unlock(&Giant); 304157774Siwasaki } 305157774Siwasaki 306157774Siwasaki acpi_SetInteger(handle, "_EJ0", 0); 307157774Siwasakiout: 308157774Siwasaki return (AE_OK); 309157774Siwasaki} 310157774Siwasaki 311157774Siwasakistatic void 312157774Siwasakiacpi_dock_eject_children(device_t dev) 313157774Siwasaki{ 314157774Siwasaki ACPI_HANDLE sb_handle; 315159855Snjl ACPI_STATUS status; 316157774Siwasaki 317159855Snjl status = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &sb_handle); 318159855Snjl if (ACPI_SUCCESS(status)) { 319157774Siwasaki AcpiWalkNamespace(ACPI_TYPE_DEVICE, sb_handle, 320199337Sjkim 100, acpi_dock_eject_child, NULL, &dev, NULL); 321157774Siwasaki } 322157774Siwasaki} 323157774Siwasaki 324157774Siwasakistatic void 325157774Siwasakiacpi_dock_removal(device_t dev) 326157774Siwasaki{ 327157774Siwasaki struct acpi_dock_softc *sc; 328157774Siwasaki 329157774Siwasaki ACPI_SERIAL_ASSERT(dock); 330157774Siwasaki 331157774Siwasaki sc = device_get_softc(dev); 332161065Snjl if (sc->status == ACPI_DOCK_STATUS_DOCKED || 333161065Snjl sc->status == ACPI_DOCK_STATUS_UNKNOWN) { 334157774Siwasaki acpi_dock_eject_children(dev); 335161065Snjl if (acpi_dock_execute_dck(dev, ACPI_DOCK_ISOLATE) != 0) 336157774Siwasaki return; 337157774Siwasaki 338159855Snjl acpi_dock_execute_lck(dev, ACPI_DOCK_UNLOCK); 339157774Siwasaki 340157774Siwasaki if (acpi_dock_execute_ejx(dev, 1, 0) != 0) { 341157774Siwasaki device_printf(dev, "_EJ0 failed\n"); 342157774Siwasaki return; 343157774Siwasaki } 344157774Siwasaki 345161065Snjl sc->status = ACPI_DOCK_STATUS_UNDOCKED; 346157774Siwasaki } 347157774Siwasaki 348157774Siwasaki acpi_dock_get_info(dev); 349159855Snjl if (sc->_sta != 0) 350159855Snjl device_printf(dev, "mechanical failure (%#x).\n", sc->_sta); 351157774Siwasaki} 352157774Siwasaki 353157774Siwasaki/* 354157774Siwasaki * Device/Bus check 355157774Siwasaki */ 356157774Siwasaki 357157774Siwasakistatic void 358157774Siwasakiacpi_dock_device_check(device_t dev) 359157774Siwasaki{ 360157774Siwasaki struct acpi_dock_softc *sc; 361157774Siwasaki 362157774Siwasaki ACPI_SERIAL_ASSERT(dock); 363157774Siwasaki 364157774Siwasaki sc = device_get_softc(dev); 365157774Siwasaki acpi_dock_get_info(dev); 366157774Siwasaki 367157774Siwasaki /* 368161065Snjl * If the _STA method indicates 'present' and 'functioning', the 369161065Snjl * system is docked. If _STA does not exist for this device, it 370161065Snjl * is always present. 371157774Siwasaki */ 372161065Snjl if (sc->_sta == ACPI_DOCK_STATUS_UNKNOWN || 373161065Snjl ACPI_DEVICE_PRESENT(sc->_sta)) 374157774Siwasaki acpi_dock_insert(dev); 375161065Snjl else if (sc->_sta == 0) 376157774Siwasaki acpi_dock_removal(dev); 377157774Siwasaki} 378157774Siwasaki 379157774Siwasaki/* 380157774Siwasaki * Notify Handler 381157774Siwasaki */ 382157774Siwasaki 383157774Siwasakistatic void 384157774Siwasakiacpi_dock_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 385157774Siwasaki{ 386157774Siwasaki device_t dev; 387157774Siwasaki 388157774Siwasaki dev = (device_t) context; 389157774Siwasaki ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), 390157774Siwasaki "got notification %#x\n", notify); 391157774Siwasaki 392157774Siwasaki ACPI_SERIAL_BEGIN(dock); 393157774Siwasaki switch (notify) { 394170148Stakawata case ACPI_NOTIFY_BUS_CHECK: 395170148Stakawata case ACPI_NOTIFY_DEVICE_CHECK: 396157774Siwasaki acpi_dock_device_check(dev); 397157774Siwasaki break; 398170148Stakawata case ACPI_NOTIFY_EJECT_REQUEST: 399157774Siwasaki acpi_dock_removal(dev); 400157774Siwasaki break; 401157774Siwasaki default: 402157774Siwasaki device_printf(dev, "unknown notify %#x\n", notify); 403157774Siwasaki break; 404157774Siwasaki } 405157774Siwasaki ACPI_SERIAL_END(dock); 406157774Siwasaki} 407157774Siwasaki 408157774Siwasakistatic int 409157774Siwasakiacpi_dock_status_sysctl(SYSCTL_HANDLER_ARGS) 410157774Siwasaki{ 411157774Siwasaki struct acpi_dock_softc *sc; 412157774Siwasaki device_t dev; 413161065Snjl int status, err; 414157774Siwasaki 415161065Snjl dev = (device_t)arg1; 416161065Snjl 417157774Siwasaki sc = device_get_softc(dev); 418161065Snjl status = sc->status; 419157774Siwasaki 420157774Siwasaki ACPI_SERIAL_BEGIN(dock); 421161065Snjl err = sysctl_handle_int(oidp, &status, 0, req); 422161065Snjl if (err != 0 || req->newptr == NULL) 423161065Snjl goto out; 424157774Siwasaki 425157774Siwasaki if (status != ACPI_DOCK_STATUS_UNDOCKED && 426157774Siwasaki status != ACPI_DOCK_STATUS_DOCKED) { 427157774Siwasaki err = EINVAL; 428161065Snjl goto out; 429157774Siwasaki } 430157774Siwasaki 431159855Snjl if (status == sc->status) 432157774Siwasaki goto out; 433157774Siwasaki 434157774Siwasaki switch (status) { 435157774Siwasaki case ACPI_DOCK_STATUS_UNDOCKED: 436157774Siwasaki acpi_dock_removal(dev); 437157774Siwasaki break; 438157774Siwasaki case ACPI_DOCK_STATUS_DOCKED: 439157774Siwasaki acpi_dock_device_check(dev); 440157774Siwasaki break; 441157774Siwasaki default: 442157774Siwasaki err = EINVAL; 443157774Siwasaki break; 444157774Siwasaki } 445157774Siwasakiout: 446157774Siwasaki ACPI_SERIAL_END(dock); 447157774Siwasaki return (err); 448157774Siwasaki} 449157774Siwasaki 450157774Siwasakistatic int 451157774Siwasakiacpi_dock_probe(device_t dev) 452157774Siwasaki{ 453157774Siwasaki ACPI_HANDLE h, tmp; 454157774Siwasaki 455157774Siwasaki h = acpi_get_handle(dev); 456157774Siwasaki if (acpi_disabled("dock") || 457157774Siwasaki ACPI_FAILURE(AcpiGetHandle(h, "_DCK", &tmp))) 458157774Siwasaki return (ENXIO); 459157774Siwasaki 460159855Snjl device_set_desc(dev, "ACPI Docking Station"); 461159855Snjl 462159855Snjl /* 463159855Snjl * XXX Somewhere else in the kernel panics on "sysctl kern" if we 464159855Snjl * return a negative value here (reprobe ok). 465159855Snjl */ 466157774Siwasaki return (0); 467157774Siwasaki} 468157774Siwasaki 469157774Siwasakistatic int 470157774Siwasakiacpi_dock_attach(device_t dev) 471157774Siwasaki{ 472157774Siwasaki struct acpi_dock_softc *sc; 473157774Siwasaki ACPI_HANDLE h; 474157774Siwasaki 475157774Siwasaki sc = device_get_softc(dev); 476157774Siwasaki h = acpi_get_handle(dev); 477161065Snjl if (sc == NULL || h == NULL) 478157774Siwasaki return (ENXIO); 479157774Siwasaki 480157774Siwasaki sc->status = ACPI_DOCK_STATUS_UNKNOWN; 481157774Siwasaki 482157774Siwasaki AcpiEvaluateObject(h, "_INI", NULL, NULL); 483157774Siwasaki 484157774Siwasaki ACPI_SERIAL_BEGIN(dock); 485157774Siwasaki 486157774Siwasaki acpi_dock_device_check(dev); 487157774Siwasaki 488161065Snjl /* Get the sysctl tree */ 489157774Siwasaki sc->sysctl_ctx = device_get_sysctl_ctx(dev); 490157774Siwasaki sc->sysctl_tree = device_get_sysctl_tree(dev); 491157774Siwasaki 492157774Siwasaki SYSCTL_ADD_INT(sc->sysctl_ctx, 493157774Siwasaki SYSCTL_CHILDREN(sc->sysctl_tree), 494157774Siwasaki OID_AUTO, "_sta", CTLFLAG_RD, 495157774Siwasaki &sc->_sta, 0, "Dock _STA"); 496157774Siwasaki SYSCTL_ADD_INT(sc->sysctl_ctx, 497157774Siwasaki SYSCTL_CHILDREN(sc->sysctl_tree), 498157774Siwasaki OID_AUTO, "_bdn", CTLFLAG_RD, 499157774Siwasaki &sc->_bdn, 0, "Dock _BDN"); 500157774Siwasaki SYSCTL_ADD_INT(sc->sysctl_ctx, 501157774Siwasaki SYSCTL_CHILDREN(sc->sysctl_tree), 502157774Siwasaki OID_AUTO, "_uid", CTLFLAG_RD, 503157774Siwasaki &sc->_uid, 0, "Dock _UID"); 504157774Siwasaki SYSCTL_ADD_PROC(sc->sysctl_ctx, 505157774Siwasaki SYSCTL_CHILDREN(sc->sysctl_tree), 506157774Siwasaki OID_AUTO, "status", 507157774Siwasaki CTLTYPE_INT|CTLFLAG_RW, dev, 0, 508157774Siwasaki acpi_dock_status_sysctl, "I", 509157774Siwasaki "Dock/Undock operation"); 510157774Siwasaki 511157774Siwasaki ACPI_SERIAL_END(dock); 512157774Siwasaki 513157774Siwasaki AcpiInstallNotifyHandler(h, ACPI_ALL_NOTIFY, 514157774Siwasaki acpi_dock_notify_handler, dev); 515157774Siwasaki 516157774Siwasaki return (0); 517157774Siwasaki} 518157774Siwasaki 519157774Siwasakistatic device_method_t acpi_dock_methods[] = { 520157774Siwasaki /* Device interface */ 521157774Siwasaki DEVMETHOD(device_probe, acpi_dock_probe), 522157774Siwasaki DEVMETHOD(device_attach, acpi_dock_attach), 523157774Siwasaki 524157774Siwasaki {0, 0} 525157774Siwasaki}; 526157774Siwasaki 527157774Siwasakistatic driver_t acpi_dock_driver = { 528157774Siwasaki "acpi_dock", 529157774Siwasaki acpi_dock_methods, 530157774Siwasaki sizeof(struct acpi_dock_softc), 531157774Siwasaki}; 532157774Siwasaki 533157774Siwasakistatic devclass_t acpi_dock_devclass; 534157774Siwasaki 535157774SiwasakiDRIVER_MODULE(acpi_dock, acpi, acpi_dock_driver, acpi_dock_devclass, 0, 0); 536157774SiwasakiMODULE_DEPEND(acpi_dock, acpi, 1, 1, 1); 537157774Siwasaki 538