[BACK]Return to gpio.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / gpio

Annotation of src/sys/dev/gpio/gpio.c, Revision 1.15.4.4

1.15.4.4! yamt        1: /* $NetBSD: gpio.c,v 1.15.4.3 2009/08/19 18:47:05 yamt Exp $ */
1.5       riz         2: /*     $OpenBSD: gpio.c,v 1.6 2006/01/14 12:33:49 grange Exp $ */
                      3:
1.1       jmcneill    4: /*
1.15.4.3  yamt        5:  * Copyright (c) 2008, 2009 Marc Balmer <marc@msys.ch>
1.5       riz         6:  * Copyright (c) 2004, 2006 Alexander Yurchenko <grange@openbsd.org>
1.1       jmcneill    7:  *
                      8:  * Permission to use, copy, modify, and distribute this software for any
                      9:  * purpose with or without fee is hereby granted, provided that the above
                     10:  * copyright notice and this permission notice appear in all copies.
                     11:  *
                     12:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     13:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     14:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     15:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     16:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     17:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     18:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     19:  */
                     20:
1.2       cube       21: #include <sys/cdefs.h>
1.15.4.4! yamt       22: __KERNEL_RCSID(0, "$NetBSD: gpio.c,v 1.15.4.3 2009/08/19 18:47:05 yamt Exp $");
1.2       cube       23:
1.1       jmcneill   24: /*
                     25:  * General Purpose Input/Output framework.
                     26:  */
                     27:
                     28: #include <sys/param.h>
                     29: #include <sys/systm.h>
                     30: #include <sys/conf.h>
                     31: #include <sys/device.h>
1.15.4.3  yamt       32: #include <sys/fcntl.h>
1.1       jmcneill   33: #include <sys/ioctl.h>
                     34: #include <sys/gpio.h>
                     35: #include <sys/vnode.h>
1.15.4.3  yamt       36: #include <sys/kmem.h>
                     37: #include <sys/queue.h>
                     38: #include <sys/kauth.h>
1.1       jmcneill   39:
                     40: #include <dev/gpio/gpiovar.h>
                     41:
1.3       drochner   42: #include "locators.h"
                     43:
1.15.4.3  yamt       44: #ifdef GPIO_DEBUG
                     45: #define DPRINTFN(n, x) do { if (gpiodebug > (n)) printf x; } while (0)
                     46: int gpiodebug = 0;
                     47: #else
                     48: #define DPRINTFN(n, x)
                     49: #endif
                     50: #define DPRINTF(x)     DPRINTFN(0, x)
1.1       jmcneill   51:
1.15.4.3  yamt       52: struct gpio_softc {
                     53:        device_t                 sc_dev;
1.1       jmcneill   54:
1.15.4.3  yamt       55:        gpio_chipset_tag_t       sc_gc;         /* GPIO controller */
                     56:        gpio_pin_t              *sc_pins;       /* pins array */
                     57:        int                      sc_npins;      /* number of pins */
                     58:
                     59:        int                      sc_opened;
                     60:        LIST_HEAD(, gpio_dev)    sc_devs;       /* devices */
                     61:        LIST_HEAD(, gpio_name)   sc_names;      /* named pins */
1.1       jmcneill   62: };
                     63:
1.15.4.1  yamt       64: int    gpio_match(device_t, cfdata_t, void *);
1.15.4.3  yamt       65: int    gpio_submatch(device_t, cfdata_t, const int *, void *);
1.14      dyoung     66: void   gpio_attach(device_t, device_t, void *);
1.15      dyoung     67: bool   gpio_resume(device_t PMF_FN_PROTO);
1.14      dyoung     68: int    gpio_detach(device_t, int);
                     69: int    gpio_activate(device_t, enum devact);
1.15.4.1  yamt       70: int    gpio_search(device_t, cfdata_t, const int *, void *);
1.1       jmcneill   71: int    gpio_print(void *, const char *);
1.15.4.3  yamt       72: int    gpio_pinbyname(struct gpio_softc *, char *);
                     73:
                     74: /* Old API */
                     75: int    gpio_ioctl_oapi(struct gpio_softc *, u_long, void *, int, kauth_cred_t);
1.1       jmcneill   76:
1.15.4.2  yamt       77: CFATTACH_DECL3_NEW(gpio, sizeof(struct gpio_softc),
                     78:     gpio_match, gpio_attach, gpio_detach, gpio_activate, NULL, NULL,
                     79:     DVF_DETACH_SHUTDOWN);
