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

Annotation of src/sys/dev/i2c/i2c.c, Revision 1.47

1.47    ! riastrad    1: /*     $NetBSD: i2c.c,v 1.46 2015/01/22 17:56:35 jakllsch Exp $        */
1.1       thorpej     2:
                      3: /*
                      4:  * Copyright (c) 2003 Wasabi Systems, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed for the NetBSD Project by
                     20:  *      Wasabi Systems, Inc.
                     21:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
                     22:  *    or promote products derived from this software without specific prior
                     23:  *    written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
                     29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     35:  * POSSIBILITY OF SUCH DAMAGE.
                     36:  */
                     37:
1.45      jmcneill   38: #ifdef _KERNEL_OPT
                     39: #include "opt_i2c.h"
                     40: #endif
                     41:
1.18      lukem      42: #include <sys/cdefs.h>
1.47    ! riastrad   43: __KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.46 2015/01/22 17:56:35 jakllsch Exp $");
1.18      lukem      44:
1.1       thorpej    45: #include <sys/param.h>
                     46: #include <sys/systm.h>
                     47: #include <sys/device.h>
                     48: #include <sys/event.h>
                     49: #include <sys/conf.h>
1.11      jmcneill   50: #include <sys/malloc.h>
1.34      jmcneill   51: #include <sys/kmem.h>
1.11      jmcneill   52: #include <sys/kthread.h>
                     53: #include <sys/proc.h>
                     54: #include <sys/kernel.h>
1.32      jmcneill   55: #include <sys/fcntl.h>
1.28      mbalmer    56: #include <sys/module.h>
1.1       thorpej    57:
                     58: #include <dev/i2c/i2cvar.h>
                     59:
                     60: #include "locators.h"
                     61:
1.45      jmcneill   62: #ifndef I2C_MAX_ADDR
1.27      pgoyette   63: #define I2C_MAX_ADDR   0x3ff   /* 10-bit address, max */
1.45      jmcneill   64: #endif
1.27      pgoyette   65:
1.1       thorpej    66: struct iic_softc {
                     67:        i2c_tag_t sc_tag;
1.6       jmcneill   68:        int sc_type;
1.27      pgoyette   69:        device_t sc_devices[I2C_MAX_ADDR + 1];
1.1       thorpej    70: };
                     71:
1.31      jmcneill   72: static dev_type_open(iic_open);
                     73: static dev_type_close(iic_close);
                     74: static dev_type_ioctl(iic_ioctl);
                     75:
                     76: const struct cdevsw iic_cdevsw = {
1.43      dholland   77:        .d_open = iic_open,
                     78:        .d_close = iic_close,
                     79:        .d_read = noread,
                     80:        .d_write = nowrite,
                     81:        .d_ioctl = iic_ioctl,
                     82:        .d_stop = nostop,
                     83:        .d_tty = notty,
                     84:        .d_poll = nopoll,
                     85:        .d_mmap = nommap,
                     86:        .d_kqfilter = nokqfilter,
1.44      dholland   87:        .d_discard = nodiscard,
1.43      dholland   88:        .d_flag = D_OTHER
1.31      jmcneill   89: };
                     90:
                     91: extern struct cfdriver iic_cd;
                     92:
1.11      jmcneill   93: static void    iic_smbus_intr_thread(void *);
1.24      martin     94: static void    iic_fill_compat(struct i2c_attach_args*, const char*,
                     95:                        size_t, char **);
1.11      jmcneill   96:
1.1       thorpej    97: static int
1.24      martin     98: iic_print_direct(void *aux, const char *pnp)
                     99: {
                    100:        struct i2c_attach_args *ia = aux;
                    101:
                    102:        if (pnp != NULL)
                    103:                aprint_normal("%s at %s addr 0x%02x", ia->ia_name, pnp,
                    104:                        ia->ia_addr);
                    105:        else
                    106:                aprint_normal(" addr 0x%02x", ia->ia_addr);
                    107:
                    108:        return UNCONF;
                    109: }
                    110:
                    111: static int
