[BACK]Return to i82365.c CVS log [TXT][DIR] Up to [local] / sys / dev / ic

Annotation of sys/dev/ic/i82365.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: i82365.c,v 1.25 2005/11/23 11:39:37 mickey Exp $      */
        !             2: /*     $NetBSD: i82365.c,v 1.10 1998/06/09 07:36:55 thorpej Exp $      */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  * 3. All advertising materials mentioning features or use of this software
        !            16:  *    must display the following acknowledgement:
        !            17:  *     This product includes software developed by Marc Horowitz.
        !            18:  * 4. The name of the author may not be used to endorse or promote products
        !            19:  *    derived from this software without specific prior written permission.
        !            20:  *
        !            21:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            22:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            23:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            24:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            25:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            26:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            27:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            28:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            29:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            30:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: #include <sys/types.h>
        !            34: #include <sys/param.h>
        !            35: #include <sys/systm.h>
        !            36: #include <sys/device.h>
        !            37: #include <sys/extent.h>
        !            38: #include <sys/kernel.h>
        !            39: #include <sys/malloc.h>
        !            40: #include <sys/kthread.h>
        !            41:
        !            42: #include <uvm/uvm_extern.h>
        !            43:
        !            44: #include <machine/bus.h>
        !            45: #include <machine/intr.h>
        !            46:
        !            47: #include <dev/pcmcia/pcmciareg.h>
        !            48: #include <dev/pcmcia/pcmciavar.h>
        !            49:
        !            50: #include <dev/ic/i82365reg.h>
        !            51: #include <dev/ic/i82365var.h>
        !            52:
        !            53: #ifdef PCICDEBUG
        !            54: #define        DPRINTF(arg)    printf arg;
        !            55: #else
        !            56: #define        DPRINTF(arg)
        !            57: #endif
        !            58:
        !            59: #define        PCIC_VENDOR_UNKNOWN             0
        !            60: #define        PCIC_VENDOR_I82365SLR0          1
        !            61: #define        PCIC_VENDOR_I82365SLR1          2
        !            62: #define        PCIC_VENDOR_I82365SLR2          3
        !            63: #define        PCIC_VENDOR_CIRRUS_PD6710       4
        !            64: #define        PCIC_VENDOR_CIRRUS_PD672X       5
        !            65: #define        PCIC_VENDOR_VADEM_VG468         6
        !            66: #define        PCIC_VENDOR_VADEM_VG469         7
        !            67:
        !            68: static char *pcic_vendor_to_string[] = {
        !            69:        "Unknown",
        !            70:        "Intel 82365SL rev 0",
        !            71:        "Intel 82365SL rev 1",
        !            72:        "Intel 82365SL rev 2",
        !            73:        "Cirrus PD6710",
        !            74:        "Cirrus PD672X",
        !            75:        "Vadem VG468",
        !            76:        "Vadem VG469",
        !            77: };
        !            78:
        !            79: /*
        !            80:  * Individual drivers will allocate their own memory and io regions. Memory
        !            81:  * regions must be a multiple of 4k, aligned on a 4k boundary.
        !            82:  */
        !            83:
        !            84: #define        PCIC_MEM_ALIGN  PCIC_MEM_PAGESIZE
        !            85:
        !            86: void   pcic_attach_socket(struct pcic_handle *);
        !            87: void   pcic_init_socket(struct pcic_handle *);
        !            88:
        !            89: int    pcic_submatch(struct device *, void *, void *);
        !            90: int    pcic_print(void *arg, const char *pnp);
        !            91: int    pcic_intr_socket(struct pcic_handle *);
        !            92:
        !            93: void   pcic_attach_card(struct pcic_handle *);
        !            94: void   pcic_detach_card(struct pcic_handle *, int);
        !            95: void   pcic_deactivate_card(struct pcic_handle *);
        !            96:
        !            97: void   pcic_chip_do_mem_map(struct pcic_handle *, int);
        !            98: void   pcic_chip_do_io_map(struct pcic_handle *, int);
        !            99:
        !           100: void   pcic_create_event_thread(void *);
        !           101: void   pcic_event_thread(void *);
        !           102: void   pcic_event_process(struct pcic_handle *, struct pcic_event *);
        !           103: void   pcic_queue_event(struct pcic_handle *, int);
        !           104:
        !           105: void   pcic_wait_ready(struct pcic_handle *);
        !           106:
        !           107: u_int8_t st_pcic_read(struct pcic_handle *, int);
        !           108: void   st_pcic_write(struct pcic_handle *, int, int);
        !           109:
        !           110: struct cfdriver pcic_cd = {
        !           111:        NULL, "pcic", DV_DULL
        !           112: };
        !           113:
        !           114: int
        !           115: pcic_ident_ok(ident)
        !           116:        int ident;
        !           117: {
        !           118:        /* this is very empirical and heuristic */
        !           119:
        !           120:        if (ident == 0 || ident == 0xff || (ident & PCIC_IDENT_ZERO))
        !           121:                return (0);
        !           122:
        !           123:        if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) {
        !           124: #ifdef DIAGNOSTIC
        !           125:                printf("pcic: does not support memory and I/O cards, "
        !           126:                    "ignored (ident=%0x)\n", ident);
        !           127: #endif
        !           128:                return (0);
        !           129:        }
        !           130:        return (1);
        !           131: }
        !           132:
        !           133: int
        !           134: pcic_vendor(h)
        !           135:        struct pcic_handle *h;
        !           136: {
        !           137:        int vendor, reg;
        !           138:
        !           139:        /*
        !           140:         * the chip_id of the cirrus toggles between 11 and 00 after a write.
        !           141:         * weird.
        !           142:         */
        !           143:
        !           144:        pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0);
        !           145:        reg = pcic_read(h, -1);
        !           146:
        !           147:        if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) ==
        !           148:            PCIC_CIRRUS_CHIP_INFO_CHIP_ID) {
        !           149:                reg = pcic_read(h, -1);
        !           150:                if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
        !           151:                        if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)
        !           152:                                return (PCIC_VENDOR_CIRRUS_PD672X);
        !           153:                        else
        !           154:                                return (PCIC_VENDOR_CIRRUS_PD6710);
        !           155:                }
        !           156:        }
        !           157:
        !           158:        reg = pcic_read(h, PCIC_IDENT);
        !           159:
        !           160:        switch (reg) {
        !           161:        case PCIC_IDENT_REV_I82365SLR0:
        !           162:                vendor = PCIC_VENDOR_I82365SLR0;
        !           163:                break;
        !           164:        case PCIC_IDENT_REV_I82365SLR1:
        !           165:                vendor = PCIC_VENDOR_I82365SLR1;
        !           166:                break;
        !           167:        case PCIC_IDENT_REV_I82365SLR2:
        !           168:                vendor = PCIC_VENDOR_I82365SLR2;
        !           169:                break;
        !           170:        default:
        !           171:                vendor = PCIC_VENDOR_UNKNOWN;
        !           172:                break;
        !           173:        }
        !           174:
        !           175:        pcic_write(h, 0x0e, -1);
        !           176:        pcic_write(h, 0x37, -1);
        !           177:
        !           178:        reg = pcic_read(h, PCIC_VG468_MISC);
        !           179:        reg |= PCIC_VG468_MISC_VADEMREV;
        !           180:        pcic_write(h, PCIC_VG468_MISC, reg);
        !           181:
        !           182:        reg = pcic_read(h, PCIC_IDENT);
        !           183:
        !           184:        if (reg & PCIC_IDENT_VADEM_MASK) {
        !           185:                if ((reg & 7) >= 4)
        !           186:                        vendor = PCIC_VENDOR_VADEM_VG469;
        !           187:                else
        !           188:                        vendor = PCIC_VENDOR_VADEM_VG468;
        !           189:
        !           190:                reg = pcic_read(h, PCIC_VG468_MISC);
        !           191:                reg &= ~PCIC_VG468_MISC_VADEMREV;
        !           192:                pcic_write(h, PCIC_VG468_MISC, reg);
        !           193:        }
        !           194:
        !           195:        return (vendor);
        !           196: }
        !           197:
        !           198: void
        !           199: pcic_attach(sc)
        !           200:        struct pcic_softc *sc;
        !           201: {
        !           202:        int vendor, count, i, reg;
        !           203:
        !           204:        /* now check for each controller/socket */
        !           205:
        !           206:        /*
        !           207:         * this could be done with a loop, but it would violate the
        !           208:         * abstraction
        !           209:         */
        !           210:
        !           211:        count = 0;
        !           212:
        !           213:        DPRINTF(("pcic ident regs:"));
        !           214:
        !           215:        sc->handle[0].ph_parent = (struct device *)sc;
        !           216:        sc->handle[0].sock = C0SA;
        !           217:        /* initialise pcic_read and pcic_write functions */
        !           218:        sc->handle[0].ph_read = st_pcic_read;
        !           219:        sc->handle[0].ph_write = st_pcic_write;
        !           220:        sc->handle[0].ph_bus_t = sc->iot;
        !           221:        sc->handle[0].ph_bus_h = sc->ioh;
        !           222:        if (pcic_ident_ok(reg = pcic_read(&sc->handle[0], PCIC_IDENT))) {
        !           223:                sc->handle[0].flags = PCIC_FLAG_SOCKETP;
        !           224:                count++;
        !           225:        } else {
        !           226:                sc->handle[0].flags = 0;
        !           227:        }
        !           228:        sc->handle[0].laststate = PCIC_LASTSTATE_EMPTY;
        !           229:
        !           230:        DPRINTF((" 0x%02x", reg));
        !           231:
        !           232:        sc->handle[1].ph_parent = (struct device *)sc;
        !           233:        sc->handle[1].sock = C0SB;
        !           234:        /* initialise pcic_read and pcic_write functions */
        !           235:        sc->handle[1].ph_read = st_pcic_read;
        !           236:        sc->handle[1].ph_write = st_pcic_write;
        !           237:        sc->handle[1].ph_bus_t = sc->iot;
        !           238:        sc->handle[1].ph_bus_h = sc->ioh;
        !           239:        if (pcic_ident_ok(reg = pcic_read(&sc->handle[1], PCIC_IDENT))) {
        !           240:                sc->handle[1].flags = PCIC_FLAG_SOCKETP;
        !           241:                count++;
        !           242:        } else {
        !           243:                sc->handle[1].flags = 0;
        !           244:        }
        !           245:        sc->handle[1].laststate = PCIC_LASTSTATE_EMPTY;
        !           246:
        !           247:        DPRINTF((" 0x%02x", reg));
        !           248:
        !           249:        /*
        !           250:         * The CL-PD6729 has only one controller and always returns 0
        !           251:         * if you try to read from the second one. Maybe pcic_ident_ok
        !           252:         * shouldn't accept 0?
        !           253:         */
        !           254:        sc->handle[2].ph_parent = (struct device *)sc;
        !           255:        sc->handle[2].sock = C1SA;
        !           256:        /* initialise pcic_read and pcic_write functions */
        !           257:        sc->handle[2].ph_read = st_pcic_read;
        !           258:        sc->handle[2].ph_write = st_pcic_write;
        !           259:        sc->handle[2].ph_bus_t = sc->iot;
        !           260:        sc->handle[2].ph_bus_h = sc->ioh;
        !           261:        if (pcic_vendor(&sc->handle[0]) != PCIC_VENDOR_CIRRUS_PD672X ||
        !           262:            pcic_read(&sc->handle[2], PCIC_IDENT) != 0) {
        !           263:                if (pcic_ident_ok(reg = pcic_read(&sc->handle[2],
        !           264:                    PCIC_IDENT))) {
        !           265:                        sc->handle[2].flags = PCIC_FLAG_SOCKETP;
        !           266:                        count++;
        !           267:                } else {
        !           268:                        sc->handle[2].flags = 0;
        !           269:                }
        !           270:                sc->handle[2].laststate = PCIC_LASTSTATE_EMPTY;
        !           271:
        !           272:                DPRINTF((" 0x%02x", reg));
        !           273:
        !           274:                sc->handle[3].ph_parent = (struct device *)sc;
        !           275:                sc->handle[3].sock = C1SB;
        !           276:                /* initialise pcic_read and pcic_write functions */
        !           277:                sc->handle[3].ph_read = st_pcic_read;
        !           278:                sc->handle[3].ph_write = st_pcic_write;
        !           279:                sc->handle[3].ph_bus_t = sc->iot;
        !           280:                sc->handle[3].ph_bus_h = sc->ioh;
        !           281:                if (pcic_ident_ok(reg = pcic_read(&sc->handle[3],
        !           282:                    PCIC_IDENT))) {
        !           283:                        sc->handle[3].flags = PCIC_FLAG_SOCKETP;
        !           284:                        count++;
        !           285:                } else {
        !           286:                        sc->handle[3].flags = 0;
        !           287:                }
        !           288:                sc->handle[3].laststate = PCIC_LASTSTATE_EMPTY;
        !           289:
        !           290:                DPRINTF((" 0x%02x\n", reg));
        !           291:        } else {
        !           292:                sc->handle[2].flags = 0;
        !           293:                sc->handle[3].flags = 0;
        !           294:        }
        !           295:
        !           296:        if (count == 0)
        !           297:                return;
        !           298:
        !           299:        /* establish the interrupt */
        !           300:
        !           301:        /* XXX block interrupts? */
        !           302:
        !           303:        for (i = 0; i < PCIC_NSLOTS; i++) {
        !           304:                /*
        !           305:                 * this should work, but w/o it, setting tty flags hangs at
        !           306:                 * boot time.
        !           307:                 */
        !           308:                if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) {
        !           309:                        SIMPLEQ_INIT(&sc->handle[i].events);
        !           310:                        pcic_write(&sc->handle[i], PCIC_CSC_INTR, 0);
        !           311:                        pcic_read(&sc->handle[i], PCIC_CSC);
        !           312:                }
        !           313:        }
        !           314:
        !           315:        for (i = 0; i < PCIC_NSLOTS; i += 2) {
        !           316:                if ((sc->handle[i+0].flags & PCIC_FLAG_SOCKETP) ||
        !           317:                    (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP)) {
        !           318:                        vendor = pcic_vendor(&sc->handle[i]);
        !           319:
        !           320:                        printf("%s controller %d: <%s> has socket",
        !           321:                            sc->dev.dv_xname, i/2,
        !           322:                            pcic_vendor_to_string[vendor]);
        !           323:
        !           324:                        if ((sc->handle[i+0].flags & PCIC_FLAG_SOCKETP) &&
        !           325:                            (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP))
        !           326:                                printf("s A and B\n");
        !           327:                        else if (sc->handle[i+0].flags & PCIC_FLAG_SOCKETP)
        !           328:                                printf(" A only\n");
        !           329:                        else
        !           330:                                printf(" B only\n");
        !           331:
        !           332:                        if (sc->handle[i+0].flags & PCIC_FLAG_SOCKETP)
        !           333:                                sc->handle[i+0].vendor = vendor;
        !           334:                        if (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP)
        !           335:                                sc->handle[i+1].vendor = vendor;
        !           336:                }
        !           337:        }
        !           338: }
        !           339:
        !           340: void
        !           341: pcic_attach_sockets(sc)
        !           342:        struct pcic_softc *sc;
        !           343: {
        !           344:        int i;
        !           345:
        !           346:        for (i = 0; i < PCIC_NSLOTS; i++)
        !           347:                if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
        !           348:                        pcic_attach_socket(&sc->handle[i]);
        !           349: }
        !           350:
        !           351: void
        !           352: pcic_attach_socket(h)
        !           353:        struct pcic_handle *h;
        !           354: {
        !           355:        struct pcmciabus_attach_args paa;
        !           356:        struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
        !           357:
        !           358:        /* initialize the rest of the handle */
        !           359:
        !           360:        h->shutdown = 0;
        !           361:        h->memalloc = 0;
        !           362:        h->ioalloc = 0;
        !           363:        h->ih_irq = 0;
        !           364:
        !           365:        /* now, config one pcmcia device per socket */
        !           366:
        !           367:        paa.paa_busname = "pcmcia";
        !           368:        paa.pct = (pcmcia_chipset_tag_t) sc->pct;
        !           369:        paa.pch = (pcmcia_chipset_handle_t) h;
        !           370:        paa.iobase = sc->iobase;
        !           371:        paa.iosize = sc->iosize;
        !           372:
        !           373:        h->pcmcia = config_found_sm(&sc->dev, &paa, pcic_print,
        !           374:            pcic_submatch);
        !           375:
        !           376:        /* if there's actually a pcmcia device attached, initialize the slot */
        !           377:
        !           378:        if (h->pcmcia)
        !           379:                pcic_init_socket(h);
        !           380:        else
        !           381:                h->flags &= ~PCIC_FLAG_SOCKETP;
        !           382: }
        !           383:
        !           384: void
        !           385: pcic_create_event_thread(arg)
        !           386:        void *arg;
        !           387: {
        !           388:        struct pcic_handle *h = arg;
        !           389:        const char *cs;
        !           390:
        !           391:        switch (h->sock) {
        !           392:        case C0SA:
        !           393:                cs = "0,0";
        !           394:                break;
        !           395:        case C0SB:
        !           396:                cs = "0,1";
        !           397:                break;
        !           398:        case C1SA:
        !           399:                cs = "1,0";
        !           400:                break;
        !           401:        case C1SB:
        !           402:                cs = "1,1";
        !           403:                break;
        !           404:        default:
        !           405:                panic("pcic_create_event_thread: unknown pcic socket");
        !           406:        }
        !           407:
        !           408:        if (kthread_create(pcic_event_thread, h, &h->event_thread,
        !           409:            "%s,%s", h->ph_parent->dv_xname, cs)) {
        !           410:                printf("%s: unable to create event thread for sock 0x%02x\n",
        !           411:                    h->ph_parent->dv_xname, h->sock);
        !           412:                panic("pcic_create_event_thread");
        !           413:        }
        !           414: }
        !           415:
        !           416: void
        !           417: pcic_event_thread(arg)
        !           418:        void *arg;
        !           419: {
        !           420:        struct pcic_handle *h = arg;
        !           421:        struct pcic_event *pe;
        !           422:        int s;
        !           423:        struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
        !           424:
        !           425:        while (h->shutdown == 0) {
        !           426:                s = splhigh();
        !           427:                if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
        !           428:                        splx(s);
        !           429:                        (void) tsleep(&h->events, PWAIT, "pcicev", 0);
        !           430:                        continue;
        !           431:                } else {
        !           432:                        splx(s);
        !           433:                        /* sleep .25s to be enqueued chatterling interrupts */
        !           434:                        (void) tsleep((caddr_t)pcic_event_thread, PWAIT,
        !           435:                            "pcicss", hz/4);
        !           436:                }
        !           437:                pcic_event_process(h, pe);
        !           438:        }
        !           439:
        !           440:        h->event_thread = NULL;
        !           441:
        !           442:        /* In case parent is waiting for us to exit. */
        !           443:        wakeup(sc);
        !           444:
        !           445:        kthread_exit(0);
        !           446: }
        !           447:
        !           448: void
        !           449: pcic_event_process(h, pe)
        !           450:        struct pcic_handle *h;
        !           451:        struct pcic_event *pe;
        !           452: {
        !           453:        int s;
        !           454:
        !           455:        s = splhigh();
        !           456:        SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
        !           457:        splx(s);
        !           458:
        !           459:        switch (pe->pe_type) {
        !           460:        case PCIC_EVENT_INSERTION:
        !           461:                s = splhigh();
        !           462:                while (1) {
        !           463:                        struct pcic_event *pe1, *pe2;
        !           464:
        !           465:                        if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
        !           466:                                break;
        !           467:                        if (pe1->pe_type != PCIC_EVENT_REMOVAL)
        !           468:                                break;
        !           469:                        if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
        !           470:                                break;
        !           471:                        if (pe2->pe_type == PCIC_EVENT_INSERTION) {
        !           472:                                SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
        !           473:                                free(pe1, M_TEMP);
        !           474:                                SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
        !           475:                                free(pe2, M_TEMP);
        !           476:                        }
        !           477:                }
        !           478:                splx(s);
        !           479:
        !           480:                DPRINTF(("%s: insertion event\n", h->ph_parent->dv_xname));
        !           481:                pcic_attach_card(h);
        !           482:                break;
        !           483:
        !           484:        case PCIC_EVENT_REMOVAL:
        !           485:                s = splhigh();
        !           486:                while (1) {
        !           487:                        struct pcic_event *pe1, *pe2;
        !           488:
        !           489:                        if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
        !           490:                                break;
        !           491:                        if (pe1->pe_type != PCIC_EVENT_INSERTION)
        !           492:                                break;
        !           493:                        if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
        !           494:                                break;
        !           495:                        if (pe2->pe_type == PCIC_EVENT_REMOVAL) {
        !           496:                                SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
        !           497:                                free(pe1, M_TEMP);
        !           498:                                SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
        !           499:                                free(pe2, M_TEMP);
        !           500:                        }
        !           501:                }
        !           502:                splx(s);
        !           503:
        !           504:                DPRINTF(("%s: removal event\n", h->ph_parent->dv_xname));
        !           505:                pcic_detach_card(h, DETACH_FORCE);
        !           506:                break;
        !           507:
        !           508:        default:
        !           509:                panic("pcic_event_thread: unknown event %d", pe->pe_type);
        !           510:        }
        !           511:        free(pe, M_TEMP);
        !           512: }
        !           513:
        !           514: void
        !           515: pcic_init_socket(h)
        !           516:        struct pcic_handle *h;
        !           517: {
        !           518:        int reg;
        !           519:        struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
        !           520:
        !           521:        /*
        !           522:         * queue creation of a kernel thread to handle insert/removal events.
        !           523:         */
        !           524: #ifdef DIAGNOSTIC
        !           525:        if (h->event_thread != NULL)
        !           526:                panic("pcic_attach_socket: event thread");
        !           527: #endif
        !           528:        kthread_create_deferred(pcic_create_event_thread, h);
        !           529:
        !           530:        /* set up the card to interrupt on card detect */
        !           531:
        !           532:        pcic_write(h, PCIC_CSC_INTR, (sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) |
        !           533:            PCIC_CSC_INTR_CD_ENABLE);
        !           534:        pcic_write(h, PCIC_INTR, 0);
        !           535:        pcic_read(h, PCIC_CSC);
        !           536:
        !           537:        /* unsleep the cirrus controller */
        !           538:
        !           539:        if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) ||
        !           540:            (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) {
        !           541:                reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
        !           542:                if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) {
        !           543:                        DPRINTF(("%s: socket %02x was suspended\n",
        !           544:                            h->ph_parent->dv_xname, h->sock));
        !           545:                        reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND;
        !           546:                        pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg);
        !           547:                }
        !           548:        }
        !           549:        /* if there's a card there, then attach it. */
        !           550:
        !           551:        reg = pcic_read(h, PCIC_IF_STATUS);
        !           552:
        !           553:        if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
        !           554:            PCIC_IF_STATUS_CARDDETECT_PRESENT) {
        !           555:                pcic_attach_card(h);
        !           556:                h->laststate = PCIC_LASTSTATE_PRESENT;
        !           557:        } else
        !           558:                h->laststate = PCIC_LASTSTATE_EMPTY;
        !           559: }
        !           560:
        !           561: int
        !           562: pcic_submatch(parent, match, aux)
        !           563:        struct device *parent;
        !           564:        void *match, *aux;
        !           565: {
        !           566:        struct cfdata *cf = match;
        !           567:        struct pcmciabus_attach_args *paa = aux;
        !           568:        struct pcic_handle *h = (struct pcic_handle *) paa->pch;
        !           569:
        !           570:        switch (h->sock) {
        !           571:        case C0SA:
        !           572:                if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
        !           573:                    -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
        !           574:                    cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0)
        !           575:                        return 0;
        !           576:                if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
        !           577:                    -1 /* PCICCF_SOCKET_DEFAULT */ &&
        !           578:                    cf->cf_loc[1 /* PCICCF_SOCKET */] != 0)
        !           579:                        return 0;
        !           580:
        !           581:                break;
        !           582:        case C0SB:
        !           583:                if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
        !           584:                    -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
        !           585:                    cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0)
        !           586:                        return 0;
        !           587:                if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
        !           588:                    -1 /* PCICCF_SOCKET_DEFAULT */ &&
        !           589:                    cf->cf_loc[1 /* PCICCF_SOCKET */] != 1)
        !           590:                        return 0;
        !           591:
        !           592:                break;
        !           593:        case C1SA:
        !           594:                if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
        !           595:                    -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
        !           596:                    cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1)
        !           597:                        return 0;
        !           598:                if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
        !           599:                    -1 /* PCICCF_SOCKET_DEFAULT */ &&
        !           600:                    cf->cf_loc[1 /* PCICCF_SOCKET */] != 0)
        !           601:                        return 0;
        !           602:
        !           603:                break;
        !           604:        case C1SB:
        !           605:                if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
        !           606:                    -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
        !           607:                    cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1)
        !           608:                        return 0;
        !           609:                if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
        !           610:                    -1 /* PCICCF_SOCKET_DEFAULT */ &&
        !           611:                    cf->cf_loc[1 /* PCICCF_SOCKET */] != 1)
        !           612:                        return 0;
        !           613:
        !           614:                break;
        !           615:        default:
        !           616:                panic("unknown pcic socket");
        !           617:        }
        !           618:
        !           619:        return ((*cf->cf_attach->ca_match)(parent, cf, aux));
        !           620: }
        !           621:
        !           622: int
        !           623: pcic_print(arg, pnp)
        !           624:        void *arg;
        !           625:        const char *pnp;
        !           626: {
        !           627:        struct pcmciabus_attach_args *paa = arg;
        !           628:        struct pcic_handle *h = (struct pcic_handle *) paa->pch;
        !           629:
        !           630:        /* Only "pcmcia"s can attach to "pcic"s... easy. */
        !           631:        if (pnp)
        !           632:                printf("pcmcia at %s", pnp);
        !           633:
        !           634:        switch (h->sock) {
        !           635:        case C0SA:
        !           636:                printf(" controller 0 socket 0");
        !           637:                break;
        !           638:        case C0SB:
        !           639:                printf(" controller 0 socket 1");
        !           640:                break;
        !           641:        case C1SA:
        !           642:                printf(" controller 1 socket 0");
        !           643:                break;
        !           644:        case C1SB:
        !           645:                printf(" controller 1 socket 1");
        !           646:                break;
        !           647:        default:
        !           648:                panic("unknown pcic socket");
        !           649:        }
        !           650:
        !           651:        return (UNCONF);
        !           652: }
        !           653:
        !           654: int
        !           655: pcic_intr(arg)
        !           656:        void *arg;
        !           657: {
        !           658:        struct pcic_softc *sc = arg;
        !           659:        int i, ret = 0;
        !           660:
        !           661:        DPRINTF(("%s: intr\n", sc->dev.dv_xname));
        !           662:
        !           663:        for (i = 0; i < PCIC_NSLOTS; i++)
        !           664:                if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
        !           665:                        ret += pcic_intr_socket(&sc->handle[i]);
        !           666:
        !           667:        return (ret ? 1 : 0);
        !           668: }
        !           669:
        !           670: void
        !           671: pcic_poll_intr(arg)
        !           672:        void *arg;
        !           673: {
        !           674:        struct pcic_softc *sc = arg;
        !           675:        int i, s;
        !           676:
        !           677:        /*
        !           678:         * Since we're polling, we aren't in interrupt context, so block any
        !           679:         * actual interrupts coming from the pcic.
        !           680:         */
        !           681:        s = spltty();
        !           682:
        !           683:        for (i = 0; i < PCIC_NSLOTS; i++)
        !           684:                if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
        !           685:                        pcic_intr_socket(&sc->handle[i]);
        !           686:
        !           687:        timeout_add(&sc->poll_timeout, hz / 2);
        !           688:
        !           689:        splx(s);
        !           690: }
        !           691:
        !           692: int
        !           693: pcic_intr_socket(h)
        !           694:        struct pcic_handle *h;
        !           695: {
        !           696:        int cscreg;
        !           697:
        !           698:        cscreg = pcic_read(h, PCIC_CSC);
        !           699:
        !           700:        cscreg &= (PCIC_CSC_GPI |
        !           701:                   PCIC_CSC_CD |
        !           702:                   PCIC_CSC_READY |
        !           703:                   PCIC_CSC_BATTWARN |
        !           704:                   PCIC_CSC_BATTDEAD);
        !           705:
        !           706:        if (cscreg & PCIC_CSC_GPI) {
        !           707:                DPRINTF(("%s: %02x GPI\n", h->ph_parent->dv_xname, h->sock));
        !           708:        }
        !           709:        if (cscreg & PCIC_CSC_CD) {
        !           710:                int statreg;
        !           711:
        !           712:                statreg = pcic_read(h, PCIC_IF_STATUS);
        !           713:
        !           714:                DPRINTF(("%s: %02x CD %x\n", h->ph_parent->dv_xname, h->sock,
        !           715:                    statreg));
        !           716:
        !           717:                if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
        !           718:                    PCIC_IF_STATUS_CARDDETECT_PRESENT) {
        !           719:                        if (h->laststate != PCIC_LASTSTATE_PRESENT) {
        !           720:                                DPRINTF(("%s: enqueing INSERTION event\n",
        !           721:                                    h->ph_parent->dv_xname));
        !           722:                                pcic_queue_event(h, PCIC_EVENT_INSERTION);
        !           723:                        }
        !           724:                        h->laststate = PCIC_LASTSTATE_PRESENT;
        !           725:                } else {
        !           726:                        if (h->laststate == PCIC_LASTSTATE_PRESENT) {
        !           727:                                /* Deactivate the card now. */
        !           728:                                DPRINTF(("%s: deactivating card\n",
        !           729:                                    h->ph_parent->dv_xname));
        !           730:                                pcic_deactivate_card(h);
        !           731:
        !           732:                                DPRINTF(("%s: enqueing REMOVAL event\n",
        !           733:                                    h->ph_parent->dv_xname));
        !           734:                                pcic_queue_event(h, PCIC_EVENT_REMOVAL);
        !           735:                        }
        !           736:                        h->laststate =
        !           737:                            ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == 0)
        !           738:                            ? PCIC_LASTSTATE_EMPTY : PCIC_LASTSTATE_HALF;
        !           739:                }
        !           740:        }
        !           741:        if (cscreg & PCIC_CSC_READY) {
        !           742:                DPRINTF(("%s: %02x READY\n", h->ph_parent->dv_xname, h->sock));
        !           743:                /* shouldn't happen */
        !           744:        }
        !           745:        if (cscreg & PCIC_CSC_BATTWARN) {
        !           746:                DPRINTF(("%s: %02x BATTWARN\n", h->ph_parent->dv_xname,
        !           747:                    h->sock));
        !           748:        }
        !           749:        if (cscreg & PCIC_CSC_BATTDEAD) {
        !           750:                DPRINTF(("%s: %02x BATTDEAD\n", h->ph_parent->dv_xname,
        !           751:                    h->sock));
        !           752:        }
        !           753:        return (cscreg ? 1 : 0);
        !           754: }
        !           755:
        !           756: void
        !           757: pcic_queue_event(h, event)
        !           758:        struct pcic_handle *h;
        !           759:        int event;
        !           760: {
        !           761:        struct pcic_event *pe;
        !           762:        int s;
        !           763:
        !           764:        pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
        !           765:        if (pe == NULL)
        !           766:                panic("pcic_queue_event: can't allocate event");
        !           767:
        !           768:        pe->pe_type = event;
        !           769:        s = splhigh();
        !           770:        SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
        !           771:        splx(s);
        !           772:        wakeup(&h->events);
        !           773: }
        !           774:
        !           775: void
        !           776: pcic_attach_card(h)
        !           777:        struct pcic_handle *h;
        !           778: {
        !           779:        if (h->flags & PCIC_FLAG_CARDP)
        !           780:                panic("pcic_attach_card: already attached");
        !           781:
        !           782:        /* call the MI attach function */
        !           783:        pcmcia_card_attach(h->pcmcia);
        !           784:
        !           785:        h->flags |= PCIC_FLAG_CARDP;
        !           786: }
        !           787:
        !           788: void
        !           789: pcic_detach_card(h, flags)
        !           790:        struct pcic_handle *h;
        !           791:        int flags;              /* DETACH_* */
        !           792: {
        !           793:
        !           794:        if (h->flags & PCIC_FLAG_CARDP) {
        !           795:                h->flags &= ~PCIC_FLAG_CARDP;
        !           796:
        !           797:                /* call the MI detach function */
        !           798:                pcmcia_card_detach(h->pcmcia, flags);
        !           799:        } else {
        !           800:                DPRINTF(("pcic_detach_card: already detached"));
        !           801:        }
        !           802: }
        !           803:
        !           804: void
        !           805: pcic_deactivate_card(h)
        !           806:        struct pcic_handle *h;
        !           807: {
        !           808:        struct device *dev = (struct device *)h->pcmcia;
        !           809:
        !           810:        /*
        !           811:         * At suspend, apm deactivates any connected cards. If we've woken up
        !           812:         * to find a previously-connected device missing, and we're detaching
        !           813:         * it, we don't want to deactivate it again.
        !           814:         */
        !           815:        if (dev->dv_flags & DVF_ACTIVE)
        !           816:                pcmcia_card_deactivate(h->pcmcia);
        !           817:
        !           818:        /* power down the socket */
        !           819:        pcic_write(h, PCIC_PWRCTL, 0);
        !           820:
        !           821:        /* reset the socket */
        !           822:        pcic_write(h, PCIC_INTR, 0);
        !           823: }
        !           824:
        !           825: /*
        !           826:  * The pcic_power() function must execute BEFORE the pcmcia_power() hooks.
        !           827:  * During suspend, a card may have been ejected. If so, we must detach it
        !           828:  * completely before pcmcia_power() tries to activate it. Attempting to
        !           829:  * activate a card that isn't there is bad news.
        !           830:  */
        !           831: void
        !           832: pcic_power(why, arg)
        !           833:        int why;
        !           834:        void *arg;
        !           835: {
        !           836:        struct pcic_handle *h = (struct pcic_handle *)arg;
        !           837:        struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent;
        !           838:        struct pcic_event *pe;
        !           839:
        !           840:        if (why != PWR_RESUME) {
        !           841:                if (timeout_pending(&sc->poll_timeout))
        !           842:                        timeout_del(&sc->poll_timeout);
        !           843:        }
        !           844:        else {
        !           845:                pcic_intr_socket(h);
        !           846:
        !           847:                while ((pe = SIMPLEQ_FIRST(&h->events)))
        !           848:                        pcic_event_process(h, pe);
        !           849:
        !           850:                timeout_add(&sc->poll_timeout, hz / 2);
        !           851:        }
        !           852: }
        !           853:
        !           854: int
        !           855: pcic_chip_mem_alloc(pch, size, pcmhp)
        !           856:        pcmcia_chipset_handle_t pch;
        !           857:        bus_size_t size;
        !           858:        struct pcmcia_mem_handle *pcmhp;
        !           859: {
        !           860:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !           861:        bus_space_handle_t memh;
        !           862:        bus_addr_t addr;
        !           863:        bus_size_t sizepg;
        !           864:        int i, mask, mhandle;
        !           865:        struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
        !           866:
        !           867:        /* out of sc->memh, allocate as many pages as necessary */
        !           868:
        !           869:        /* convert size to PCIC pages */
        !           870:        sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN;
        !           871:        if (sizepg > PCIC_MAX_MEM_PAGES)
        !           872:                return (1);
        !           873:
        !           874:        mask = (1 << sizepg) - 1;
        !           875:
        !           876:        addr = 0;               /* XXX gcc -Wuninitialized */
        !           877:        mhandle = 0;            /* XXX gcc -Wuninitialized */
        !           878:
        !           879:        for (i = 0; i <= PCIC_MAX_MEM_PAGES - sizepg; i++) {
        !           880:                if ((sc->subregionmask & (mask << i)) == (mask << i)) {
        !           881:                        if (bus_space_subregion(sc->memt, sc->memh,
        !           882:                            i * PCIC_MEM_PAGESIZE,
        !           883:                            sizepg * PCIC_MEM_PAGESIZE, &memh))
        !           884:                                return (1);
        !           885:                        mhandle = mask << i;
        !           886:                        addr = sc->membase + (i * PCIC_MEM_PAGESIZE);
        !           887:                        sc->subregionmask &= ~(mhandle);
        !           888:                        pcmhp->memt = sc->memt;
        !           889:                        pcmhp->memh = memh;
        !           890:                        pcmhp->addr = addr;
        !           891:                        pcmhp->size = size;
        !           892:                        pcmhp->mhandle = mhandle;
        !           893:                        pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
        !           894:
        !           895:                        DPRINTF(("pcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n",
        !           896:                            (u_long) addr, (u_long) size));
        !           897:
        !           898:                        return (0);
        !           899:                }
        !           900:        }
        !           901:
        !           902:        return (1);
        !           903: }
        !           904:
        !           905: void
        !           906: pcic_chip_mem_free(pch, pcmhp)
        !           907:        pcmcia_chipset_handle_t pch;
        !           908:        struct pcmcia_mem_handle *pcmhp;
        !           909: {
        !           910:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !           911:        struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
        !           912:
        !           913:        sc->subregionmask |= pcmhp->mhandle;
        !           914: }
        !           915:
        !           916: static struct mem_map_index_st {
        !           917:        int     sysmem_start_lsb;
        !           918:        int     sysmem_start_msb;
        !           919:        int     sysmem_stop_lsb;
        !           920:        int     sysmem_stop_msb;
        !           921:        int     cardmem_lsb;
        !           922:        int     cardmem_msb;
        !           923:        int     memenable;
        !           924: } mem_map_index[] = {
        !           925:        {
        !           926:                PCIC_SYSMEM_ADDR0_START_LSB,
        !           927:                PCIC_SYSMEM_ADDR0_START_MSB,
        !           928:                PCIC_SYSMEM_ADDR0_STOP_LSB,
        !           929:                PCIC_SYSMEM_ADDR0_STOP_MSB,
        !           930:                PCIC_CARDMEM_ADDR0_LSB,
        !           931:                PCIC_CARDMEM_ADDR0_MSB,
        !           932:                PCIC_ADDRWIN_ENABLE_MEM0,
        !           933:        },
        !           934:        {
        !           935:                PCIC_SYSMEM_ADDR1_START_LSB,
        !           936:                PCIC_SYSMEM_ADDR1_START_MSB,
        !           937:                PCIC_SYSMEM_ADDR1_STOP_LSB,
        !           938:                PCIC_SYSMEM_ADDR1_STOP_MSB,
        !           939:                PCIC_CARDMEM_ADDR1_LSB,
        !           940:                PCIC_CARDMEM_ADDR1_MSB,
        !           941:                PCIC_ADDRWIN_ENABLE_MEM1,
        !           942:        },
        !           943:        {
        !           944:                PCIC_SYSMEM_ADDR2_START_LSB,
        !           945:                PCIC_SYSMEM_ADDR2_START_MSB,
        !           946:                PCIC_SYSMEM_ADDR2_STOP_LSB,
        !           947:                PCIC_SYSMEM_ADDR2_STOP_MSB,
        !           948:                PCIC_CARDMEM_ADDR2_LSB,
        !           949:                PCIC_CARDMEM_ADDR2_MSB,
        !           950:                PCIC_ADDRWIN_ENABLE_MEM2,
        !           951:        },
        !           952:        {
        !           953:                PCIC_SYSMEM_ADDR3_START_LSB,
        !           954:                PCIC_SYSMEM_ADDR3_START_MSB,
        !           955:                PCIC_SYSMEM_ADDR3_STOP_LSB,
        !           956:                PCIC_SYSMEM_ADDR3_STOP_MSB,
        !           957:                PCIC_CARDMEM_ADDR3_LSB,
        !           958:                PCIC_CARDMEM_ADDR3_MSB,
        !           959:                PCIC_ADDRWIN_ENABLE_MEM3,
        !           960:        },
        !           961:        {
        !           962:                PCIC_SYSMEM_ADDR4_START_LSB,
        !           963:                PCIC_SYSMEM_ADDR4_START_MSB,
        !           964:                PCIC_SYSMEM_ADDR4_STOP_LSB,
        !           965:                PCIC_SYSMEM_ADDR4_STOP_MSB,
        !           966:                PCIC_CARDMEM_ADDR4_LSB,
        !           967:                PCIC_CARDMEM_ADDR4_MSB,
        !           968:                PCIC_ADDRWIN_ENABLE_MEM4,
        !           969:        },
        !           970: };
        !           971:
        !           972: void
        !           973: pcic_chip_do_mem_map(h, win)
        !           974:        struct pcic_handle *h;
        !           975:        int win;
        !           976: {
        !           977:        int reg;
        !           978:        int kind = h->mem[win].kind & ~PCMCIA_WIDTH_MEM_MASK;
        !           979:        int mem8 =
        !           980:            (h->mem[win].kind & PCMCIA_WIDTH_MEM_MASK) == PCMCIA_WIDTH_MEM8
        !           981:            || (kind == PCMCIA_MEM_ATTR);
        !           982:
        !           983:        pcic_write(h, mem_map_index[win].sysmem_start_lsb,
        !           984:            (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
        !           985:        pcic_write(h, mem_map_index[win].sysmem_start_msb,
        !           986:            ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
        !           987:            PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK) |
        !           988:            (mem8 ? 0 : PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT));
        !           989:
        !           990:        pcic_write(h, mem_map_index[win].sysmem_stop_lsb,
        !           991:            ((h->mem[win].addr + h->mem[win].size) >>
        !           992:            PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
        !           993:        pcic_write(h, mem_map_index[win].sysmem_stop_msb,
        !           994:            (((h->mem[win].addr + h->mem[win].size) >>
        !           995:            (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
        !           996:            PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
        !           997:            PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2);
        !           998:
        !           999:        pcic_write(h, mem_map_index[win].cardmem_lsb,
        !          1000:            (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff);
        !          1001:        pcic_write(h, mem_map_index[win].cardmem_msb,
        !          1002:            ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) &
        !          1003:            PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) |
        !          1004:            ((kind == PCMCIA_MEM_ATTR) ?
        !          1005:            PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0));
        !          1006:
        !          1007:        reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
        !          1008:        reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16);
        !          1009:        pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
        !          1010:
        !          1011: #ifdef PCICDEBUG
        !          1012:        {
        !          1013:                int r1, r2, r3, r4, r5, r6;
        !          1014:
        !          1015:                r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb);
        !          1016:                r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb);
        !          1017:                r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb);
        !          1018:                r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb);
        !          1019:                r5 = pcic_read(h, mem_map_index[win].cardmem_msb);
        !          1020:                r6 = pcic_read(h, mem_map_index[win].cardmem_lsb);
        !          1021:
        !          1022:                DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x "
        !          1023:                    "%02x%02x\n", win, r1, r2, r3, r4, r5, r6));
        !          1024:        }
        !          1025: #endif
        !          1026: }
        !          1027:
        !          1028: int
        !          1029: pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
        !          1030:        pcmcia_chipset_handle_t pch;
        !          1031:        int kind;
        !          1032:        bus_addr_t card_addr;
        !          1033:        bus_size_t size;
        !          1034:        struct pcmcia_mem_handle *pcmhp;
        !          1035:        bus_size_t *offsetp;
        !          1036:        int *windowp;
        !          1037: {
        !          1038:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !          1039:        bus_addr_t busaddr;
        !          1040:        long card_offset;
        !          1041:        int i, win;
        !          1042:        struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
        !          1043:
        !          1044:        win = -1;
        !          1045:        for (i = 0; i < (sizeof(mem_map_index) / sizeof(mem_map_index[0]));
        !          1046:            i++) {
        !          1047:                if ((h->memalloc & (1 << i)) == 0) {
        !          1048:                        win = i;
        !          1049:                        h->memalloc |= (1 << i);
        !          1050:                        break;
        !          1051:                }
        !          1052:        }
        !          1053:
        !          1054:        if (win == -1)
        !          1055:                return (1);
        !          1056:
        !          1057:        *windowp = win;
        !          1058:
        !          1059:        /* XXX this is pretty gross */
        !          1060:
        !          1061:        if (sc->memt != pcmhp->memt)
        !          1062:                panic("pcic_chip_mem_map memt is bogus");
        !          1063:
        !          1064:        busaddr = pcmhp->addr;
        !          1065:
        !          1066:        /*
        !          1067:         * Compute the address offset to the pcmcia address space for the
        !          1068:         * pcic.  This is intentionally signed.  The masks and shifts below
        !          1069:         * will cause TRT to happen in the pcic registers.  Deal with making
        !          1070:         * sure the address is aligned, and return the alignment offset.
        !          1071:         */
        !          1072:
        !          1073:        *offsetp = card_addr % PCIC_MEM_ALIGN;
        !          1074:        card_addr -= *offsetp;
        !          1075:
        !          1076:        DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
        !          1077:            "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
        !          1078:            (u_long) card_addr));
        !          1079:
        !          1080:        /*
        !          1081:         * include the offset in the size, and decrement size by one, since
        !          1082:         * the hw wants start/stop
        !          1083:         */
        !          1084:        size += *offsetp - 1;
        !          1085:
        !          1086:        card_offset = (((long) card_addr) - ((long) busaddr));
        !          1087:
        !          1088:        h->mem[win].addr = busaddr;
        !          1089:        h->mem[win].size = size;
        !          1090:        h->mem[win].offset = card_offset;
        !          1091:        h->mem[win].kind = kind;
        !          1092:
        !          1093:        pcic_chip_do_mem_map(h, win);
        !          1094:
        !          1095:        return (0);
        !          1096: }
        !          1097:
        !          1098: void
        !          1099: pcic_chip_mem_unmap(pch, window)
        !          1100:        pcmcia_chipset_handle_t pch;
        !          1101:        int window;
        !          1102: {
        !          1103:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !          1104:        int reg;
        !          1105:
        !          1106:        if (window >= (sizeof(mem_map_index) / sizeof(mem_map_index[0])))
        !          1107:                panic("pcic_chip_mem_unmap: window out of range");
        !          1108:
        !          1109:        reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
        !          1110:        reg &= ~mem_map_index[window].memenable;
        !          1111:        pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
        !          1112:
        !          1113:        h->memalloc &= ~(1 << window);
        !          1114: }
        !          1115:
        !          1116: int
        !          1117: pcic_chip_io_alloc(pch, start, size, align, pcihp)
        !          1118:        pcmcia_chipset_handle_t pch;
        !          1119:        bus_addr_t start;
        !          1120:        bus_size_t size;
        !          1121:        bus_size_t align;
        !          1122:        struct pcmcia_io_handle *pcihp;
        !          1123: {
        !          1124:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !          1125:        bus_space_tag_t iot;
        !          1126:        bus_space_handle_t ioh;
        !          1127:        bus_addr_t ioaddr, beg, fin;
        !          1128:        int flags = 0;
        !          1129:        struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
        !          1130:        struct pcic_ranges *range;
        !          1131:
        !          1132:        /*
        !          1133:         * Allocate some arbitrary I/O space.
        !          1134:         */
        !          1135:
        !          1136:        iot = sc->iot;
        !          1137:
        !          1138:        if (start) {
        !          1139:                ioaddr = start;
        !          1140:                if (bus_space_map(iot, start, size, 0, &ioh))
        !          1141:                        return (1);
        !          1142:                DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n",
        !          1143:                    (u_long)ioaddr, (u_long)size));
        !          1144:        } else if (sc->ranges) {
        !          1145:                flags |= PCMCIA_IO_ALLOCATED;
        !          1146:
        !          1147:                /*
        !          1148:                 * In this case, we know the "size" and "align" that
        !          1149:                 * we want.  So we need to start walking down
        !          1150:                 * sc->ranges, searching for a similar space that
        !          1151:                 * is (1) large enough for the size and alignment
        !          1152:                 * (2) then we need to try to allocate
        !          1153:                 * (3) if it fails to allocate, we try next range.
        !          1154:                 *
        !          1155:                 * We must also check that the start/size of each
        !          1156:                 * allocation we are about to do is within the bounds
        !          1157:                 * of "sc->iobase" and "sc->iosize".
        !          1158:                 * (Some pcmcia controllers handle a 12 bits of addressing,
        !          1159:                 * but we want to use the same range structure)
        !          1160:                 */
        !          1161:                for (range = sc->ranges; range->start; range++) {
        !          1162:                        /* Potentially trim the range because of bounds. */
        !          1163:                        beg = max(range->start, sc->iobase);
        !          1164:                        fin = min(range->start + range->len,
        !          1165:                            sc->iobase + sc->iosize);
        !          1166:
        !          1167:                        /* Short-circuit easy cases. */
        !          1168:                        if (fin < beg || fin - beg < size)
        !          1169:                                continue;
        !          1170:
        !          1171:                        /*
        !          1172:                         * This call magically fulfills our alignment
        !          1173:                         * requirements.
        !          1174:                         */
        !          1175:                        DPRINTF(("pcic_chip_io_alloc beg-fin %lx-%lx\n",
        !          1176:                            (u_long)beg, (u_long)fin));
        !          1177:                        if (bus_space_alloc(iot, beg, fin, size, align, 0, 0,
        !          1178:                            &ioaddr, &ioh) == 0)
        !          1179:                                break;
        !          1180:                }
        !          1181:                if (range->start == 0)
        !          1182:                        return (1);
        !          1183:                DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
        !          1184:                    (u_long)ioaddr, (u_long)size));
        !          1185:
        !          1186:        } else {
        !          1187:                flags |= PCMCIA_IO_ALLOCATED;
        !          1188:                if (bus_space_alloc(iot, sc->iobase,
        !          1189:                    sc->iobase + sc->iosize, size, align, 0, 0,
        !          1190:                    &ioaddr, &ioh))
        !          1191:                        return (1);
        !          1192:                DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
        !          1193:                    (u_long)ioaddr, (u_long)size));
        !          1194:        }
        !          1195:
        !          1196:        pcihp->iot = iot;
        !          1197:        pcihp->ioh = ioh;
        !          1198:        pcihp->addr = ioaddr;
        !          1199:        pcihp->size = size;
        !          1200:        pcihp->flags = flags;
        !          1201:
        !          1202:        return (0);
        !          1203: }
        !          1204:
        !          1205: void
        !          1206: pcic_chip_io_free(pch, pcihp)
        !          1207:        pcmcia_chipset_handle_t pch;
        !          1208:        struct pcmcia_io_handle *pcihp;
        !          1209: {
        !          1210:        bus_space_tag_t iot = pcihp->iot;
        !          1211:        bus_space_handle_t ioh = pcihp->ioh;
        !          1212:        bus_size_t size = pcihp->size;
        !          1213:
        !          1214:        if (pcihp->flags & PCMCIA_IO_ALLOCATED)
        !          1215:                bus_space_free(iot, ioh, size);
        !          1216:        else
        !          1217:                bus_space_unmap(iot, ioh, size);
        !          1218: }
        !          1219:
        !          1220:
        !          1221: static struct io_map_index_st {
        !          1222:        int     start_lsb;
        !          1223:        int     start_msb;
        !          1224:        int     stop_lsb;
        !          1225:        int     stop_msb;
        !          1226:        int     ioenable;
        !          1227:        int     ioctlmask;
        !          1228:        int     ioctlbits[3];           /* indexed by PCMCIA_WIDTH_* */
        !          1229: }               io_map_index[] = {
        !          1230:        {
        !          1231:                PCIC_IOADDR0_START_LSB,
        !          1232:                PCIC_IOADDR0_START_MSB,
        !          1233:                PCIC_IOADDR0_STOP_LSB,
        !          1234:                PCIC_IOADDR0_STOP_MSB,
        !          1235:                PCIC_ADDRWIN_ENABLE_IO0,
        !          1236:                PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT |
        !          1237:                PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK,
        !          1238:                {
        !          1239:                        PCIC_IOCTL_IO0_IOCS16SRC_CARD,
        !          1240:                        PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
        !          1241:                            PCIC_IOCTL_IO0_DATASIZE_8BIT,
        !          1242:                        PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
        !          1243:                            PCIC_IOCTL_IO0_DATASIZE_16BIT,
        !          1244:                },
        !          1245:        },
        !          1246:        {
        !          1247:                PCIC_IOADDR1_START_LSB,
        !          1248:                PCIC_IOADDR1_START_MSB,
        !          1249:                PCIC_IOADDR1_STOP_LSB,
        !          1250:                PCIC_IOADDR1_STOP_MSB,
        !          1251:                PCIC_ADDRWIN_ENABLE_IO1,
        !          1252:                PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT |
        !          1253:                PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK,
        !          1254:                {
        !          1255:                        PCIC_IOCTL_IO1_IOCS16SRC_CARD,
        !          1256:                        PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE |
        !          1257:                            PCIC_IOCTL_IO1_DATASIZE_8BIT,
        !          1258:                        PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE |
        !          1259:                            PCIC_IOCTL_IO1_DATASIZE_16BIT,
        !          1260:                },
        !          1261:        },
        !          1262: };
        !          1263:
        !          1264: void
        !          1265: pcic_chip_do_io_map(h, win)
        !          1266:        struct pcic_handle *h;
        !          1267:        int win;
        !          1268: {
        !          1269:        int reg;
        !          1270:
        !          1271:        DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n",
        !          1272:            win, (long) h->io[win].addr, (long) h->io[win].size,
        !          1273:            h->io[win].width * 8));
        !          1274:
        !          1275:        pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff);
        !          1276:        pcic_write(h, io_map_index[win].start_msb,
        !          1277:            (h->io[win].addr >> 8) & 0xff);
        !          1278:
        !          1279:        pcic_write(h, io_map_index[win].stop_lsb,
        !          1280:            (h->io[win].addr + h->io[win].size - 1) & 0xff);
        !          1281:        pcic_write(h, io_map_index[win].stop_msb,
        !          1282:            ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff);
        !          1283:
        !          1284:        reg = pcic_read(h, PCIC_IOCTL);
        !          1285:        reg &= ~io_map_index[win].ioctlmask;
        !          1286:        reg |= io_map_index[win].ioctlbits[h->io[win].width];
        !          1287:        pcic_write(h, PCIC_IOCTL, reg);
        !          1288:
        !          1289:        reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
        !          1290:        reg |= io_map_index[win].ioenable;
        !          1291:        pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
        !          1292: }
        !          1293:
        !          1294: int
        !          1295: pcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
        !          1296:        pcmcia_chipset_handle_t pch;
        !          1297:        int width;
        !          1298:        bus_addr_t offset;
        !          1299:        bus_size_t size;
        !          1300:        struct pcmcia_io_handle *pcihp;
        !          1301:        int *windowp;
        !          1302: {
        !          1303:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !          1304:        bus_addr_t ioaddr = pcihp->addr + offset;
        !          1305:        int i, win;
        !          1306: #ifdef PCICDEBUG
        !          1307:        static char *width_names[] = { "auto", "io8", "io16" };
        !          1308: #endif
        !          1309:        struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
        !          1310:
        !          1311:        /* XXX Sanity check offset/size. */
        !          1312:
        !          1313:        win = -1;
        !          1314:        for (i = 0; i < (sizeof(io_map_index) / sizeof(io_map_index[0])); i++) {
        !          1315:                if ((h->ioalloc & (1 << i)) == 0) {
        !          1316:                        win = i;
        !          1317:                        h->ioalloc |= (1 << i);
        !          1318:                        break;
        !          1319:                }
        !          1320:        }
        !          1321:
        !          1322:        if (win == -1)
        !          1323:                return (1);
        !          1324:
        !          1325:        *windowp = win;
        !          1326:
        !          1327:        /* XXX this is pretty gross */
        !          1328:
        !          1329:        if (sc->iot != pcihp->iot)
        !          1330:                panic("pcic_chip_io_map iot is bogus");
        !          1331:
        !          1332:        DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n",
        !          1333:                 win, width_names[width], (u_long) ioaddr, (u_long) size));
        !          1334:
        !          1335:        h->io[win].addr = ioaddr;
        !          1336:        h->io[win].size = size;
        !          1337:        h->io[win].width = width;
        !          1338:
        !          1339:        pcic_chip_do_io_map(h, win);
        !          1340:
        !          1341:        return (0);
        !          1342: }
        !          1343:
        !          1344: void
        !          1345: pcic_chip_io_unmap(pch, window)
        !          1346:        pcmcia_chipset_handle_t pch;
        !          1347:        int window;
        !          1348: {
        !          1349:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !          1350:        int reg;
        !          1351:
        !          1352:        if (window >= (sizeof(io_map_index) / sizeof(io_map_index[0])))
        !          1353:                panic("pcic_chip_io_unmap: window out of range");
        !          1354:
        !          1355:        reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
        !          1356:        reg &= ~io_map_index[window].ioenable;
        !          1357:        pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
        !          1358:
        !          1359:        h->ioalloc &= ~(1 << window);
        !          1360: }
        !          1361:
        !          1362: void
        !          1363: pcic_wait_ready(h)
        !          1364:        struct pcic_handle *h;
        !          1365: {
        !          1366:        int i;
        !          1367:
        !          1368:        for (i = 0; i < 10000; i++) {
        !          1369:                if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY)
        !          1370:                        return;
        !          1371:                delay(500);
        !          1372: #ifdef PCICDEBUG
        !          1373:                        if ((i>5000) && (i%100 == 99))
        !          1374:                                printf(".");
        !          1375: #endif
        !          1376:        }
        !          1377:
        !          1378: #ifdef DIAGNOSTIC
        !          1379:        printf("pcic_wait_ready: ready never happened, status = %02x\n",
        !          1380:            pcic_read(h, PCIC_IF_STATUS));
        !          1381: #endif
        !          1382: }
        !          1383:
        !          1384: void
        !          1385: pcic_chip_socket_enable(pch)
        !          1386:        pcmcia_chipset_handle_t pch;
        !          1387: {
        !          1388:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !          1389:        int cardtype, reg, win;
        !          1390:
        !          1391:        /* this bit is mostly stolen from pcic_attach_card */
        !          1392:
        !          1393:        /* power down the socket to reset it, clear the card reset pin */
        !          1394:
        !          1395:        pcic_write(h, PCIC_PWRCTL, 0);
        !          1396:
        !          1397:        /*
        !          1398:         * wait 300ms until power fails (Tpf).  Then, wait 100ms since
        !          1399:         * we are changing Vcc (Toff).
        !          1400:         */
        !          1401:        delay((300 + 100) * 1000);
        !          1402:
        !          1403:        if (h->vendor == PCIC_VENDOR_VADEM_VG469) {
        !          1404:                reg = pcic_read(h, PCIC_VG469_VSELECT);
        !          1405:                reg &= ~PCIC_VG469_VSELECT_VCC;
        !          1406:                pcic_write(h, PCIC_VG469_VSELECT, reg);
        !          1407:        }
        !          1408:
        !          1409:        /* power up the socket */
        !          1410:
        !          1411:        pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV
        !          1412:                           | PCIC_PWRCTL_PWR_ENABLE);
        !          1413:
        !          1414:        /*
        !          1415:         * wait 100ms until power raise (Tpr) and 20ms to become
        !          1416:         * stable (Tsu(Vcc)).
        !          1417:         *
        !          1418:         * some machines require some more time to be settled
        !          1419:         * (another 200ms is added here).
        !          1420:         */
        !          1421:        delay((100 + 20 + 200) * 1000);
        !          1422:
        !          1423:        pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV |
        !          1424:            PCIC_PWRCTL_OE | PCIC_PWRCTL_PWR_ENABLE);
        !          1425:        pcic_write(h, PCIC_INTR, 0);
        !          1426:
        !          1427:        /*
        !          1428:         * hold RESET at least 10us.
        !          1429:         */
        !          1430:        delay(10);
        !          1431:
        !          1432:        /* clear the reset flag */
        !          1433:
        !          1434:        pcic_write(h, PCIC_INTR, PCIC_INTR_RESET);
        !          1435:
        !          1436:        /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
        !          1437:
        !          1438:        delay(20000);
        !          1439:
        !          1440:        /* wait for the chip to finish initializing */
        !          1441:
        !          1442: #ifdef DIAGNOSTIC
        !          1443:        reg = pcic_read(h, PCIC_IF_STATUS);
        !          1444:        if (!(reg & PCIC_IF_STATUS_POWERACTIVE)) {
        !          1445:                printf("pcic_chip_socket_enable: status %x\n", reg);
        !          1446:        }
        !          1447: #endif
        !          1448:
        !          1449:        pcic_wait_ready(h);
        !          1450:
        !          1451:        /* zero out the address windows */
        !          1452:
        !          1453:        pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
        !          1454:
        !          1455:        /* set the card type */
        !          1456:
        !          1457:        cardtype = pcmcia_card_gettype(h->pcmcia);
        !          1458:
        !          1459:        reg = pcic_read(h, PCIC_INTR);
        !          1460:        reg &= ~PCIC_INTR_CARDTYPE_MASK;
        !          1461:        reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
        !          1462:                PCIC_INTR_CARDTYPE_IO :
        !          1463:                PCIC_INTR_CARDTYPE_MEM);
        !          1464:        reg |= h->ih_irq;
        !          1465:        pcic_write(h, PCIC_INTR, reg);
        !          1466:
        !          1467:        DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n",
        !          1468:            h->ph_parent->dv_xname, h->sock,
        !          1469:            ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg));
        !          1470:
        !          1471:        /* reinstall all the memory and io mappings */
        !          1472:
        !          1473:        for (win = 0; win < PCIC_MEM_WINS; win++)
        !          1474:                if (h->memalloc & (1 << win))
        !          1475:                        pcic_chip_do_mem_map(h, win);
        !          1476:
        !          1477:        for (win = 0; win < PCIC_IO_WINS; win++)
        !          1478:                if (h->ioalloc & (1 << win))
        !          1479:                        pcic_chip_do_io_map(h, win);
        !          1480: }
        !          1481:
        !          1482: void
        !          1483: pcic_chip_socket_disable(pch)
        !          1484:        pcmcia_chipset_handle_t pch;
        !          1485: {
        !          1486:        struct pcic_handle *h = (struct pcic_handle *) pch;
        !          1487:
        !          1488:        DPRINTF(("pcic_chip_socket_disable\n"));
        !          1489:
        !          1490:        /* power down the socket */
        !          1491:
        !          1492:        pcic_write(h, PCIC_PWRCTL, 0);
        !          1493:
        !          1494:        /*
        !          1495:         * wait 300ms until power fails (Tpf).
        !          1496:         */
        !          1497:        delay(300 * 1000);
        !          1498: }
        !          1499:
        !          1500: u_int8_t
        !          1501: st_pcic_read(h, idx)
        !          1502:        struct pcic_handle *h;
        !          1503:        int idx;
        !          1504: {
        !          1505:        if (idx != -1)
        !          1506:                bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX,
        !          1507:                    h->sock + idx);
        !          1508:        return bus_space_read_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA);
        !          1509: }
        !          1510:
        !          1511: void
        !          1512: st_pcic_write(h, idx, data)
        !          1513:        struct pcic_handle *h;
        !          1514:        int idx;
        !          1515:        int data;
        !          1516: {
        !          1517:        if (idx != -1)
        !          1518:                bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX,
        !          1519:                    h->sock + idx);
        !          1520:        if (data != -1)
        !          1521:                bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA,
        !          1522:                    data);
        !          1523: }

CVSweb