1.1       jmcneill   80:
                     81: dev_type_open(gpioopen);
                     82: dev_type_close(gpioclose);
                     83: dev_type_ioctl(gpioioctl);
                     84:
                     85: const struct cdevsw gpio_cdevsw = {
                     86:        gpioopen, gpioclose, noread, nowrite, gpioioctl,
1.9       christos   87:        nostop, notty, nopoll, nommap, nokqfilter, D_OTHER,
1.1       jmcneill   88: };
                     89:
                     90: extern struct cfdriver gpio_cd;
                     91:
                     92: int
1.15.4.1  yamt       93: gpio_match(device_t parent, cfdata_t cf, void *aux)
1.1       jmcneill   94: {
1.15.4.3  yamt       95:        return 1;
                     96: }
                     97:
                     98: int
                     99: gpio_submatch(device_t parent, cfdata_t cf, const int *ip, void *aux)
                    100: {
                    101:        struct gpio_attach_args *ga = aux;
1.1       jmcneill  102:
1.15.4.3  yamt      103:        if (ga->ga_offset == -1)
                    104:                return 0;
                    105:
                    106:        return strcmp(ga->ga_dvname, cf->cf_name) == 0;
1.1       jmcneill  107: }
                    108:
1.13      dyoung    109: bool
1.15      dyoung    110: gpio_resume(device_t self PMF_FN_ARGS)
1.13      dyoung    111: {
                    112:        struct gpio_softc *sc = device_private(self);
                    113:        int pin;
                    114:
                    115:        for (pin = 0; pin < sc->sc_npins; pin++) {
                    116:                gpiobus_pin_ctl(sc->sc_gc, pin, sc->sc_pins[pin].pin_flags);
                    117:                gpiobus_pin_write(sc->sc_gc, pin, sc->sc_pins[pin].pin_state);
                    118:        }
                    119:        return true;
                    120: }
                    121:
1.1       jmcneill  122: void
1.14      dyoung    123: gpio_attach(device_t parent, device_t self, void *aux)
1.1       jmcneill  124: {
1.7       thorpej   125:        struct gpio_softc *sc = device_private(self);
1.1       jmcneill  126:        struct gpiobus_attach_args *gba = aux;
                    127:
1.15.4.1  yamt      128:        sc->sc_dev = self;
1.1       jmcneill  129:        sc->sc_gc = gba->gba_gc;
                    130:        sc->sc_pins = gba->gba_pins;
                    131:        sc->sc_npins = gba->gba_npins;
                    132:
                    133:        printf(": %d pins\n", sc->sc_npins);
                    134:
1.13      dyoung    135:        if (!pmf_device_register(self, NULL, gpio_resume))
                    136:                aprint_error_dev(self, "couldn't establish power handler\n");
                    137:
1.1       jmcneill  138:        /*
                    139:         * Attach all devices that can be connected to the GPIO pins
                    140:         * described in the kernel configuration file.
                    141:         */
1.5       riz       142:        config_search_ia(gpio_search, self, "gpio", sc);
1.1       jmcneill  143: }
                    144:
                    145: int
1.14      dyoung    146: gpio_detach(device_t self, int flags)
1.1       jmcneill  147: {
                    148: #if 0
                    149:        int maj, mn;
                    150:
                    151:        /* Locate the major number */
                    152:        for (maj = 0; maj < nchrdev; maj++)
                    153:                if (cdevsw[maj].d_open == gpioopen)
                    154:                        break;
                    155:
                    156:        /* Nuke the vnodes for any open instances (calls close) */
1.6       thorpej   157:        mn = device_unit(self);
1.1       jmcneill  158:        vdevgone(maj, mn, mn, VCHR);
                    159: #endif
1.15.4.3  yamt      160:        return 0;
1.1       jmcneill  161: }
                    162:
                    163: int
1.14      dyoung    164: gpio_activate(device_t self, enum devact act)
1.1       jmcneill  165: {
1.15.4.3  yamt      166:        printf("gpio_active: ");
1.1       jmcneill  167:        switch (act) {
                    168:        case DVACT_ACTIVATE:
1.15.4.3  yamt      169:                DPRINTF(("ACTIVATE\n"));
                    170:                return EOPNOTSUPP;
1.1       jmcneill  171:        case DVACT_DEACTIVATE:
1.15.4.3  yamt      172:                DPRINTF(("DEACTIVATE\n"));
1.1       jmcneill  173:                break;
                    174:        }
1.15.4.3  yamt      175:        return 0;
1.1       jmcneill  176: }
                    177:
                    178: int