1.10      christos  112: iic_print(void *aux, const char *pnp)
1.1       thorpej   113: {
                    114:        struct i2c_attach_args *ia = aux;
                    115:
1.6       jmcneill  116:        if (ia->ia_addr != (i2c_addr_t)-1)
                    117:                aprint_normal(" addr 0x%x", ia->ia_addr);
1.1       thorpej   118:
1.30      mbalmer   119:        return UNCONF;
1.1       thorpej   120: }
                    121:
                    122: static int
1.20      xtraeme   123: iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
1.1       thorpej   124: {
1.20      xtraeme   125:        struct iic_softc *sc = device_private(parent);
1.1       thorpej   126:        struct i2c_attach_args ia;
                    127:
                    128:        ia.ia_tag = sc->sc_tag;
                    129:        ia.ia_size = cf->cf_loc[IICCF_SIZE];
1.6       jmcneill  130:        ia.ia_type = sc->sc_type;
1.1       thorpej   131:
1.25      njoly     132:        ia.ia_name = NULL;
                    133:        ia.ia_ncompat = 0;
                    134:        ia.ia_compat = NULL;
                    135:
1.40      soren     136:        for (ia.ia_addr = 0; ia.ia_addr <= I2C_MAX_ADDR; ia.ia_addr++) {
                    137:                if (sc->sc_devices[ia.ia_addr] != NULL)
                    138:                        continue;
                    139:
                    140:                if (cf->cf_loc[IICCF_ADDR] != -1 &&
                    141:                    cf->cf_loc[IICCF_ADDR] != ia.ia_addr)
                    142:                        continue;
                    143:
                    144:                if (config_match(parent, cf, &ia) > 0)
1.27      pgoyette  145:                        sc->sc_devices[ia.ia_addr] =
                    146:                            config_attach(parent, cf, &ia, iic_print);
                    147:        }
1.40      soren     148:
1.30      mbalmer   149:        return 0;
1.1       thorpej   150: }
                    151:
1.27      pgoyette  152: static void
                    153: iic_child_detach(device_t parent, device_t child)
                    154: {
                    155:        struct iic_softc *sc = device_private(parent);
                    156:        int i;
                    157:
                    158:        for (i = 0; i <= I2C_MAX_ADDR; i++)
                    159:                if (sc->sc_devices[i] == child) {
                    160:                        sc->sc_devices[i] = NULL;
                    161:                        break;
1.40      soren     162:                }
1.27      pgoyette  163: }
                    164:
1.1       thorpej   165: static int
1.26      jmcneill  166: iic_rescan(device_t self, const char *ifattr, const int *locators)
                    167: {
                    168:        config_search_ia(iic_search, self, ifattr, NULL);
                    169:        return 0;
                    170: }
                    171:
                    172: static int
1.20      xtraeme   173: iic_match(device_t parent, cfdata_t cf, void *aux)
1.1       thorpej   174: {
                    175:
1.30      mbalmer   176:        return 1;
1.1       thorpej   177: }
                    178:
                    179: static void
1.20      xtraeme   180: iic_attach(device_t parent, device_t self, void *aux)
1.1       thorpej   181: {
1.7       thorpej   182:        struct iic_softc *sc = device_private(self);
1.1       thorpej   183:        struct i2cbus_attach_args *iba = aux;
1.24      martin    184:        prop_array_t child_devices;
1.42      jdc       185:        prop_dictionary_t props;
1.24      martin    186:        char *buf;
1.14      ad        187:        i2c_tag_t ic;
                    188:        int rv;
1.42      jdc       189:        bool indirect_config;
1.1       thorpej   190:
1.33      jmcneill  191:        aprint_naive("\n");
1.1       thorpej   192:        aprint_normal(": I2C bus\n");
                    193:
                    194:        sc->sc_tag = iba->iba_tag;
1.6       jmcneill  195:        sc->sc_type = iba->iba_type;
1.14      ad        196:        ic = sc->sc_tag;
1.19      cegger    197:        ic->ic_devname = device_xname(self);
1.11      jmcneill  198:
1.13      jmcneill  199:        LIST_INIT(&(sc->sc_tag->ic_list));
                    200:        LIST_INIT(&(sc->sc_tag->ic_proc_list));
1.14      ad        201:
1.33      jmcneill  202:        rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
                    203:            iic_smbus_intr_thread, ic, &ic->ic_intr_thread,
                    204:            "%s", ic->ic_devname);
