devctl.c revision 278320
1278320Sjhb/*- 2278320Sjhb * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org> 3278320Sjhb * All rights reserved. 4278320Sjhb * 5278320Sjhb * Redistribution and use in source and binary forms, with or without 6278320Sjhb * modification, are permitted provided that the following conditions 7278320Sjhb * are met: 8278320Sjhb * 1. Redistributions of source code must retain the above copyright 9278320Sjhb * notice, this list of conditions and the following disclaimer. 10278320Sjhb * 2. Redistributions in binary form must reproduce the above copyright 11278320Sjhb * notice, this list of conditions and the following disclaimer in the 12278320Sjhb * documentation and/or other materials provided with the distribution. 13278320Sjhb * 14278320Sjhb * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15278320Sjhb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16278320Sjhb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17278320Sjhb * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18278320Sjhb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19278320Sjhb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20278320Sjhb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21278320Sjhb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22278320Sjhb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23278320Sjhb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24278320Sjhb * SUCH DAMAGE. 25278320Sjhb */ 26278320Sjhb 27278320Sjhb#include <sys/cdefs.h> 28278320Sjhb__FBSDID("$FreeBSD: head/lib/libdevctl/devctl.c 278320 2015-02-06 16:09:01Z jhb $"); 29278320Sjhb 30278320Sjhb#include <sys/types.h> 31278320Sjhb#include <sys/bus.h> 32278320Sjhb#include <errno.h> 33278320Sjhb#include <fcntl.h> 34278320Sjhb#include <string.h> 35278320Sjhb#include "devctl.h" 36278320Sjhb 37278320Sjhbstatic int 38278320Sjhbdevctl_request(u_long cmd, struct devreq *req) 39278320Sjhb{ 40278320Sjhb static int devctl2_fd = -1; 41278320Sjhb 42278320Sjhb if (devctl2_fd == -1) { 43278320Sjhb devctl2_fd = open("/dev/devctl2", O_RDONLY); 44278320Sjhb if (devctl2_fd == -1) 45278320Sjhb return (-1); 46278320Sjhb } 47278320Sjhb return (ioctl(devctl2_fd, cmd, req)); 48278320Sjhb} 49278320Sjhb 50278320Sjhbstatic int 51278320Sjhbdevctl_simple_request(u_long cmd, const char *name, int flags) 52278320Sjhb{ 53278320Sjhb struct devreq req; 54278320Sjhb 55278320Sjhb memset(&req, 0, sizeof(req)); 56278320Sjhb if (strlcpy(req.dr_name, name, sizeof(req.dr_name)) >= 57278320Sjhb sizeof(req.dr_name)) { 58278320Sjhb errno = EINVAL; 59278320Sjhb return (-1); 60278320Sjhb } 61278320Sjhb req.dr_flags = flags; 62278320Sjhb return (devctl_request(cmd, &req)); 63278320Sjhb} 64278320Sjhb 65278320Sjhbint 66278320Sjhbdevctl_attach(const char *device) 67278320Sjhb{ 68278320Sjhb 69278320Sjhb return (devctl_simple_request(DEV_ATTACH, device, 0)); 70278320Sjhb} 71278320Sjhb 72278320Sjhbint 73278320Sjhbdevctl_detach(const char *device, bool force) 74278320Sjhb{ 75278320Sjhb 76278320Sjhb return (devctl_simple_request(DEV_DETACH, device, force ? 77278320Sjhb DEVF_FORCE_DETACH : 0)); 78278320Sjhb} 79278320Sjhb 80278320Sjhbint 81278320Sjhbdevctl_enable(const char *device) 82278320Sjhb{ 83278320Sjhb 84278320Sjhb return (devctl_simple_request(DEV_ENABLE, device, 0)); 85278320Sjhb} 86278320Sjhb 87278320Sjhbint 88278320Sjhbdevctl_disable(const char *device, bool force_detach) 89278320Sjhb{ 90278320Sjhb 91278320Sjhb return (devctl_simple_request(DEV_DISABLE, device, force_detach ? 92278320Sjhb DEVF_FORCE_DETACH : 0)); 93278320Sjhb} 94278320Sjhb 95278320Sjhbint 96278320Sjhbdevctl_suspend(const char *device) 97278320Sjhb{ 98278320Sjhb 99278320Sjhb return (devctl_simple_request(DEV_SUSPEND, device, 0)); 100278320Sjhb} 101278320Sjhb 102278320Sjhbint 103278320Sjhbdevctl_resume(const char *device) 104278320Sjhb{ 105278320Sjhb 106278320Sjhb return (devctl_simple_request(DEV_RESUME, device, 0)); 107278320Sjhb} 108278320Sjhb 109278320Sjhbint 110278320Sjhbdevctl_set_driver(const char *device, const char *driver, bool force) 111278320Sjhb{ 112278320Sjhb struct devreq req; 113278320Sjhb 114278320Sjhb memset(&req, 0, sizeof(req)); 115278320Sjhb if (strlcpy(req.dr_name, device, sizeof(req.dr_name)) >= 116278320Sjhb sizeof(req.dr_name)) { 117278320Sjhb errno = EINVAL; 118278320Sjhb return (-1); 119278320Sjhb } 120278320Sjhb req.dr_data = __DECONST(char *, driver); 121278320Sjhb if (force) 122278320Sjhb req.dr_flags |= DEVF_SET_DRIVER_DETACH; 123278320Sjhb return (devctl_request(DEV_SET_DRIVER, &req)); 124278320Sjhb} 125