1.15.4.1  yamt      179: gpio_search(device_t parent, cfdata_t cf,
1.11      christos  180:     const int *ldesc, void *aux)
1.1       jmcneill  181: {
                    182:        struct gpio_attach_args ga;
                    183:
1.5       riz       184:        ga.ga_gpio = aux;
                    185:        ga.ga_offset = cf->cf_loc[GPIOCF_OFFSET];
1.3       drochner  186:        ga.ga_mask = cf->cf_loc[GPIOCF_MASK];
1.1       jmcneill  187:
                    188:        if (config_match(parent, cf, &ga) > 0)
                    189:                config_attach(parent, cf, &ga, gpio_print);
                    190:
1.15.4.3  yamt      191:        return 0;
1.1       jmcneill  192: }
                    193:
                    194: int
1.11      christos  195: gpio_print(void *aux, const char *pnp)
1.1       jmcneill  196: {
                    197:        struct gpio_attach_args *ga = aux;
                    198:        int i;
                    199:
                    200:        printf(" pins");
                    201:        for (i = 0; i < 32; i++)
                    202:                if (ga->ga_mask & (1 << i))
1.5       riz       203:                        printf(" %d", ga->ga_offset + i);
1.1       jmcneill  204:
1.15.4.3  yamt      205:        return UNCONF;
1.1       jmcneill  206: }
                    207:
                    208: int
1.11      christos  209: gpiobus_print(void *aux, const char *pnp)
1.1       jmcneill  210: {
1.3       drochner  211: #if 0
1.1       jmcneill  212:        struct gpiobus_attach_args *gba = aux;
1.3       drochner  213: #endif
1.1       jmcneill  214:        if (pnp != NULL)
1.15.4.3  yamt      215:                printf("gpiobus at %s", pnp);
1.1       jmcneill  216:
1.15.4.3  yamt      217:        return UNCONF;
1.1       jmcneill  218: }
                    219:
1.15.4.4! yamt      220: /* return 1 if all pins can be mapped, 0 if not */
        !           221:
        !           222: int
        !           223: gpio_pin_can_map(void *gpio, int offset, u_int32_t mask)
        !           224: {
        !           225:        struct gpio_softc *sc = gpio;
        !           226:        int npins, pin, i;
        !           227:
        !           228:        npins = gpio_npins(mask);
        !           229:        if (npins > sc->sc_npins)
        !           230:                return 0;
        !           231:
        !           232:        for (npins = 0, i = 0; i < 32; i++)
        !           233:                if (mask & (1 << i)) {
        !           234:                        pin = offset + i;
        !           235:                        if (pin < 0 || pin >= sc->sc_npins)
        !           236:                                return 0;
        !           237:                        if (sc->sc_pins[pin].pin_mapped)
        !           238:                                return 0;
        !           239:                }
        !           240:
        !           241:        return 1;
        !           242: }
        !           243:
1.8       uwe       244: int
1.5       riz       245: gpio_pin_map(void *gpio, int offset, u_int32_t mask, struct gpio_pinmap *map)
                    246: {
                    247:        struct gpio_softc *sc = gpio;
                    248:        int npins, pin, i;
                    249:
                    250:        npins = gpio_npins(mask);
                    251:        if (npins > sc->sc_npins)
1.15.4.3  yamt      252:                return 1;
1.5       riz       253:
                    254:        for (npins = 0, i = 0; i < 32; i++)
                    255:                if (mask & (1 << i)) {
                    256:                        pin = offset + i;
                    257:                        if (pin < 0 || pin >= sc->sc_npins)
1.15.4.3  yamt      258:                                return 1;
1.5       riz       259:                        if (sc->sc_pins[pin].pin_mapped)
1.15.4.3  yamt      260:                                return 1;
1.5       riz       261:                        sc->sc_pins[pin].pin_mapped = 1;
                    262:                        map->pm_map[npins++] = pin;
                    263:                }
                    264:        map->pm_size = npins;
                    265:
1.15.4.3  yamt      266:        return 0;
1.5       riz       267: }
                    268:
                    269: void
                    270: gpio_pin_unmap(void *gpio, struct gpio_pinmap *map)
                    271: {
                    272:        struct gpio_softc *sc = gpio;
                    273:        int pin, i;
                    274:
                    275:        for (i = 0; i < map->pm_size; i++) {
                    276:                pin = map->pm_map[i];
                    277:                sc->sc_pins[pin].pin_mapped = 0;
                    278:        }
                    279: }
                    280:
                    281: int
                    282: gpio_pin_read(void *gpio, struct gpio_pinmap *map, int pin)
                    283: {
                    284:        struct gpio_softc *sc = gpio;
                    285:
1.15.4.3  yamt      286:        return gpiobus_pin_read(sc->sc_gc, map->pm_map[pin]);
1.5       riz       287: }
                    288:
                    289: void
                    290: gpio_pin_write(void *gpio, struct gpio_pinmap *map, int pin, int value)
                    291: {
                    292:        struct gpio_softc *sc = gpio;
                    293:
1.13      dyoung    294:        gpiobus_pin_write(sc->sc_gc, map->pm_map[pin], value);
                    295:        sc->sc_pins[map->pm_map[pin]].pin_state = value;
1.5       riz       296: }
                    297:
                    298: void
                    299: gpio_pin_ctl(void *gpio, struct gpio_pinmap *map, int pin, int flags)
                    300: {
                    301:        struct gpio_softc *sc = gpio;
                    302:
1.15.4.3  yamt      303:        return gpiobus_pin_ctl(sc->sc_gc, map->pm_map[pin], flags);
1.5       riz       304: }
                    305:
                    306: int
                    307: gpio_pin_caps(void *gpio, struct gpio_pinmap *map, int pin)
                    308: {
                    309:        struct gpio_softc *sc = gpio;
                    310:
1.15.4.3  yamt      311:        return sc->sc_pins[map->pm_map[pin]].pin_caps;
1.5       riz       312: }
                    313:
                    314: int
                    315: gpio_npins(u_int32_t mask)
                    316: {
                    317:        int npins, i;
                    318:
                    319:        for (npins = 0, i = 0; i < 32; i++)
                    320:                if (mask & (1 << i))
                    321:                        npins++;
                    322:
1.15.4.3  yamt      323:        return npins;
1.5       riz       324: }
                    325:
1.1       jmcneill  326: int
1.15.4.3  yamt      327: gpioopen(dev_t dev, int flag, int mode, struct lwp *l)
1.1       jmcneill  328: {
                    329:        struct gpio_softc *sc;
1.15.4.1  yamt      330:        int ret;
1.1       jmcneill  331:
1.15.4.1  yamt      332:        sc = device_lookup_private(&gpio_cd, minor(dev));
1.1       jmcneill  333:        if (sc == NULL)
1.15.4.3  yamt      334:                return ENXIO;
                    335:        DPRINTF(("%s: opening\n", device_xname(sc->sc_dev)));
                    336:        if (sc->sc_opened) {
                    337:                DPRINTF(("%s: already opened\n", device_xname(sc->sc_dev)));
                    338:                return EBUSY;
                    339:        }
1.15.4.1  yamt      340:
1.15.4.3  yamt      341:        if ((ret = gpiobus_open(sc->sc_gc, sc->sc_dev))) {
                    342:                DPRINTF(("%s: gpiobus_open returned %d\n",
                    343:                    device_xname(sc->sc_dev),
                    344:                    ret));
1.15.4.1  yamt      345:                return ret;
1.15.4.3  yamt      346:        }
1.15.4.1  yamt      347:
1.1       jmcneill  348:        sc->sc_opened = 1;
                    349:
1.15.4.3  yamt      350:        return 0;
1.1       jmcneill  351: }
                    352:
                    353: int
1.15.4.3  yamt      354: gpioclose(dev_t dev, int flag, int mode, struct lwp *l)
1.1       jmcneill  355: {
                    356:        struct gpio_softc *sc;
                    357:
1.15.4.1  yamt      358:        sc = device_lookup_private(&gpio_cd, minor(dev));
1.15.4.3  yamt      359:        DPRINTF(("%s: closing\n", device_xname(sc->sc_dev)));
1.15.4.1  yamt      360:        gpiobus_close(sc->sc_gc, sc->sc_dev);
1.1       jmcneill  361:        sc->sc_opened = 0;
                    362:
1.15.4.3  yamt      363:        return 0;
                    364: }
                    365:
                    366: int
                    367: gpio_pinbyname(struct gpio_softc *sc, char *gp_name)
                    368: {
                    369:         struct gpio_name *nm;
                    370:
                    371:         LIST_FOREACH(nm, &sc->sc_names, gp_next)
                    372:                 if (!strcmp(nm->gp_name, gp_name))
                    373:                         return nm->gp_pin;
                    374:         return -1;
1.1       jmcneill  375: }
                    376:
                    377: int