1.14      ad        205:        if (rv)
1.20      xtraeme   206:                aprint_error_dev(self, "unable to create intr thread\n");
1.1       thorpej   207:
1.17      jmcneill  208:        if (!pmf_device_register(self, NULL, NULL))
                    209:                aprint_error_dev(self, "couldn't establish power handler\n");
                    210:
1.42      jdc       211:        props = device_properties(parent);
                    212:        if (!prop_dictionary_get_bool(props, "i2c-indirect-config",
                    213:            &indirect_config))
                    214:                indirect_config = true;
                    215:        child_devices = prop_dictionary_get(props, "i2c-child-devices");
1.24      martin    216:        if (child_devices) {
                    217:                unsigned int i, count;
                    218:                prop_dictionary_t dev;
                    219:                prop_data_t cdata;
                    220:                uint32_t addr, size;
                    221:                uint64_t cookie;
                    222:                const char *name;
                    223:                struct i2c_attach_args ia;
                    224:                int loc[2];
                    225:
                    226:                memset(loc, 0, sizeof loc);
                    227:                count = prop_array_count(child_devices);
                    228:                for (i = 0; i < count; i++) {
                    229:                        dev = prop_array_get(child_devices, i);
                    230:                        if (!dev) continue;
                    231:                        if (!prop_dictionary_get_cstring_nocopy(
                    232:                            dev, "name", &name))
                    233:                                continue;
                    234:                        if (!prop_dictionary_get_uint32(dev, "addr", &addr))
                    235:                                continue;
                    236:                        if (!prop_dictionary_get_uint64(dev, "cookie", &cookie))
                    237:                                cookie = 0;
                    238:                        loc[0] = addr;
                    239:                        if (prop_dictionary_get_uint32(dev, "size", &size))
                    240:                                loc[1] = size;
                    241:                        else
                    242:                                loc[1] = -1;
                    243:
                    244:                        memset(&ia, 0, sizeof ia);
                    245:                        ia.ia_addr = addr;
                    246:                        ia.ia_type = sc->sc_type;
                    247:                        ia.ia_tag = ic;
                    248:                        ia.ia_name = name;
                    249:                        ia.ia_cookie = cookie;
1.39      jdc       250:                        ia.ia_size = size;
1.24      martin    251:
                    252:                        buf = NULL;
                    253:                        cdata = prop_dictionary_get(dev, "compatible");
                    254:                        if (cdata)
                    255:                                iic_fill_compat(&ia,
                    256:                                    prop_data_data_nocopy(cdata),
                    257:                                    prop_data_size(cdata), &buf);
                    258:
1.33      jmcneill  259:                        if (addr > I2C_MAX_ADDR) {
                    260:                                aprint_error_dev(self,
                    261:                                    "WARNING: ignoring bad device address "
                    262:                                    "@ 0x%02x\n", addr);
                    263:                        } else if (sc->sc_devices[addr] == NULL) {
                    264:                                sc->sc_devices[addr] =
                    265:                                    config_found_sm_loc(self, "iic", loc, &ia,
                    266:                                        iic_print_direct, NULL);
                    267:                        }
1.24      martin    268:
                    269:                        if (ia.ia_compat)
                    270:                                free(ia.ia_compat, M_TEMP);
                    271:                        if (buf)
                    272:                                free(buf, M_TEMP);
                    273:                }
1.42      jdc       274:        } else if (indirect_config) {
1.24      martin    275:                /*
                    276:                 * Attach all i2c devices described in the kernel
                    277:                 * configuration file.
                    278:                 */
1.26      jmcneill  279:                iic_rescan(self, "iic", NULL);
1.24      martin    280:        }
1.1       thorpej   281: }
                    282:
1.33      jmcneill  283: static int
                    284: iic_detach(device_t self, int flags)
                    285: {
                    286:        struct iic_softc *sc = device_private(self);
                    287:        i2c_tag_t ic = sc->sc_tag;
                    288:        int i, error;
                    289:        void *hdl;
                    290:
                    291:        for (i = 0; i <= I2C_MAX_ADDR; i++) {
                    292:                if (sc->sc_devices[i]) {
                    293:                        error = config_detach(sc->sc_devices[i], flags);
                    294:                        if (error)
                    295:                                return error;
                    296:                }
                    297:        }
                    298:
                    299:        if (ic->ic_running) {
                    300:                ic->ic_running = 0;
                    301:                wakeup(ic);
                    302:                kthread_join(ic->ic_intr_thread);
                    303:        }
                    304:
                    305:        if (!LIST_EMPTY(&ic->ic_list)) {
                    306:                device_printf(self, "WARNING: intr handler list not empty\n");
                    307:                while (!LIST_EMPTY(&ic->ic_list)) {
                    308:                        hdl = LIST_FIRST(&ic->ic_list);
                    309:                        iic_smbus_intr_disestablish(ic, hdl);
                    310:                }
                    311:        }
                    312:        if (!LIST_EMPTY(&ic->ic_proc_list)) {
                    313:                device_printf(self, "WARNING: proc handler list not empty\n");
                    314:                while (!LIST_EMPTY(&ic->ic_proc_list)) {
                    315:                        hdl = LIST_FIRST(&ic->ic_proc_list);
                    316:                        iic_smbus_intr_disestablish_proc(ic, hdl);
                    317:                }
                    318:        }
                    319:
                    320:        pmf_device_deregister(self);
                    321:
                    322:        return 0;
                    323: }
                    324:
1.11      jmcneill  325: static void
1.14      ad        326: iic_smbus_intr_thread(void *aux)
1.11      jmcneill  327: {
                    328:        i2c_tag_t ic;
                    329:        struct ic_intr_list *il;
                    330:
                    331:        ic = (i2c_tag_t)aux;
                    332:        ic->ic_running = 1;
                    333:        ic->ic_pending = 0;
                    334:
                    335:        while (ic->ic_running) {
                    336:                if (ic->ic_pending == 0)
1.41      martin    337:                        tsleep(ic, PZERO, "iicintr", hz);
1.11      jmcneill  338:                if (ic->ic_pending > 0) {
                    339:                        LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
                    340:                                (*il->il_intr)(il->il_intrarg);
                    341:                        }
                    342:                        ic->ic_pending--;
                    343:                }
                    344:        }
                    345:
                    346:        kthread_exit(0);
                    347: }
                    348:
                    349: void *
                    350: iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
                    351: {
                    352:        struct ic_intr_list *il;
                    353:
                    354:        il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
                    355:        if (il == NULL)
                    356:                return NULL;
1.28      mbalmer   357:
1.11      jmcneill  358:        il->il_intr = intr;
                    359:        il->il_intrarg = intrarg;
                    360:
                    361:        LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
                    362:
                    363:        return il;
                    364: }
                    365:
                    366: void
                    367: iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
                    368: {
                    369:        struct ic_intr_list *il;
                    370:
                    371:        il = (struct ic_intr_list *)hdl;
                    372:
                    373:        LIST_REMOVE(il, il_next);
                    374:        free(il, M_DEVBUF);
                    375:
                    376:        return;
                    377: }
                    378:
                    379: void *
                    380: iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
                    381: {
                    382:        struct ic_intr_list *il;
                    383:
                    384:        il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
                    385:        if (il == NULL)
                    386:                return NULL;
1.28      mbalmer   387:
1.11      jmcneill  388:        il->il_intr = intr;
                    389:        il->il_intrarg = intrarg;
                    390:
                    391:        LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
                    392:
                    393:        return il;
                    394: }
                    395:
                    396: void
                    397: iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
                    398: {
                    399:        struct ic_intr_list *il;
                    400:
                    401:        il = (struct ic_intr_list *)hdl;
                    402:
                    403:        LIST_REMOVE(il, il_next);
                    404:        free(il, M_DEVBUF);
                    405:
                    406:        return;
                    407: }
                    408:
                    409: int
                    410: iic_smbus_intr(i2c_tag_t ic)
                    411: {
                    412:        struct ic_intr_list *il;
                    413:
                    414:        LIST_FOREACH(il, &(ic->ic_list), il_next) {
                    415:                (*il->il_intr)(il->il_intrarg);
                    416:        }
                    417:
                    418:        ic->ic_pending++;
                    419:        wakeup(ic);
                    420:
                    421:        return 1;
                    422: }
                    423:
1.24      martin    424: static void
                    425: iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len,
                    426:        char **buffer)
                    427: {
                    428:        int count, i;
                    429:        const char *c, *start, **ptr;
                    430:
                    431:        *buffer = NULL;
                    432:        for (i = count = 0, c = compat; i < len; i++, c++)
                    433:                if (*c == 0)
                    434:                        count++;
                    435:        count += 2;
                    436:        ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK);
                    437:        if (!ptr) return;
                    438:
                    439:        for (i = count = 0, start = c = compat; i < len; i++, c++) {
                    440:                if (*c == 0) {
                    441:                        ptr[count++] = start;
                    442:                        start = c+1;
                    443:                }
                    444:        }
                    445:        if (start < compat+len) {
                    446:                /* last string not 0 terminated */
                    447:                size_t l = c-start;
                    448:                *buffer = malloc(l+1, M_TEMP, M_WAITOK);
                    449:                memcpy(*buffer, start, l);
                    450:                (*buffer)[l] = 0;
                    451:                ptr[count++] = *buffer;
                    452:        }
                    453:        ptr[count] = NULL;
                    454:
                    455:        ia->ia_compat = ptr;
                    456:        ia->ia_ncompat = count;
                    457: }
                    458:
                    459: int
                    460: iic_compat_match(struct i2c_attach_args *ia, const char ** compats)
                    461: {
                    462:        int i;
                    463:
                    464:        for (; compats && *compats; compats++) {
                    465:                for (i = 0; i < ia->ia_ncompat; i++) {
                    466:                        if (strcmp(*compats, ia->ia_compat[i]) == 0)
                    467:                                return 1;
                    468:                }
                    469:        }
                    470:        return 0;
                    471: }
                    472:
1.31      jmcneill  473: static int
                    474: iic_open(dev_t dev, int flag, int fmt, lwp_t *l)
                    475: {
                    476:        struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
                    477:
                    478:        if (sc == NULL)
                    479:                return ENXIO;
                    480:
                    481:        return 0;
                    482: }
                    483:
                    484: static int
                    485: iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
                    486: {
                    487:        return 0;
                    488: }
                    489:
                    490: static int
1.32      jmcneill  491: iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag)
1.31      jmcneill  492: {
                    493:        i2c_tag_t ic = sc->sc_tag;
                    494:        uint8_t buf[I2C_EXEC_MAX_BUFLEN];
1.34      jmcneill  495:        void *cmd = NULL;
1.31      jmcneill  496:        int error;
                    497:
                    498:        /* Validate parameters */
                    499:        if (iie->iie_addr > I2C_MAX_ADDR)
                    500:                return EINVAL;
                    501:        if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN ||
                    502:            iie->iie_buflen > I2C_EXEC_MAX_BUFLEN)
                    503:                return EINVAL;
                    504:        if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0)
                    505:                return EINVAL;
                    506:        if (iie->iie_buf != NULL && iie->iie_buflen == 0)
                    507:                return EINVAL;
