[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.39.2.2

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

CVSweb <webmaster@jp.NetBSD.org>