1.15.4.3  yamt      378: gpioioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
1.1       jmcneill  379: {
                    380:        struct gpio_softc *sc;
                    381:        gpio_chipset_tag_t gc;
                    382:        struct gpio_info *info;
1.15.4.3  yamt      383:        struct gpio_attach *attach;
                    384:        struct gpio_attach_args ga;
                    385:        struct gpio_dev *gdev;
                    386:        struct gpio_req *req;
                    387:        struct gpio_name *nm;
                    388:        struct gpio_set *set;
                    389:        device_t dv;
                    390:        cfdata_t cf;
                    391:        kauth_cred_t cred;
                    392:        int locs[GPIOCF_NLOCS];
1.15.4.4! yamt      393:        int pin, value, flags, npins;
1.1       jmcneill  394:
1.15.4.1  yamt      395:        sc = device_lookup_private(&gpio_cd, minor(dev));
1.1       jmcneill  396:        gc = sc->sc_gc;
                    397:
1.15.4.3  yamt      398:        if (cmd != GPIOINFO && !device_is_active(sc->sc_dev)) {
                    399:                DPRINTF(("%s: device is not active\n",
                    400:                    device_xname(sc->sc_dev)));
1.13      dyoung    401:                return EBUSY;
1.15.4.3  yamt      402:        }
                    403:
                    404:        cred = kauth_cred_get();
1.13      dyoung    405:
1.1       jmcneill  406:        switch (cmd) {
                    407:        case GPIOINFO:
                    408:                info = (struct gpio_info *)data;
1.15.4.3  yamt      409:                if (!kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    410:                    NULL, NULL, NULL, NULL))
                    411:                        info->gpio_npins = sc->sc_npins;
                    412:                else {
                    413:                        for (pin = npins = 0; pin < sc->sc_npins; pin++)
                    414:                                if (sc->sc_pins[pin].pin_flags & GPIO_PIN_SET)
                    415:                                        ++npins;
                    416:                        info->gpio_npins = npins;
                    417:                }
                    418:                break;
                    419:        case GPIOREAD:
                    420:                req = (struct gpio_req *)data;
                    421:
                    422:                if (req->gp_name[0] != '\0') {
                    423:                        pin = gpio_pinbyname(sc, req->gp_name);
                    424:                        if (pin == -1)
                    425:                                return EINVAL;
                    426:                } else
                    427:                        pin = req->gp_pin;
                    428:
                    429:                if (pin < 0 || pin >= sc->sc_npins)
                    430:                        return EINVAL;
                    431:
                    432:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    433:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    434:                    NULL, NULL, NULL, NULL))
                    435:                        return EPERM;
                    436:
                    437:                /* return read value */
                    438:                req->gp_value = gpiobus_pin_read(gc, pin);
                    439:                break;
                    440:        case GPIOWRITE:
                    441:                if ((flag & FWRITE) == 0)
                    442:                        return EBADF;
                    443:
                    444:                req = (struct gpio_req *)data;
                    445:
                    446:                if (req->gp_name[0] != '\0') {
                    447:                        pin = gpio_pinbyname(sc, req->gp_name);
                    448:                        if (pin == -1)
                    449:                                return EINVAL;
                    450:                } else
                    451:                        pin = req->gp_pin;
                    452:
                    453:                if (pin < 0 || pin >= sc->sc_npins)
                    454:                        return EINVAL;
                    455:
                    456:                if (sc->sc_pins[pin].pin_mapped)
                    457:                        return EBUSY;
                    458:
                    459:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    460:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    461:                    NULL, NULL, NULL, NULL))
                    462:                        return EPERM;
1.1       jmcneill  463:
1.15.4.3  yamt      464:                value = req->gp_value;
                    465:                if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
                    466:                        return EINVAL;
                    467:
                    468:                gpiobus_pin_write(gc, pin, value);
                    469:                /* return old value */
                    470:                req->gp_value = sc->sc_pins[pin].pin_state;
                    471:                /* update current value */
                    472:                sc->sc_pins[pin].pin_state = value;