1.32      jmcneill  508:        if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0)
                    509:                return EBADF;
1.31      jmcneill  510:
                    511: #if 0
                    512:        /* Disallow userspace access to devices that have drivers attached. */
                    513:        if (sc->sc_devices[iie->iie_addr] != NULL)
                    514:                return EBUSY;
                    515: #endif
                    516:
                    517:        if (iie->iie_cmd != NULL) {
1.34      jmcneill  518:                cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP);
                    519:                if (cmd == NULL)
                    520:                        return ENOMEM;
1.31      jmcneill  521:                error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen);
1.34      jmcneill  522:                if (error) {
                    523:                        kmem_free(cmd, iie->iie_cmdlen);
1.31      jmcneill  524:                        return error;
1.34      jmcneill  525:                }
1.31      jmcneill  526:        }
                    527:
1.46      jakllsch  528:        if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) {
                    529:                error = copyin(iie->iie_buf, buf, iie->iie_buflen);
                    530:                if (error) {
1.47    ! riastrad  531:                        if (cmd)
        !           532:                                kmem_free(cmd, iie->iie_cmdlen);
1.46      jakllsch  533:                        return error;
                    534:                }
                    535:        }
                    536:
1.31      jmcneill  537:        iic_acquire_bus(ic, 0);
                    538:        error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen,
                    539:            buf, iie->iie_buflen, 0);
                    540:        iic_release_bus(ic, 0);
                    541:
1.36      jmcneill  542:        /*
                    543:         * Some drivers return error codes on failure, and others return -1.
                    544:         */
                    545:        if (error < 0)
                    546:                error = EIO;
                    547:
1.34      jmcneill  548:        if (cmd)
                    549:                kmem_free(cmd, iie->iie_cmdlen);
                    550:
1.31      jmcneill  551:        if (error)
                    552:                return error;
                    553:
1.46      jakllsch  554:        if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op))
1.31      jmcneill  555:                error = copyout(buf, iie->iie_buf, iie->iie_buflen);
                    556:
                    557:        return error;
                    558: }
                    559:
                    560: static int
                    561: iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
                    562: {
                    563:        struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
                    564:
                    565:        if (sc == NULL)
                    566:                return ENXIO;
                    567:
                    568:        switch (cmd) {
                    569:        case I2C_IOCTL_EXEC:
1.32      jmcneill  570:                return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag);
1.31      jmcneill  571:        default:
                    572:                return ENODEV;
                    573:        }
                    574: }
                    575:
1.24      martin    576:
1.26      jmcneill  577: CFATTACH_DECL2_NEW(iic, sizeof(struct iic_softc),
1.33      jmcneill  578:     iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach);
1.28      mbalmer   579:
                    580: MODULE(MODULE_CLASS_DRIVER, iic, NULL);
                    581:
                    582: #ifdef _MODULE
                    583: #include "ioconf.c"
                    584: #endif
                    585:
                    586: static int
                    587: iic_modcmd(modcmd_t cmd, void *opaque)
                    588: {
                    589:        int error;
                    590:
                    591:        error = 0;
                    592:        switch (cmd) {
                    593:        case MODULE_CMD_INIT:
                    594: #ifdef _MODULE
                    595:                error = config_init_component(cfdriver_ioconf_iic,
                    596:                    cfattach_ioconf_iic, cfdata_ioconf_iic);
                    597:                if (error)
                    598:                        aprint_error("%s: unable to init component\n",
                    599:                            iic_cd.cd_name);
                    600: #endif
                    601:                break;
                    602:        case MODULE_CMD_FINI:
                    603: #ifdef _MODULE
                    604:                config_fini_component(cfdriver_ioconf_iic,
                    605:                    cfattach_ioconf_iic, cfdata_ioconf_iic);
                    606: #endif
                    607:                break;
                    608:        default:
                    609:                error = ENOTTY;
                    610:        }
                    611:        return error;
                    612: }

CVSweb <webmaster@jp.NetBSD.org>