1.1       jmcneill  473:                break;
1.15.4.3  yamt      474:        case GPIOTOGGLE:
                    475:                if ((flag & FWRITE) == 0)
                    476:                        return EBADF;
                    477:
                    478:                req = (struct gpio_req *)data;
                    479:
                    480:                if (req->gp_name[0] != '\0') {
                    481:                        pin = gpio_pinbyname(sc, req->gp_name);
                    482:                        if (pin == -1)
                    483:                                return EINVAL;
                    484:                } else
                    485:                        pin = req->gp_pin;
                    486:
                    487:                if (pin < 0 || pin >= sc->sc_npins)
                    488:                        return EINVAL;
                    489:
                    490:                if (sc->sc_pins[pin].pin_mapped)
                    491:                        return EBUSY;
                    492:
                    493:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    494:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    495:                    NULL, NULL, NULL, NULL))
                    496:                        return EPERM;
                    497:
                    498:                value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
                    499:                    GPIO_PIN_HIGH : GPIO_PIN_LOW);
                    500:                gpiobus_pin_write(gc, pin, value);
                    501:                /* return old value */
                    502:                req->gp_value = sc->sc_pins[pin].pin_state;
                    503:                /* update current value */
                    504:                sc->sc_pins[pin].pin_state = value;
                    505:                break;
                    506:        case GPIOATTACH:
                    507:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    508:                    NULL, NULL, NULL, NULL))
                    509:                        return EPERM;
1.15.4.4! yamt      510:
1.15.4.3  yamt      511:                attach = (struct gpio_attach *)data;
1.15.4.4! yamt      512:
        !           513:                /* do not try to attach if the pins are already mapped */
        !           514:                if (!gpio_pin_can_map(sc, attach->ga_offset, attach->ga_mask))
        !           515:                        return EBUSY;
        !           516:
1.15.4.3  yamt      517:                ga.ga_gpio = sc;
                    518:                ga.ga_dvname = attach->ga_dvname;
                    519:                ga.ga_offset = attach->ga_offset;
                    520:                ga.ga_mask = attach->ga_mask;
                    521:                DPRINTF(("%s: attach %s with offset %d and mask 0x%02x\n",
                    522:                    device_xname(sc->sc_dev), ga.ga_dvname, ga.ga_offset,
                    523:                    ga.ga_mask));
                    524:
                    525:                locs[GPIOCF_OFFSET] = ga.ga_offset;
                    526:                locs[GPIOCF_MASK] = ga.ga_mask;
                    527:
                    528:                cf = config_search_loc(NULL, sc->sc_dev, "gpio", locs, &ga);
                    529:                if (cf != NULL) {
                    530:                        dv = config_attach_loc(sc->sc_dev, cf, locs, &ga,
                    531:                            gpiobus_print);
                    532:                        if (dv != NULL) {
                    533:                                gdev = kmem_alloc(sizeof(struct gpio_dev),
                    534:                                    KM_SLEEP);
                    535:                                gdev->sc_dev = dv;
                    536:                                LIST_INSERT_HEAD(&sc->sc_devs, gdev, sc_next);
                    537:                        } else
                    538:                                return EINVAL;
                    539:                } else
                    540:                        return EINVAL;
                    541:                break;
                    542:        case GPIODETACH:
                    543:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    544:                    NULL, NULL, NULL, NULL))
                    545:                        return EPERM;
                    546:
                    547:                attach = (struct gpio_attach *)data;
                    548:                LIST_FOREACH(gdev, &sc->sc_devs, sc_next) {
                    549:                        if (strcmp(device_xname(gdev->sc_dev),
                    550:                            attach->ga_dvname) == 0) {
                    551:                                if (config_detach(gdev->sc_dev, 0) == 0) {
                    552:                                        LIST_REMOVE(gdev, sc_next);
                    553:                                        kmem_free(gdev,
                    554:                                            sizeof(struct gpio_dev));
                    555:                                        return 0;
                    556:                                }
                    557:                                break;
                    558:                        }
                    559:                }
                    560:                return EINVAL;
                    561:                break;
                    562:        case GPIOSET:
                    563:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    564:                    NULL, NULL, NULL, NULL))
                    565:                        return EPERM;
                    566:
                    567:                set = (struct gpio_set *)data;
                    568:
                    569:                if (set->gp_name[0] != '\0') {
                    570:                        pin = gpio_pinbyname(sc, set->gp_name);
                    571:                        if (pin == -1)
                    572:                                return EINVAL;
                    573:                } else
                    574:                        pin = set->gp_pin;
                    575:                if (pin < 0 || pin >= sc->sc_npins)
                    576:                        return EINVAL;
                    577:                flags = set->gp_flags;
                    578:
                    579:                /* check that the controller supports all requested flags */
                    580:                if ((flags & sc->sc_pins[pin].pin_caps) != flags)
                    581:                        return ENODEV;
                    582:                flags = set->gp_flags | GPIO_PIN_SET;
                    583:
                    584:                set->gp_caps = sc->sc_pins[pin].pin_caps;
                    585:                /* return old value */
                    586:                set->gp_flags = sc->sc_pins[pin].pin_flags;
                    587:                if (flags > 0) {
                    588:                        gpiobus_pin_ctl(gc, pin, flags);
                    589:                        /* update current value */
                    590:                        sc->sc_pins[pin].pin_flags = flags;
                    591:                }
                    592:
                    593:                /* rename pin or new pin? */
                    594:                if (set->gp_name2[0] != '\0') {
1.15.4.4! yamt      595:                        struct gpio_name *gnm;
        !           596:
        !           597:                        gnm = NULL;
        !           598:                        LIST_FOREACH(nm, &sc->sc_names, gp_next) {
        !           599:                                if (!strcmp(nm->gp_name, set->gp_name2) &&
        !           600:                                    nm->gp_pin != pin)
        !           601:                                        return EINVAL;  /* duplicate name */
        !           602:                                if (nm->gp_pin == pin)
        !           603:                                        gnm = nm;
        !           604:                        }
        !           605:                        if (gnm != NULL)
        !           606:                                strlcpy(gnm->gp_name, set->gp_name2,
        !           607:                                    sizeof(gnm->gp_name));
        !           608:                        else  {
1.15.4.3  yamt      609:                                nm = kmem_alloc(sizeof(struct gpio_name),
                    610:                                    KM_SLEEP);
                    611:                                strlcpy(nm->gp_name, set->gp_name2,
                    612:                                    sizeof(nm->gp_name));
                    613:                                nm->gp_pin = set->gp_pin;
                    614:                                LIST_INSERT_HEAD(&sc->sc_names, nm, gp_next);
                    615:                        }
                    616:                }
                    617:                break;
                    618:        case GPIOUNSET:
                    619:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    620:                    NULL, NULL, NULL, NULL))
                    621:                        return EPERM;
                    622:
                    623:                set = (struct gpio_set *)data;
                    624:                if (set->gp_name[0] != '\0') {
                    625:                        pin = gpio_pinbyname(sc, set->gp_name);
                    626:                        if (pin == -1)
                    627:                                return EINVAL;
                    628:                } else
                    629:                        pin = set->gp_pin;
                    630:
                    631:                if (pin < 0 || pin >= sc->sc_npins)
                    632:                        return EINVAL;
                    633:                if (sc->sc_pins[pin].pin_mapped)
                    634:                        return EBUSY;
                    635:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET))
                    636:                        return EINVAL;
                    637:
                    638:                LIST_FOREACH(nm, &sc->sc_names, gp_next) {
                    639:                        if (nm->gp_pin == pin) {
                    640:                                LIST_REMOVE(nm, gp_next);
                    641:                                kmem_free(nm, sizeof(struct gpio_name));
                    642:                                break;
                    643:                        }
                    644:                }
                    645:                sc->sc_pins[pin].pin_flags &= ~GPIO_PIN_SET;
                    646:                break;
                    647:        default:
                    648:                /* Try the old API */
                    649:                DPRINTF(("%s: trying the old API\n", device_xname(sc->sc_dev)));
                    650:                return gpio_ioctl_oapi(sc, cmd, data, flag, cred);
                    651:        }
                    652:        return 0;
                    653: }
                    654:
                    655: int
                    656: gpio_ioctl_oapi(struct gpio_softc *sc, u_long cmd, void *data, int flag,
                    657:     kauth_cred_t cred)
                    658: {
                    659:        gpio_chipset_tag_t gc;
                    660:        struct gpio_pin_op *op;
                    661:        struct gpio_pin_ctl *ctl;
                    662:        int pin, value, flags;
                    663:
                    664:        gc = sc->sc_gc;
                    665:
                    666:        switch (cmd) {
1.1       jmcneill  667:        case GPIOPINREAD:
                    668:                op = (struct gpio_pin_op *)data;
                    669:
                    670:                pin = op->gp_pin;
1.15.4.3  yamt      671:
1.1       jmcneill  672:                if (pin < 0 || pin >= sc->sc_npins)
1.15.4.3  yamt      673:                        return EINVAL;
                    674:
                    675:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    676:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    677:                    NULL, NULL, NULL, NULL))
                    678:                        return EPERM;
1.1       jmcneill  679:
                    680:                /* return read value */
                    681:                op->gp_value = gpiobus_pin_read(gc, pin);
                    682:                break;
                    683:        case GPIOPINWRITE:
1.15.4.3  yamt      684:                if ((flag & FWRITE) == 0)
                    685:                        return EBADF;
                    686:
1.1       jmcneill  687:                op = (struct gpio_pin_op *)data;
                    688:
                    689:                pin = op->gp_pin;
1.15.4.3  yamt      690:
1.1       jmcneill  691:                if (pin < 0 || pin >= sc->sc_npins)
1.15.4.3  yamt      692:                        return EINVAL;
                    693:
1.5       riz       694:                if (sc->sc_pins[pin].pin_mapped)
1.15.4.3  yamt      695:                        return EBUSY;
                    696:
                    697:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    698:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    699:                    NULL, NULL, NULL, NULL))
                    700:                        return EPERM;
1.1       jmcneill  701:
                    702:                value = op->gp_value;
                    703:                if (value != GPIO_PIN_LOW && value != GPIO_PIN_HIGH)
1.15.4.3  yamt      704:                        return EINVAL;
1.1       jmcneill  705:
                    706:                gpiobus_pin_write(gc, pin, value);
                    707:                /* return old value */
                    708:                op->gp_value = sc->sc_pins[pin].pin_state;
                    709:                /* update current value */
                    710:                sc->sc_pins[pin].pin_state = value;
                    711:                break;
                    712:        case GPIOPINTOGGLE:
1.15.4.3  yamt      713:                if ((flag & FWRITE) == 0)
                    714:                        return EBADF;
                    715:
1.1       jmcneill  716:                op = (struct gpio_pin_op *)data;
                    717:
                    718:                pin = op->gp_pin;
1.15.4.3  yamt      719:
1.1       jmcneill  720:                if (pin < 0 || pin >= sc->sc_npins)
1.15.4.3  yamt      721:                        return EINVAL;
                    722:
1.5       riz       723:                if (sc->sc_pins[pin].pin_mapped)
1.15.4.3  yamt      724:                        return EBUSY;
                    725:
                    726:                if (!(sc->sc_pins[pin].pin_flags & GPIO_PIN_SET) &&
                    727:                    kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    728:                    NULL, NULL, NULL, NULL))
                    729:                        return EPERM;
1.1       jmcneill  730:
                    731:                value = (sc->sc_pins[pin].pin_state == GPIO_PIN_LOW ?
                    732:                    GPIO_PIN_HIGH : GPIO_PIN_LOW);
                    733:                gpiobus_pin_write(gc, pin, value);
                    734:                /* return old value */
                    735:                op->gp_value = sc->sc_pins[pin].pin_state;
                    736:                /* update current value */
                    737:                sc->sc_pins[pin].pin_state = value;
                    738:                break;
                    739:        case GPIOPINCTL:
1.15.4.3  yamt      740:                ctl = (struct gpio_pin_ctl *) data;
                    741:
                    742:                if (kauth_authorize_device(cred, KAUTH_DEVICE_GPIO_PINSET,
                    743:                    NULL, NULL, NULL, NULL))
                    744:                        return EPERM;
1.1       jmcneill  745:
                    746:                pin = ctl->gp_pin;
1.15.4.3  yamt      747:
1.1       jmcneill  748:                if (pin < 0 || pin >= sc->sc_npins)
1.15.4.3  yamt      749:                        return EINVAL;
1.5       riz       750:                if (sc->sc_pins[pin].pin_mapped)
1.15.4.3  yamt      751:                        return EBUSY;
1.1       jmcneill  752:                flags = ctl->gp_flags;
1.15.4.3  yamt      753:
1.1       jmcneill  754:                /* check that the controller supports all requested flags */
                    755:                if ((flags & sc->sc_pins[pin].pin_caps) != flags)
1.15.4.3  yamt      756:                        return ENODEV;
1.1       jmcneill  757:
                    758:                ctl->gp_caps = sc->sc_pins[pin].pin_caps;
                    759:                /* return old value */
                    760:                ctl->gp_flags = sc->sc_pins[pin].pin_flags;
                    761:                if (flags > 0) {
                    762:                        gpiobus_pin_ctl(gc, pin, flags);
                    763:                        /* update current value */
                    764:                        sc->sc_pins[pin].pin_flags = flags;
                    765:                }
                    766:                break;
                    767:        default:
1.15.4.3  yamt      768:                return ENOTTY;
1.1       jmcneill  769:        }
1.15.4.3  yamt      770:        return 0;
1.1       jmcneill  771: }

CVSweb <webmaster@jp.NetBSD.org>