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

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

1.1     ! nbrk        1: /*     $OpenBSD: tcic2.c,v 1.7 2005/11/23 11:39:37 mickey Exp $        */
        !             2: /*     $NetBSD: tcic2.c,v 1.3 2000/01/13 09:38:17 joda Exp $   */
        !             3:
        !             4: #undef TCICDEBUG
        !             5:
        !             6: /*
        !             7:  * Copyright (c) 1998, 1999 Christoph Badura.  All rights reserved.
        !             8:  * Copyright (c) 1997 Marc Horowitz.  All rights reserved.
        !             9:  *
        !            10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  * 3. All advertising materials mentioning features or use of this software
        !            19:  *    must display the following acknowledgement:
        !            20:  *     This product includes software developed by Marc Horowitz.
        !            21:  * 4. The name of the author may not be used to endorse or promote products
        !            22:  *    derived from this software without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            25:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            26:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            27:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            28:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            29:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            30:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            31:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            32:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            33:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35:
        !            36: #include <sys/types.h>
        !            37: #include <sys/param.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/device.h>
        !            40: #include <sys/extent.h>
        !            41: #include <sys/malloc.h>
        !            42: #include <sys/kthread.h>
        !            43:
        !            44: #include <uvm/uvm_extern.h>
        !            45:
        !            46: #include <machine/bus.h>
        !            47: #include <machine/intr.h>
        !            48:
        !            49: #include <dev/pcmcia/pcmciareg.h>
        !            50: #include <dev/pcmcia/pcmciavar.h>
        !            51:
        !            52: #include <dev/ic/tcic2reg.h>
        !            53: #include <dev/ic/tcic2var.h>
        !            54:
        !            55: #ifdef TCICDEBUG
        !            56: int    tcic_debug = 1;
        !            57: #define        DPRINTF(arg) if (tcic_debug) printf arg;
        !            58: #else
        !            59: #define        DPRINTF(arg)
        !            60: #endif
        !            61:
        !            62: /*
        !            63:  * Individual drivers will allocate their own memory and io regions. Memory
        !            64:  * regions must be a multiple of 4k, aligned on a 4k boundary.
        !            65:  */
        !            66:
        !            67: #define        TCIC_MEM_ALIGN  TCIC_MEM_PAGESIZE
        !            68:
        !            69: void   tcic_attach_socket(struct tcic_handle *);
        !            70: void   tcic_init_socket(struct tcic_handle *);
        !            71:
        !            72: int    tcic_submatch(struct device *, void *, void *);
        !            73: int    tcic_print(void *arg, const char *pnp);
        !            74: int    tcic_intr_socket(struct tcic_handle *);
        !            75:
        !            76: void   tcic_attach_card(struct tcic_handle *);
        !            77: void   tcic_detach_card(struct tcic_handle *, int);
        !            78: void   tcic_deactivate_card(struct tcic_handle *);
        !            79:
        !            80: void   tcic_chip_do_mem_map(struct tcic_handle *, int);
        !            81: void   tcic_chip_do_io_map(struct tcic_handle *, int);
        !            82:
        !            83: void   tcic_create_event_thread(void *);
        !            84: void   tcic_event_thread(void *);
        !            85:
        !            86: void   tcic_queue_event(struct tcic_handle *, int);
        !            87:
        !            88: struct cfdriver tcic_cd = {
        !            89:        NULL, "tcic", DV_DULL
        !            90: };
        !            91:
        !            92: /* Map between irq numbers and internal representation */
        !            93: #if 1
        !            94: int tcic_irqmap[] =
        !            95:     { 0, 0, 0, 3, 4, 5, 6, 7, 0, 0, 10, 1, 0, 0, 14, 0 };
        !            96: int tcic_valid_irqs = 0x4cf8;
        !            97: #else
        !            98: int tcic_irqmap[] =    /* irqs 9 and 6 switched, some ISA cards */
        !            99:     { 0, 0, 0, 3, 4, 5, 0, 7, 0, 6, 10, 1, 0, 0, 14, 0 };
        !           100: int tcic_valid_irqs = 0x4eb8;
        !           101: #endif
        !           102:
        !           103: int tcic_mem_speed = 250;      /* memory access time in nanoseconds */
        !           104: int tcic_io_speed = 165;       /* io access time in nanoseconds */
        !           105:
        !           106: /*
        !           107:  * Check various reserved and otherwise in their value restricted bits.
        !           108:  */
        !           109: int
        !           110: tcic_check_reserved_bits(iot, ioh)
        !           111:        bus_space_tag_t iot;
        !           112:        bus_space_handle_t ioh;
        !           113: {
        !           114:        int val, auxreg;
        !           115:
        !           116:        DPRINTF(("tcic: chkrsvd 1\n"));
        !           117:        /* R_ADDR bit 30:28 have a restricted range. */
        !           118:        val = (bus_space_read_2(iot, ioh, TCIC_R_ADDR2) & TCIC_SS_MASK)
        !           119:            >> TCIC_SS_SHIFT;
        !           120:        if (val > 1)
        !           121:                return 0;
        !           122:
        !           123:        DPRINTF(("tcic: chkrsvd 2\n"));
        !           124:        /* R_SCTRL bits 6,2,1 are reserved. */
        !           125:        val = bus_space_read_1(iot, ioh, TCIC_R_SCTRL);
        !           126:        if (val & TCIC_SCTRL_RSVD)
        !           127:                return 0;
        !           128:
        !           129:        DPRINTF(("tcic: chkrsvd 3\n"));
        !           130:        /* R_ICSR bit 2 must be same as bit 3. */
        !           131:        val = bus_space_read_1(iot, ioh, TCIC_R_ICSR);
        !           132:        if (((val >> 1) & 1) != ((val >> 2) & 1))
        !           133:                return 0;
        !           134:
        !           135:        DPRINTF(("tcic: chkrsvd 4\n"));
        !           136:        /* R_IENA bits 7,2 are reserved. */
        !           137:        val = bus_space_read_1(iot, ioh, TCIC_R_IENA);
        !           138:        if (val & TCIC_IENA_RSVD)
        !           139:                return 0;
        !           140:
        !           141:        DPRINTF(("tcic: chkrsvd 5\n"));
        !           142:        /* Some aux registers have reserved bits. */
        !           143:        /* Which are we looking at? */
        !           144:        auxreg = bus_space_read_1(iot, ioh, TCIC_R_MODE)
        !           145:            & TCIC_AR_MASK;
        !           146:        val = bus_space_read_2(iot, ioh, TCIC_R_AUX);
        !           147:        DPRINTF(("tcic: auxreg 0x%02x val 0x%04x\n", auxreg, val));
        !           148:        switch (auxreg) {
        !           149:        case TCIC_AR_SYSCFG:
        !           150:                if (INVALID_AR_SYSCFG(val))
        !           151:                        return 0;
        !           152:                break;
        !           153:        case TCIC_AR_ILOCK:
        !           154:                if (INVALID_AR_ILOCK(val))
        !           155:                        return 0;
        !           156:                break;
        !           157:        case TCIC_AR_TEST:
        !           158:                if (INVALID_AR_TEST(val))
        !           159:                        return 0;
        !           160:                break;
        !           161:        }
        !           162:
        !           163:        DPRINTF(("tcic: chkrsvd 6\n"));
        !           164:        /* XXX fails if pcmcia bios is enabled. */
        !           165:        /* Various bits set or not depending if in RESET mode. */
        !           166:        val = bus_space_read_1(iot, ioh, TCIC_R_SCTRL);
        !           167:        if (val & TCIC_SCTRL_RESET) {
        !           168:                DPRINTF(("tcic: chkrsvd 7\n"));
        !           169:                /* Address bits must be 0 */
        !           170:                val = bus_space_read_2(iot, ioh, TCIC_R_ADDR);
        !           171:                if (val != 0)
        !           172:                        return 0;
        !           173:                val = bus_space_read_2(iot, ioh, TCIC_R_ADDR2);
        !           174:                if (val != 0)
        !           175:                        return 0;
        !           176:                DPRINTF(("tcic: chkrsvd 8\n"));
        !           177:                /* EDC bits must be 0 */
        !           178:                val = bus_space_read_2(iot, ioh, TCIC_R_EDC);
        !           179:                if (val != 0)
        !           180:                        return 0;
        !           181:                /* We're OK, so take it out of reset. XXX -chb */
        !           182:                bus_space_write_1(iot, ioh, TCIC_R_SCTRL, 0);
        !           183:        }
        !           184:        else {  /* not in RESET mode */
        !           185:                int omode;
        !           186:                int val1, val2;
        !           187:                DPRINTF(("tcic: chkrsvd 9\n"));
        !           188:                /* Programming timers must have expired. */
        !           189:                val = bus_space_read_1(iot, ioh, TCIC_R_SSTAT);
        !           190:                if ((val & (TCIC_SSTAT_6US|TCIC_SSTAT_10US|TCIC_SSTAT_PROGTIME))
        !           191:                    != (TCIC_SSTAT_6US|TCIC_SSTAT_10US|TCIC_SSTAT_PROGTIME))
        !           192:                        return 0;
        !           193:                DPRINTF(("tcic: chkrsvd 10\n"));
        !           194:                /*
        !           195:                 * EDC bits should change on read from data space
        !           196:                 * as long as either EDC or the data are nonzero.
        !           197:                 */
        !           198:                 if ((bus_space_read_2(iot, ioh, TCIC_R_ADDR2)
        !           199:                     & TCIC_ADDR2_INDREG) != 0) {
        !           200:                        val1 = bus_space_read_2(iot, ioh, TCIC_R_EDC);
        !           201:                        val2 = bus_space_read_2(iot, ioh, TCIC_R_DATA);
        !           202:                        if (val1 | val2) {
        !           203:                                val1 = bus_space_read_2(iot, ioh, TCIC_R_EDC);
        !           204:                                if (val1 == val2)
        !           205:                                        return 0;
        !           206:                        }
        !           207:                }
        !           208:                DPRINTF(("tcic: chkrsvd 11\n"));
        !           209:                /* XXX what does this check? -chb */
        !           210:                omode = bus_space_read_1(iot, ioh, TCIC_R_MODE);
        !           211:                val1 = omode ^ TCIC_AR_MASK;
        !           212:                bus_space_write_1(iot, ioh, TCIC_R_MODE, val1);
        !           213:                val2 = bus_space_read_1(iot, ioh, TCIC_R_MODE);
        !           214:                bus_space_write_1(iot, ioh, TCIC_R_MODE, omode);
        !           215:                if ( val1 != val2)
        !           216:                        return 0;
        !           217:        }
        !           218:        /* All tests passed */
        !           219:        return 1;
        !           220: }
        !           221:
        !           222: /*
        !           223:  * Read chip ID from AR_ILOCK in test mode.
        !           224:  */
        !           225: int
        !           226: tcic_chipid(iot, ioh)
        !           227:        bus_space_tag_t iot;
        !           228:        bus_space_handle_t ioh;
        !           229: {
        !           230:        unsigned id, otest;
        !           231:
        !           232:        otest = tcic_read_aux_2(iot, ioh, TCIC_AR_TEST);
        !           233:        tcic_write_aux_2(iot, ioh, TCIC_AR_TEST, TCIC_TEST_DIAG);
        !           234:        id = tcic_read_aux_2(iot, ioh, TCIC_AR_ILOCK);
        !           235:        tcic_write_aux_2(iot, ioh, TCIC_AR_TEST, otest);
        !           236:        id &= TCIC_ILOCKTEST_ID_MASK;
        !           237:        id >>= TCIC_ILOCKTEST_ID_SHFT;
        !           238:
        !           239:        /* clear up IRQs inside tcic. XXX -chb */
        !           240:        while (bus_space_read_1(iot, ioh, TCIC_R_ICSR))
        !           241:                bus_space_write_1(iot, ioh, TCIC_R_ICSR, TCIC_ICSR_JAM);
        !           242:
        !           243:        return id;
        !           244: }
        !           245: /*
        !           246:  * Indicate whether the driver can handle the chip.
        !           247:  */
        !           248: int
        !           249: tcic_chipid_known(id)
        !           250:        int id;
        !           251: {
        !           252:        /* XXX only know how to handle DB86082 -chb */
        !           253:        switch (id) {
        !           254:        case TCIC_CHIPID_DB86082_1:
        !           255:        case TCIC_CHIPID_DB86082A:
        !           256:        case TCIC_CHIPID_DB86082B_ES:
        !           257:        case TCIC_CHIPID_DB86082B:
        !           258:        case TCIC_CHIPID_DB86084_1:
        !           259:        case TCIC_CHIPID_DB86084A:
        !           260:        case TCIC_CHIPID_DB86184_1:
        !           261:        case TCIC_CHIPID_DB86072_1_ES:
        !           262:        case TCIC_CHIPID_DB86072_1:
        !           263:                return 1;
        !           264:        }
        !           265:
        !           266:        return 0;
        !           267: }
        !           268:
        !           269: char *
        !           270: tcic_chipid_to_string(id)
        !           271:        int id;
        !           272: {
        !           273:        switch (id) {
        !           274:        case TCIC_CHIPID_DB86082_1:
        !           275:                return ("Databook DB86082");
        !           276:        case TCIC_CHIPID_DB86082A:
        !           277:                return ("Databook DB86082A");
        !           278:        case TCIC_CHIPID_DB86082B_ES:
        !           279:                return ("Databook DB86082B-es");
        !           280:        case TCIC_CHIPID_DB86082B:
        !           281:                return ("Databook DB86082B");
        !           282:        case TCIC_CHIPID_DB86084_1:
        !           283:                return ("Databook DB86084");
        !           284:        case TCIC_CHIPID_DB86084A:
        !           285:                return ("Databook DB86084A");
        !           286:        case TCIC_CHIPID_DB86184_1:
        !           287:                return ("Databook DB86184");
        !           288:        case TCIC_CHIPID_DB86072_1_ES:
        !           289:                return ("Databook DB86072-es");
        !           290:        case TCIC_CHIPID_DB86072_1:
        !           291:                return ("Databook DB86072");
        !           292:        }
        !           293:
        !           294:        return ("Unknown controller");
        !           295: }
        !           296: /*
        !           297:  * Return bitmask of IRQs that the chip can handle.
        !           298:  * XXX should be table driven.
        !           299:  */
        !           300: int
        !           301: tcic_validirqs(chipid)
        !           302:        int chipid;
        !           303: {
        !           304:        switch (chipid) {
        !           305:        case TCIC_CHIPID_DB86082_1:
        !           306:        case TCIC_CHIPID_DB86082A:
        !           307:        case TCIC_CHIPID_DB86082B_ES:
        !           308:        case TCIC_CHIPID_DB86082B:
        !           309:        case TCIC_CHIPID_DB86084_1:
        !           310:        case TCIC_CHIPID_DB86084A:
        !           311:        case TCIC_CHIPID_DB86184_1:
        !           312:        case TCIC_CHIPID_DB86072_1_ES:
        !           313:        case TCIC_CHIPID_DB86072_1:
        !           314:                return tcic_valid_irqs;
        !           315:        }
        !           316:        return 0;
        !           317: }
        !           318:
        !           319: void
        !           320: tcic_attach(sc)
        !           321:        struct tcic_softc *sc;
        !           322: {
        !           323:        int i, reg;
        !           324:
        !           325:        /* set more chipset-dependent parameters in the softc. */
        !           326:        switch (sc->chipid) {
        !           327:        case TCIC_CHIPID_DB86084_1:
        !           328:        case TCIC_CHIPID_DB86084A:
        !           329:        case TCIC_CHIPID_DB86184_1:
        !           330:                sc->pwrena = TCIC_PWR_ENA;
        !           331:                break;
        !           332:        default:
        !           333:                sc->pwrena = 0;
        !           334:                break;
        !           335:        }
        !           336:
        !           337:        /* set up global config registers */
        !           338:        reg = TCIC_WAIT_SYNC | TCIC_WAIT_CCLK | TCIC_WAIT_RISING;
        !           339:        reg |= (tcic_ns2wscnt(250) & TCIC_WAIT_COUNT_MASK);
        !           340:        tcic_write_aux_1(sc->iot, sc->ioh, TCIC_AR_WCTL, TCIC_R_WCTL_WAIT, reg);
        !           341:        reg = TCIC_SYSCFG_MPSEL_RI | TCIC_SYSCFG_MCSFULL;
        !           342:        tcic_write_aux_2(sc->iot, sc->ioh, TCIC_AR_SYSCFG, reg);
        !           343:        reg = tcic_read_aux_2(sc->iot, sc->ioh, TCIC_AR_ILOCK);
        !           344:        reg |= TCIC_ILOCK_HOLD_CCLK;
        !           345:        tcic_write_aux_2(sc->iot, sc->ioh, TCIC_AR_ILOCK, reg);
        !           346:
        !           347:        /* the TCIC has two sockets */
        !           348:        /* XXX should i check for actual presence of sockets? -chb */
        !           349:        for (i = 0; i < TCIC_NSLOTS; i++) {
        !           350:                sc->handle[i].sc = sc;
        !           351:                sc->handle[i].sock = i;
        !           352:                sc->handle[i].flags = TCIC_FLAG_SOCKETP;
        !           353:                sc->handle[i].memwins
        !           354:                    = sc->chipid == TCIC_CHIPID_DB86082_1 ?  4 : 5;
        !           355:        }
        !           356:
        !           357:        /* establish the interrupt */
        !           358:        reg = tcic_read_1(&sc->handle[0], TCIC_R_IENA);
        !           359:        tcic_write_1(&sc->handle[0], TCIC_R_IENA,
        !           360:            (reg & ~TCIC_IENA_CFG_MASK) | TCIC_IENA_CFG_HIGH);
        !           361:        reg = tcic_read_aux_2(sc->iot, sc->ioh, TCIC_AR_SYSCFG);
        !           362:        tcic_write_aux_2(sc->iot, sc->ioh, TCIC_AR_SYSCFG,
        !           363:            (reg & ~TCIC_SYSCFG_IRQ_MASK) | tcic_irqmap[sc->irq]);
        !           364:
        !           365:        /* XXX block interrupts? */
        !           366:
        !           367:        for (i = 0; i < TCIC_NSLOTS; i++) {
        !           368:                /* XXX make more clear what happens here -chb */
        !           369:                tcic_sel_sock(&sc->handle[i]);
        !           370:                tcic_write_ind_2(&sc->handle[i], TCIC_IR_SCF1_N(i), 0);
        !           371:                tcic_write_ind_2(&sc->handle[i], TCIC_IR_SCF2_N(i),
        !           372:                    (TCIC_SCF2_MCD|TCIC_SCF2_MWP|TCIC_SCF2_MRDY
        !           373: #if 1          /* XXX explain byte routing issue */
        !           374:                    |TCIC_SCF2_MLBAT2|TCIC_SCF2_MLBAT1|TCIC_SCF2_IDBR));
        !           375: #else
        !           376:                    |TCIC_SCF2_MLBAT2|TCIC_SCF2_MLBAT1));
        !           377: #endif
        !           378:                tcic_write_1(&sc->handle[i], TCIC_R_MODE, 0);
        !           379:                reg = tcic_read_aux_2(sc->iot, sc->ioh, TCIC_AR_SYSCFG);
        !           380:                reg &= ~TCIC_SYSCFG_AUTOBUSY;
        !           381:                tcic_write_aux_2(sc->iot, sc->ioh, TCIC_AR_SYSCFG, reg);
        !           382:                SIMPLEQ_INIT(&sc->handle[i].events);
        !           383:        }
        !           384:
        !           385:        if ((sc->handle[0].flags & TCIC_FLAG_SOCKETP) ||
        !           386:            (sc->handle[1].flags & TCIC_FLAG_SOCKETP)) {
        !           387:                printf("%s: %s has ", sc->dev.dv_xname,
        !           388:                       tcic_chipid_to_string(sc->chipid));
        !           389:
        !           390:                if ((sc->handle[0].flags & TCIC_FLAG_SOCKETP) &&
        !           391:                    (sc->handle[1].flags & TCIC_FLAG_SOCKETP))
        !           392:                        printf("sockets A and B\n");
        !           393:                else if (sc->handle[0].flags & TCIC_FLAG_SOCKETP)
        !           394:                        printf("socket A only\n");
        !           395:                else
        !           396:                        printf("socket B only\n");
        !           397:
        !           398:        }
        !           399: }
        !           400:
        !           401: void
        !           402: tcic_attach_sockets(sc)
        !           403:        struct tcic_softc *sc;
        !           404: {
        !           405:        int i;
        !           406:
        !           407:        for (i = 0; i < TCIC_NSLOTS; i++)
        !           408:                if (sc->handle[i].flags & TCIC_FLAG_SOCKETP)
        !           409:                        tcic_attach_socket(&sc->handle[i]);
        !           410: }
        !           411:
        !           412: void
        !           413: tcic_attach_socket(h)
        !           414:        struct tcic_handle *h;
        !           415: {
        !           416:        struct pcmciabus_attach_args paa;
        !           417:
        !           418:        /* initialize the rest of the handle */
        !           419:
        !           420:        h->shutdown = 0;
        !           421:        h->memalloc = 0;
        !           422:        h->ioalloc = 0;
        !           423:        h->ih_irq = 0;
        !           424:
        !           425:        /* now, config one pcmcia device per socket */
        !           426:
        !           427:        paa.paa_busname = "pcmcia";
        !           428:        paa.pct = (pcmcia_chipset_tag_t) h->sc->pct;
        !           429:        paa.pch = (pcmcia_chipset_handle_t) h;
        !           430:        paa.iobase = h->sc->iobase;
        !           431:        paa.iosize = h->sc->iosize;
        !           432:
        !           433:        h->pcmcia = config_found_sm(&h->sc->dev, &paa, tcic_print,
        !           434:            tcic_submatch);
        !           435:
        !           436:        /* if there's actually a pcmcia device attached, initialize the slot */
        !           437:
        !           438:        if (h->pcmcia)
        !           439:                tcic_init_socket(h);
        !           440:        else
        !           441:                h->flags &= ~TCIC_FLAG_SOCKETP;
        !           442: }
        !           443:
        !           444: void
        !           445: tcic_create_event_thread(arg)
        !           446:        void *arg;
        !           447: {
        !           448:        struct tcic_handle *h = arg;
        !           449:        const char *cs;
        !           450:
        !           451:        switch (h->sock) {
        !           452:        case 0:
        !           453:                cs = "0";
        !           454:                break;
        !           455:        case 1:
        !           456:                cs = "1";
        !           457:                break;
        !           458:        default:
        !           459:                panic("tcic_create_event_thread: unknown tcic socket");
        !           460:        }
        !           461:
        !           462:        if (kthread_create(tcic_event_thread, h, &h->event_thread,
        !           463:            "%s,%s", h->sc->dev.dv_xname, cs)) {
        !           464:                printf("%s: unable to create event thread for sock 0x%02x\n",
        !           465:                    h->sc->dev.dv_xname, h->sock);
        !           466:                panic("tcic_create_event_thread");
        !           467:        }
        !           468: }
        !           469:
        !           470: void
        !           471: tcic_event_thread(arg)
        !           472:        void *arg;
        !           473: {
        !           474:        struct tcic_handle *h = arg;
        !           475:        struct tcic_event *pe;
        !           476:        int s;
        !           477:
        !           478:        while (h->shutdown == 0) {
        !           479:                s = splhigh();
        !           480:                if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
        !           481:                        splx(s);
        !           482:                        (void) tsleep(&h->events, PWAIT, "tcicev", 0);
        !           483:                        continue;
        !           484:                }
        !           485:                SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
        !           486:                splx(s);
        !           487:
        !           488:                switch (pe->pe_type) {
        !           489:                case TCIC_EVENT_INSERTION:
        !           490:                        DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname));
        !           491:                        tcic_attach_card(h);
        !           492:                        break;
        !           493:
        !           494:                case TCIC_EVENT_REMOVAL:
        !           495:                        DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname));
        !           496:                        tcic_detach_card(h, DETACH_FORCE);
        !           497:                        break;
        !           498:
        !           499:                default:
        !           500:                        panic("tcic_event_thread: unknown event %d",
        !           501:                            pe->pe_type);
        !           502:                }
        !           503:                free(pe, M_TEMP);
        !           504:        }
        !           505:
        !           506:        h->event_thread = NULL;
        !           507:
        !           508:        /* In case parent is waiting for us to exit. */
        !           509:        wakeup(h->sc);
        !           510:
        !           511:        kthread_exit(0);
        !           512: }
        !           513:
        !           514:
        !           515: void
        !           516: tcic_init_socket(h)
        !           517:        struct tcic_handle *h;
        !           518: {
        !           519:        int reg;
        !           520:
        !           521:        /* select this socket's config registers */
        !           522:        tcic_sel_sock(h);
        !           523:
        !           524:        /* set up the socket to interrupt on card detect */
        !           525:        reg = tcic_read_ind_2(h, TCIC_IR_SCF2_N(h->sock));
        !           526:        tcic_write_ind_2(h, TCIC_IR_SCF2_N(h->sock), reg & ~TCIC_SCF2_MCD);
        !           527:
        !           528:        /* enable CD irq in R_IENA */
        !           529:        reg = tcic_read_2(h, TCIC_R_IENA);
        !           530:        tcic_write_2(h, TCIC_R_IENA, reg |= TCIC_IENA_CDCHG);
        !           531:
        !           532:        /* if there's a card there, then attach it. also save sstat */
        !           533:        h->sstat = reg = tcic_read_1(h, TCIC_R_SSTAT) & TCIC_SSTAT_STAT_MASK;
        !           534:        if (reg & TCIC_SSTAT_CD)
        !           535:                tcic_attach_card(h);
        !           536: }
        !           537:
        !           538: int
        !           539: tcic_submatch(parent, match, aux)
        !           540:        struct device *parent;
        !           541:        void *match;
        !           542:        void *aux;
        !           543: {
        !           544:        struct cfdata *cf = match;
        !           545:
        !           546:        struct pcmciabus_attach_args *paa = aux;
        !           547:        struct tcic_handle *h = (struct tcic_handle *) paa->pch;
        !           548:
        !           549:        switch (h->sock) {
        !           550:        case 0:
        !           551:                if (cf->cf_loc[0 /* PCMCIABUSCF_CONTROLLER */] !=
        !           552:                    -1 /* PCMCIABUSCF_CONTROLLER_DEFAULT */ &&
        !           553:                    cf->cf_loc[0 /* PCMCIABUSCF_CONTROLLER */] != 0)
        !           554:                        return 0;
        !           555:                if (cf->cf_loc[1 /* PCMCIABUSCF_SOCKET */] !=
        !           556:                    -1 /* PCMCIABUSCF_SOCKET_DEFAULT */ &&
        !           557:                    cf->cf_loc[1 /* PCMCIABUSCF_SOCKET */] != 0)
        !           558:                        return 0;
        !           559:
        !           560:                break;
        !           561:        case 1:
        !           562:                if (cf->cf_loc[0 /* PCMCIABUSCF_CONTROLLER */] !=
        !           563:                    -1 /* PCMCIABUSCF_CONTROLLER_DEFAULT */ &&
        !           564:                    cf->cf_loc[0 /* PCMCIABUSCF_CONTROLLER */] != 0)
        !           565:                        return 0;
        !           566:                if (cf->cf_loc[1 /* PCMCIABUSCF_SOCKET */] !=
        !           567:                    -1 /* PCMCIABUSCF_SOCKET_DEFAULT */ &&
        !           568:                    cf->cf_loc[1 /* PCMCIABUSCF_SOCKET */] != 1)
        !           569:                        return 0;
        !           570:
        !           571:                break;
        !           572:        default:
        !           573:                panic("unknown tcic socket");
        !           574:        }
        !           575:
        !           576:        return ((*cf->cf_attach->ca_match)(parent, cf, aux));
        !           577: }
        !           578:
        !           579: int
        !           580: tcic_print(arg, pnp)
        !           581:        void *arg;
        !           582:        const char *pnp;
        !           583: {
        !           584:        struct pcmciabus_attach_args *paa = arg;
        !           585:        struct tcic_handle *h = (struct tcic_handle *) paa->pch;
        !           586:
        !           587:        /* Only "pcmcia"s can attach to "tcic"s... easy. */
        !           588:        if (pnp)
        !           589:                printf("pcmcia at %s", pnp);
        !           590:
        !           591:        switch (h->sock) {
        !           592:        case 0:
        !           593:                printf(" socket 0");
        !           594:                break;
        !           595:        case 1:
        !           596:                printf(" socket 1");
        !           597:                break;
        !           598:        default:
        !           599:                panic("unknown tcic socket");
        !           600:        }
        !           601:        return (UNCONF);
        !           602: }
        !           603:
        !           604: int
        !           605: tcic_intr(arg)
        !           606:        void *arg;
        !           607: {
        !           608:        struct tcic_softc *sc = arg;
        !           609:        int i, ret = 0;
        !           610:
        !           611:        DPRINTF(("%s: intr\n", sc->dev.dv_xname));
        !           612:
        !           613:        for (i = 0; i < TCIC_NSLOTS; i++)
        !           614:                if (sc->handle[i].flags & TCIC_FLAG_SOCKETP)
        !           615:                        ret += tcic_intr_socket(&sc->handle[i]);
        !           616:
        !           617:        return (ret ? 1 : 0);
        !           618: }
        !           619:
        !           620: int
        !           621: tcic_intr_socket(h)
        !           622:        struct tcic_handle *h;
        !           623: {
        !           624:        int icsr, rv;
        !           625:
        !           626:        rv = 0;
        !           627:        tcic_sel_sock(h);
        !           628:        icsr = tcic_read_1(h, TCIC_R_ICSR);
        !           629:
        !           630:        DPRINTF(("%s: %d icsr: 0x%02x \n", h->sc->dev.dv_xname, h->sock, icsr));
        !           631:
        !           632:        /* XXX or should the next three be handled in tcic_intr? -chb */
        !           633:        if (icsr & TCIC_ICSR_PROGTIME) {
        !           634:                DPRINTF(("%s: %02x PROGTIME\n", h->sc->dev.dv_xname, h->sock));
        !           635:                rv = 1;
        !           636:        }
        !           637:        if (icsr & TCIC_ICSR_ILOCK) {
        !           638:                DPRINTF(("%s: %02x ILOCK\n", h->sc->dev.dv_xname, h->sock));
        !           639:                rv = 1;
        !           640:        }
        !           641:        if (icsr & TCIC_ICSR_ERR) {
        !           642:                DPRINTF(("%s: %02x ERR\n", h->sc->dev.dv_xname, h->sock));
        !           643:                rv = 1;
        !           644:        }
        !           645:        if (icsr & TCIC_ICSR_CDCHG) {
        !           646:                int sstat, delta;
        !           647:
        !           648:                /* compute what changed since last interrupt */
        !           649:                sstat = tcic_read_aux_1(h->sc->iot, h->sc->ioh,
        !           650:                    TCIC_AR_WCTL, TCIC_R_WCTL_XCSR) & TCIC_XCSR_STAT_MASK;
        !           651:                delta = h->sstat ^ sstat;
        !           652:                h->sstat = sstat;
        !           653:
        !           654:                if (delta)
        !           655:                        rv = 1;
        !           656:
        !           657:                DPRINTF(("%s: %02x CDCHG %x\n", h->sc->dev.dv_xname, h->sock,
        !           658:                    delta));
        !           659:
        !           660:                /*
        !           661:                 * XXX This should probably schedule something to happen
        !           662:                 * after the interrupt handler completes
        !           663:                 */
        !           664:
        !           665:                if (delta & TCIC_SSTAT_CD) {
        !           666:                        if (sstat & TCIC_SSTAT_CD) {
        !           667:                                if (!(h->flags & TCIC_FLAG_CARDP)) {
        !           668:                                        DPRINTF(("%s: enqueing INSERTION event\n",
        !           669:                                            h->sc->dev.dv_xname));
        !           670:                                        tcic_queue_event(h, TCIC_EVENT_INSERTION);
        !           671:                                }
        !           672:                        } else {
        !           673:                                if (h->flags & TCIC_FLAG_CARDP) {
        !           674:                                        /* Deactivate the card now. */
        !           675:                                        DPRINTF(("%s: deactivating card\n",
        !           676:                                            h->sc->dev.dv_xname));
        !           677:                                        tcic_deactivate_card(h);
        !           678:
        !           679:                                        DPRINTF(("%s: enqueing REMOVAL event\n",
        !           680:                                            h->sc->dev.dv_xname));
        !           681:                                        tcic_queue_event(h, TCIC_EVENT_REMOVAL);
        !           682:                                }
        !           683:                        }
        !           684:                }
        !           685:                if (delta & TCIC_SSTAT_RDY) {
        !           686:                        DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
        !           687:                        /* shouldn't happen */
        !           688:                }
        !           689:                if (delta & TCIC_SSTAT_LBAT1) {
        !           690:                        DPRINTF(("%s: %02x LBAT1\n", h->sc->dev.dv_xname, h->sock));
        !           691:                }
        !           692:                if (delta & TCIC_SSTAT_LBAT2) {
        !           693:                        DPRINTF(("%s: %02x LBAT2\n", h->sc->dev.dv_xname, h->sock));
        !           694:                }
        !           695:                if (delta & TCIC_SSTAT_WP) {
        !           696:                        DPRINTF(("%s: %02x WP\n", h->sc->dev.dv_xname, h->sock));
        !           697:                }
        !           698:        }
        !           699:        return rv;
        !           700: }
        !           701:
        !           702: void
        !           703: tcic_queue_event(h, event)
        !           704:        struct tcic_handle *h;
        !           705:        int event;
        !           706: {
        !           707:        struct tcic_event *pe;
        !           708:        int s;
        !           709:
        !           710:        pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
        !           711:        if (pe == NULL)
        !           712:                panic("tcic_queue_event: can't allocate event");
        !           713:
        !           714:        pe->pe_type = event;
        !           715:        s = splhigh();
        !           716:        SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
        !           717:        splx(s);
        !           718:        wakeup(&h->events);
        !           719: }
        !           720: void
        !           721: tcic_attach_card(h)
        !           722:        struct tcic_handle *h;
        !           723: {
        !           724:        DPRINTF(("tcic_attach_card\n"));
        !           725:
        !           726:        if (h->flags & TCIC_FLAG_CARDP)
        !           727:                panic("tcic_attach_card: already attached");
        !           728:
        !           729:        /* call the MI attach function */
        !           730:
        !           731:        pcmcia_card_attach(h->pcmcia);
        !           732:
        !           733:        h->flags |= TCIC_FLAG_CARDP;
        !           734: }
        !           735:
        !           736: void
        !           737: tcic_detach_card(h, flags)
        !           738:        struct tcic_handle *h;
        !           739:        int flags;              /* DETACH_* */
        !           740: {
        !           741:        DPRINTF(("tcic_detach_card\n"));
        !           742:
        !           743:        if (!(h->flags & TCIC_FLAG_CARDP))
        !           744:                panic("tcic_detach_card: already detached");
        !           745:
        !           746:        h->flags &= ~TCIC_FLAG_CARDP;
        !           747:
        !           748:        /* call the MI detach function */
        !           749:
        !           750:        pcmcia_card_detach(h->pcmcia, flags);
        !           751:
        !           752: }
        !           753:
        !           754: void
        !           755: tcic_deactivate_card(h)
        !           756:        struct tcic_handle *h;
        !           757: {
        !           758:        int val, reg;
        !           759:
        !           760:        if (!(h->flags & TCIC_FLAG_CARDP))
        !           761:                 panic("tcic_deactivate_card: already detached");
        !           762:
        !           763:        /* call the MI deactivate function */
        !           764:        pcmcia_card_deactivate(h->pcmcia);
        !           765:
        !           766:        tcic_sel_sock(h);
        !           767:
        !           768:        /* XXX disable card detect resume and configuration reset??? */
        !           769:
        !           770:        /* power down the socket */
        !           771:        tcic_write_1(h, TCIC_R_PWR, 0);
        !           772:
        !           773:        /* reset the card XXX ? -chb */
        !           774:
        !           775:        /* turn off irq's for this socket */
        !           776:        reg = TCIC_IR_SCF1_N(h->sock);
        !           777:        val = tcic_read_ind_2(h, reg);
        !           778:        tcic_write_ind_2(h, reg, (val & ~TCIC_SCF1_IRQ_MASK)|TCIC_SCF1_IRQOFF);
        !           779:        reg = TCIC_IR_SCF2_N(h->sock);
        !           780:        val = tcic_read_ind_2(h, reg);
        !           781:        tcic_write_ind_2(h, reg,
        !           782:            (val | (TCIC_SCF2_MLBAT1|TCIC_SCF2_MLBAT2|TCIC_SCF2_MRDY
        !           783:                |TCIC_SCF2_MWP|TCIC_SCF2_MCD)));
        !           784: }
        !           785:
        !           786: /* XXX the following routine may need to be rewritten. -chb */
        !           787: int
        !           788: tcic_chip_mem_alloc(pch, size, pcmhp)
        !           789:        pcmcia_chipset_handle_t pch;
        !           790:        bus_size_t size;
        !           791:        struct pcmcia_mem_handle *pcmhp;
        !           792: {
        !           793:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !           794:        bus_space_handle_t memh;
        !           795:        bus_addr_t addr;
        !           796:        bus_size_t sizepg;
        !           797:        int i, mask, mhandle;
        !           798:
        !           799:        /* out of sc->memh, allocate as many pages as necessary */
        !           800:
        !           801:        /*
        !           802:         * The TCIC can map memory only in sizes that are
        !           803:         * powers of two, aligned at the natural boundary for the size.
        !           804:         */
        !           805:        i = tcic_log2((u_int)size);
        !           806:        if ((1<<i) < size)
        !           807:                i++;
        !           808:        sizepg = max(i, TCIC_MEM_SHIFT) - (TCIC_MEM_SHIFT-1);
        !           809:
        !           810:        DPRINTF(("tcic_chip_mem_alloc: size %ld sizepg %ld\n", size, sizepg));
        !           811:
        !           812:        /* can't allocate that much anyway */
        !           813:        if (sizepg > TCIC_MEM_PAGES)    /* XXX -chb */
        !           814:                return 1;
        !           815:
        !           816:        mask = (1 << sizepg) - 1;
        !           817:
        !           818:        addr = 0;               /* XXX gcc -Wuninitialized */
        !           819:        mhandle = 0;            /* XXX gcc -Wuninitialized */
        !           820:
        !           821:        /* XXX i should be initialised to always lay on boundary. -chb */
        !           822:        for (i = 0; i < (TCIC_MEM_PAGES + 1 - sizepg); i += sizepg) {
        !           823:                if ((h->sc->subregionmask & (mask << i)) == (mask << i)) {
        !           824:                        if (bus_space_subregion(h->sc->memt, h->sc->memh,
        !           825:                            i * TCIC_MEM_PAGESIZE,
        !           826:                            sizepg * TCIC_MEM_PAGESIZE, &memh))
        !           827:                                return (1);
        !           828:                        mhandle = mask << i;
        !           829:                        addr = h->sc->membase + (i * TCIC_MEM_PAGESIZE);
        !           830:                        h->sc->subregionmask &= ~(mhandle);
        !           831:                        break;
        !           832:                }
        !           833:        }
        !           834:
        !           835:        if (i == (TCIC_MEM_PAGES + 1 - sizepg))
        !           836:                return (1);
        !           837:
        !           838:        DPRINTF(("tcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n", (u_long) addr,
        !           839:                 (u_long) size));
        !           840:
        !           841:        pcmhp->memt = h->sc->memt;
        !           842:        pcmhp->memh = memh;
        !           843:        pcmhp->addr = addr;
        !           844:        pcmhp->size = size;
        !           845:        pcmhp->mhandle = mhandle;
        !           846:        pcmhp->realsize = sizepg * TCIC_MEM_PAGESIZE;
        !           847:
        !           848:        return (0);
        !           849: }
        !           850:
        !           851: /* XXX the following routine may need to be rewritten. -chb */
        !           852: void
        !           853: tcic_chip_mem_free(pch, pcmhp)
        !           854:        pcmcia_chipset_handle_t pch;
        !           855:        struct pcmcia_mem_handle *pcmhp;
        !           856: {
        !           857:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !           858:
        !           859:        h->sc->subregionmask |= pcmhp->mhandle;
        !           860: }
        !           861:
        !           862: void
        !           863: tcic_chip_do_mem_map(h, win)
        !           864:        struct tcic_handle *h;
        !           865:        int win;
        !           866: {
        !           867:        int reg, hwwin, wscnt;
        !           868:
        !           869:        int kind = h->mem[win].kind & ~PCMCIA_WIDTH_MEM_MASK;
        !           870:        int mem8 = (h->mem[win].kind & PCMCIA_WIDTH_MEM_MASK) == PCMCIA_WIDTH_MEM8;
        !           871:        DPRINTF(("tcic_chip_do_mem_map window %d: 0x%lx+0x%lx 0x%lx\n",
        !           872:                win, (u_long)h->mem[win].addr, (u_long)h->mem[win].size,
        !           873:                (u_long)h->mem[win].offset));
        !           874:        /*
        !           875:         * the even windows are used for socket 0,
        !           876:         * the odd ones for socket 1.
        !           877:         */
        !           878:        hwwin = (win << 1) + h->sock;
        !           879:
        !           880:        /* the WR_MEXT register is MBZ */
        !           881:        tcic_write_ind_2(h, TCIC_WR_MEXT_N(hwwin), 0);
        !           882:
        !           883:        /* set the host base address and window size */
        !           884:        if (h->mem[win].size2 <= 1) {
        !           885:                reg = ((h->mem[win].addr >> TCIC_MEM_SHIFT) &
        !           886:                    TCIC_MBASE_ADDR_MASK) | TCIC_MBASE_4K;
        !           887:        } else {
        !           888:                reg = ((h->mem[win].addr >> TCIC_MEM_SHIFT) &
        !           889:                    TCIC_MBASE_ADDR_MASK) | (h->mem[win].size2 >> 1);
        !           890:        }
        !           891:        tcic_write_ind_2(h, TCIC_WR_MBASE_N(hwwin), reg);
        !           892:
        !           893:        /* set the card address and address space */
        !           894:        reg = 0;
        !           895:        reg = ((h->mem[win].offset >> TCIC_MEM_SHIFT) & TCIC_MMAP_ADDR_MASK);
        !           896:        reg |= (kind == PCMCIA_MEM_ATTR) ? TCIC_MMAP_ATTR : 0;
        !           897:        DPRINTF(("tcic_chip_do_map_mem window %d(%d) mmap 0x%04x\n",
        !           898:            win, hwwin, reg));
        !           899:        tcic_write_ind_2(h, TCIC_WR_MMAP_N(hwwin), reg);
        !           900:
        !           901:        /* set the MCTL register */
        !           902:        /* must save WSCNT field in case this is a DB86082 rev 0 */
        !           903:        /* XXX why can't I do the following two in one statement? */
        !           904:        reg = tcic_read_ind_2(h, TCIC_WR_MCTL_N(hwwin)) & TCIC_MCTL_WSCNT_MASK;
        !           905:        reg |= TCIC_MCTL_ENA|TCIC_MCTL_QUIET;
        !           906:        reg |= mem8 ? TCIC_MCTL_B8 : 0;
        !           907:        reg |= (h->sock << TCIC_MCTL_SS_SHIFT) & TCIC_MCTL_SS_MASK;
        !           908: #ifdef notyet  /* XXX must get speed from CIS somehow. -chb */
        !           909:        wscnt = tcic_ns2wscnt(h->mem[win].speed);
        !           910: #else
        !           911:        wscnt = tcic_ns2wscnt(tcic_mem_speed);  /*  300 is "save" default for CIS memory */
        !           912: #endif
        !           913:        if (h->sc->chipid == TCIC_CHIPID_DB86082_1) {
        !           914:                /*
        !           915:                 * this chip has the wait state count in window
        !           916:                 * register 7 - hwwin.
        !           917:                 */
        !           918:                int reg2;
        !           919:                reg2 = tcic_read_ind_2(h, TCIC_WR_MCTL_N(7-hwwin));
        !           920:                reg2 &= ~TCIC_MCTL_WSCNT_MASK;
        !           921:                reg2 |= wscnt & TCIC_MCTL_WSCNT_MASK;
        !           922:                tcic_write_ind_2(h, TCIC_WR_MCTL_N(7-hwwin), reg2);
        !           923:        } else {
        !           924:                reg |= wscnt & TCIC_MCTL_WSCNT_MASK;
        !           925:        }
        !           926:        tcic_write_ind_2(h, TCIC_WR_MCTL_N(hwwin), reg);
        !           927:
        !           928: #ifdef TCICDEBUG
        !           929:        {
        !           930:                int r1, r2, r3;
        !           931:
        !           932:                r1 = tcic_read_ind_2(h, TCIC_WR_MBASE_N(hwwin));
        !           933:                r2 = tcic_read_ind_2(h, TCIC_WR_MMAP_N(hwwin));
        !           934:                r3 = tcic_read_ind_2(h, TCIC_WR_MCTL_N(hwwin));
        !           935:
        !           936:                DPRINTF(("tcic_chip_do_mem_map window %d(%d): %04x %04x %04x\n",
        !           937:                    win, hwwin, r1, r2, r3));
        !           938:        }
        !           939: #endif
        !           940: }
        !           941:
        !           942: /* XXX needs work */
        !           943: int
        !           944: tcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
        !           945:        pcmcia_chipset_handle_t pch;
        !           946:        int kind;
        !           947:        bus_addr_t card_addr;
        !           948:        bus_size_t size;
        !           949:        struct pcmcia_mem_handle *pcmhp;
        !           950:        bus_size_t *offsetp;
        !           951:        int *windowp;
        !           952: {
        !           953:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !           954:        bus_addr_t busaddr;
        !           955:        long card_offset;
        !           956:        int i, win;
        !           957:
        !           958:        win = -1;
        !           959:        for (i = 0; i < h->memwins; i++) {
        !           960:                if ((h->memalloc & (1 << i)) == 0) {
        !           961:                        win = i;
        !           962:                        h->memalloc |= (1 << i);
        !           963:                        break;
        !           964:                }
        !           965:        }
        !           966:
        !           967:        if (win == -1)
        !           968:                return (1);
        !           969:
        !           970:        *windowp = win;
        !           971:
        !           972:        /* XXX this is pretty gross */
        !           973:
        !           974:        if (h->sc->memt != pcmhp->memt)
        !           975:                panic("tcic_chip_mem_map memt is bogus");
        !           976:
        !           977:        busaddr = pcmhp->addr;
        !           978:
        !           979:        /*
        !           980:         * compute the address offset to the pcmcia address space for the
        !           981:         * tcic.  this is intentionally signed.  The masks and shifts below
        !           982:         * will cause TRT to happen in the tcic registers.  Deal with making
        !           983:         * sure the address is aligned, and return the alignment offset.
        !           984:         */
        !           985:
        !           986:        *offsetp = card_addr % TCIC_MEM_ALIGN;
        !           987:        card_addr -= *offsetp;
        !           988:
        !           989:        DPRINTF(("tcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
        !           990:            "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
        !           991:            (u_long) card_addr));
        !           992:
        !           993:        /* XXX we can't use size. -chb */
        !           994:        /*
        !           995:         * include the offset in the size, and decrement size by one, since
        !           996:         * the hw wants start/stop
        !           997:         */
        !           998:        size += *offsetp - 1;
        !           999:
        !          1000:        card_offset = (((long) card_addr) - ((long) busaddr));
        !          1001:
        !          1002:        DPRINTF(("tcic_chip_mem_map window %d card_offset 0x%lx\n",
        !          1003:            win, (u_long)card_offset));
        !          1004:
        !          1005:        h->mem[win].addr = busaddr;
        !          1006:        h->mem[win].size = size;
        !          1007:        h->mem[win].size2 = tcic_log2((u_int)pcmhp->realsize) - TCIC_MEM_SHIFT;
        !          1008:        h->mem[win].offset = card_offset;
        !          1009:        h->mem[win].kind = kind;
        !          1010:
        !          1011:        tcic_chip_do_mem_map(h, win);
        !          1012:
        !          1013:        return (0);
        !          1014: }
        !          1015:
        !          1016: void
        !          1017: tcic_chip_mem_unmap(pch, window)
        !          1018:        pcmcia_chipset_handle_t pch;
        !          1019:        int window;
        !          1020: {
        !          1021:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !          1022:        int reg, hwwin;
        !          1023:
        !          1024:        if (window >= h->memwins)
        !          1025:                panic("tcic_chip_mem_unmap: window out of range");
        !          1026:
        !          1027:        hwwin = (window << 1) + h->sock;
        !          1028:        reg = tcic_read_ind_2(h, TCIC_WR_MCTL_N(hwwin));
        !          1029:        reg &= ~TCIC_MCTL_ENA;
        !          1030:        tcic_write_ind_2(h, TCIC_WR_MCTL_N(hwwin), reg);
        !          1031:
        !          1032:        h->memalloc &= ~(1 << window);
        !          1033: }
        !          1034:
        !          1035: int
        !          1036: tcic_chip_io_alloc(pch, start, size, align, pcihp)
        !          1037:        pcmcia_chipset_handle_t pch;
        !          1038:        bus_addr_t start;
        !          1039:        bus_size_t size;
        !          1040:        bus_size_t align;
        !          1041:        struct pcmcia_io_handle *pcihp;
        !          1042: {
        !          1043:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !          1044:        bus_space_tag_t iot;
        !          1045:        bus_space_handle_t ioh;
        !          1046:        bus_addr_t ioaddr;
        !          1047:        int size2, flags = 0;
        !          1048:
        !          1049:        /*
        !          1050:         * Allocate some arbitrary I/O space.
        !          1051:         */
        !          1052:
        !          1053:        DPRINTF(("tcic_chip_io_alloc req 0x%lx %ld %ld\n",
        !          1054:            (u_long) start, (u_long) size, (u_long) align));
        !          1055:        /*
        !          1056:         * The TCIC can map I/O space only in sizes that are
        !          1057:         * powers of two, aligned at the natural boundary for the size.
        !          1058:         */
        !          1059:        size2 = tcic_log2((u_int)size);
        !          1060:        if ((1 << size2) < size)
        !          1061:                size2++;
        !          1062:        /* can't allocate that much anyway */
        !          1063:        if (size2 > 16) /* XXX 64K -chb */
        !          1064:                return 1;
        !          1065:        if (align) {
        !          1066:                if ((1 << size2) != align)
        !          1067:                        return 1;       /* not suitably  aligned */
        !          1068:        } else {
        !          1069:                align = 1 << size2;     /* no alignment given, make it natural */
        !          1070:        }
        !          1071:        if (start & (align - 1))
        !          1072:                return 1;       /* not suitably aligned */
        !          1073:
        !          1074:        iot = h->sc->iot;
        !          1075:
        !          1076:        if (start) {
        !          1077:                ioaddr = start;
        !          1078:                if (bus_space_map(iot, start, size, 0, &ioh))
        !          1079:                        return (1);
        !          1080:                DPRINTF(("tcic_chip_io_alloc map port %lx+%lx\n",
        !          1081:                    (u_long) ioaddr, (u_long) size));
        !          1082:        } else {
        !          1083:                flags |= PCMCIA_IO_ALLOCATED;
        !          1084:                if (bus_space_alloc(iot, h->sc->iobase,
        !          1085:                    h->sc->iobase + h->sc->iosize, size, align, 0, 0,
        !          1086:                    &ioaddr, &ioh))
        !          1087:                        return (1);
        !          1088:                DPRINTF(("tcic_chip_io_alloc alloc port %lx+%lx\n",
        !          1089:                    (u_long) ioaddr, (u_long) size));
        !          1090:        }
        !          1091:
        !          1092:        pcihp->iot = iot;
        !          1093:        pcihp->ioh = ioh;
        !          1094:        pcihp->addr = ioaddr;
        !          1095:        pcihp->size = size;
        !          1096:        pcihp->flags = flags;
        !          1097:
        !          1098:        return (0);
        !          1099: }
        !          1100:
        !          1101: void
        !          1102: tcic_chip_io_free(pch, pcihp)
        !          1103:        pcmcia_chipset_handle_t pch;
        !          1104:        struct pcmcia_io_handle *pcihp;
        !          1105: {
        !          1106:        bus_space_tag_t iot = pcihp->iot;
        !          1107:        bus_space_handle_t ioh = pcihp->ioh;
        !          1108:        bus_size_t size = pcihp->size;
        !          1109:
        !          1110:        if (pcihp->flags & PCMCIA_IO_ALLOCATED)
        !          1111:                bus_space_free(iot, ioh, size);
        !          1112:        else
        !          1113:                bus_space_unmap(iot, ioh, size);
        !          1114: }
        !          1115:
        !          1116: static int tcic_iowidth_map[] =
        !          1117:     { TCIC_ICTL_AUTOSZ, TCIC_ICTL_B8, TCIC_ICTL_B16 };
        !          1118:
        !          1119: void
        !          1120: tcic_chip_do_io_map(h, win)
        !          1121:        struct tcic_handle *h;
        !          1122:        int win;
        !          1123: {
        !          1124:        int reg, size2, iotiny, wbase, hwwin, wscnt;
        !          1125:
        !          1126:        DPRINTF(("tcic_chip_do_io_map win %d addr %lx size %lx width %d\n",
        !          1127:            win, (long) h->io[win].addr, (long) h->io[win].size,
        !          1128:            h->io[win].width * 8));
        !          1129:
        !          1130:        /*
        !          1131:         * the even windows are used for socket 0,
        !          1132:         * the odd ones for socket 1.
        !          1133:         */
        !          1134:        hwwin = (win << 1) + h->sock;
        !          1135:
        !          1136:        /* set the WR_BASE register */
        !          1137:        /* XXX what if size isn't power of 2? -chb */
        !          1138:        size2 = tcic_log2((u_int)h->io[win].size);
        !          1139:        DPRINTF(("tcic_chip_do_io_map win %d size2 %d\n", win, size2));
        !          1140:        if (size2 < 1) {
        !          1141:                iotiny = TCIC_ICTL_TINY;
        !          1142:                wbase = h->io[win].addr;
        !          1143:        } else {
        !          1144:                iotiny = 0;
        !          1145:                /* XXX we should do better -chb */
        !          1146:                wbase = h->io[win].addr | (1 << (size2 - 1));
        !          1147:        }
        !          1148:        tcic_write_ind_2(h, TCIC_WR_IBASE_N(hwwin), wbase);
        !          1149:
        !          1150:        /* set the WR_ICTL register */
        !          1151:        reg = TCIC_ICTL_ENA | TCIC_ICTL_QUIET;
        !          1152:        reg |= (h->sock << TCIC_ICTL_SS_SHIFT) & TCIC_ICTL_SS_MASK;
        !          1153:        reg |= iotiny | tcic_iowidth_map[h->io[win].width];
        !          1154:        if (h->sc->chipid != TCIC_CHIPID_DB86082_1)
        !          1155:                reg |= TCIC_ICTL_PASS16;
        !          1156: #ifdef notyet  /* XXX must get speed from CIS somehow. -chb */
        !          1157:        wscnt = tcic_ns2wscnt(h->io[win].speed);
        !          1158: #else
        !          1159:        wscnt = tcic_ns2wscnt(tcic_io_speed);   /* linux uses 0 as default */
        !          1160: #endif
        !          1161:        reg |= wscnt & TCIC_ICTL_WSCNT_MASK;
        !          1162:        tcic_write_ind_2(h, TCIC_WR_ICTL_N(hwwin), reg);
        !          1163:
        !          1164: #ifdef TCICDEBUG
        !          1165:        {
        !          1166:                int r1, r2;
        !          1167:
        !          1168:                r1 = tcic_read_ind_2(h, TCIC_WR_IBASE_N(hwwin));
        !          1169:                r2 = tcic_read_ind_2(h, TCIC_WR_ICTL_N(hwwin));
        !          1170:
        !          1171:                DPRINTF(("tcic_chip_do_io_map window %d(%d): %04x %04x\n",
        !          1172:                    win, hwwin, r1, r2));
        !          1173:        }
        !          1174: #endif
        !          1175: }
        !          1176:
        !          1177: int
        !          1178: tcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
        !          1179:        pcmcia_chipset_handle_t pch;
        !          1180:        int width;
        !          1181:        bus_addr_t offset;
        !          1182:        bus_size_t size;
        !          1183:        struct pcmcia_io_handle *pcihp;
        !          1184:        int *windowp;
        !          1185: {
        !          1186:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !          1187:        bus_addr_t ioaddr = pcihp->addr + offset;
        !          1188:        int i, win;
        !          1189: #ifdef TCICDEBUG
        !          1190:        static char *width_names[] = { "auto", "io8", "io16" };
        !          1191: #endif
        !          1192:
        !          1193:        /* XXX Sanity check offset/size. */
        !          1194:
        !          1195:        win = -1;
        !          1196:        for (i = 0; i < TCIC_IO_WINS; i++) {
        !          1197:                if ((h->ioalloc & (1 << i)) == 0) {
        !          1198:                        win = i;
        !          1199:                        h->ioalloc |= (1 << i);
        !          1200:                        break;
        !          1201:                }
        !          1202:        }
        !          1203:
        !          1204:        if (win == -1)
        !          1205:                return (1);
        !          1206:
        !          1207:        *windowp = win;
        !          1208:
        !          1209:        /* XXX this is pretty gross */
        !          1210:
        !          1211:        if (h->sc->iot != pcihp->iot)
        !          1212:                panic("tcic_chip_io_map iot is bogus");
        !          1213:
        !          1214:        DPRINTF(("tcic_chip_io_map window %d %s port %lx+%lx\n",
        !          1215:                 win, width_names[width], (u_long) ioaddr, (u_long) size));
        !          1216:
        !          1217:        /* XXX wtf is this doing here? */
        !          1218:
        !          1219:        printf(" port 0x%lx", (u_long) ioaddr);
        !          1220:        if (size > 1)
        !          1221:                printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
        !          1222:
        !          1223:        h->io[win].addr = ioaddr;
        !          1224:        h->io[win].size = size;
        !          1225:        h->io[win].width = width;
        !          1226:
        !          1227:        tcic_chip_do_io_map(h, win);
        !          1228:
        !          1229:        return (0);
        !          1230: }
        !          1231:
        !          1232: void
        !          1233: tcic_chip_io_unmap(pch, window)
        !          1234:        pcmcia_chipset_handle_t pch;
        !          1235:        int window;
        !          1236: {
        !          1237:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !          1238:        int reg, hwwin;
        !          1239:
        !          1240:        if (window >= TCIC_IO_WINS)
        !          1241:                panic("tcic_chip_io_unmap: window out of range");
        !          1242:
        !          1243:        hwwin = (window << 1) + h->sock;
        !          1244:        reg = tcic_read_ind_2(h, TCIC_WR_ICTL_N(hwwin));
        !          1245:        reg &= ~TCIC_ICTL_ENA;
        !          1246:        tcic_write_ind_2(h, TCIC_WR_ICTL_N(hwwin), reg);
        !          1247:
        !          1248:        h->ioalloc &= ~(1 << window);
        !          1249: }
        !          1250:
        !          1251: void
        !          1252: tcic_chip_socket_enable(pch)
        !          1253:        pcmcia_chipset_handle_t pch;
        !          1254: {
        !          1255:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !          1256:        int cardtype, reg, win;
        !          1257:
        !          1258:        tcic_sel_sock(h);
        !          1259:
        !          1260:        /*
        !          1261:         * power down the socket to reset it.
        !          1262:         * put card reset into high-z, put chip outputs to card into high-z
        !          1263:         */
        !          1264:
        !          1265:        tcic_write_1(h, TCIC_R_PWR, 0);
        !          1266:        reg = tcic_read_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK);
        !          1267:        reg |= TCIC_ILOCK_CWAIT;
        !          1268:        reg &= ~(TCIC_ILOCK_CRESET|TCIC_ILOCK_CRESENA);
        !          1269:        tcic_write_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK, reg);
        !          1270:        tcic_write_1(h, TCIC_R_SCTRL, 0);       /* clear TCIC_SCTRL_ENA */
        !          1271:
        !          1272:        /* power up the socket */
        !          1273:
        !          1274:        /* turn on VCC, turn of VPP */
        !          1275:        reg = TCIC_PWR_VCC_N(h->sock) | TCIC_PWR_VPP_N(h->sock) | h->sc->pwrena;
        !          1276:        if (h->sc->pwrena)              /* this is a '84 type chip */
        !          1277:                reg |= TCIC_PWR_VCC5V;
        !          1278:        tcic_write_1(h, TCIC_R_PWR, reg);
        !          1279:        delay(10000);
        !          1280:
        !          1281:        /* enable reset and wiggle it to reset the card */
        !          1282:        reg = tcic_read_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK);
        !          1283:        reg |= TCIC_ILOCK_CRESENA;
        !          1284:        tcic_write_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK, reg);
        !          1285:        /* XXX need bus_space_barrier here */
        !          1286:        reg |= TCIC_ILOCK_CRESET;
        !          1287:        tcic_write_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK, reg);
        !          1288:        /* enable card signals */
        !          1289:        tcic_write_1(h, TCIC_R_SCTRL, TCIC_SCTRL_ENA);
        !          1290:        delay(10);      /* wait 10 us */
        !          1291:
        !          1292:        /* clear the reset flag */
        !          1293:        reg = tcic_read_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK);
        !          1294:        reg &= ~(TCIC_ILOCK_CRESET);
        !          1295:        tcic_write_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK, reg);
        !          1296:
        !          1297:        /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
        !          1298:        delay(20000);
        !          1299:
        !          1300:        /* wait for the chip to finish initializing */
        !          1301:        tcic_wait_ready(h);
        !          1302:
        !          1303:        /* WWW */
        !          1304:        /* zero out the address windows */
        !          1305:
        !          1306:        /* writing to WR_MBASE_N disables the window */
        !          1307:        for (win = 0; win < h->memwins; win++) {
        !          1308:                tcic_write_ind_2(h, TCIC_WR_MBASE_N((win<<1)+h->sock), 0);
        !          1309:        }
        !          1310:        /* writing to WR_IBASE_N disables the window */
        !          1311:        for (win = 0; win < TCIC_IO_WINS; win++) {
        !          1312:                tcic_write_ind_2(h, TCIC_WR_IBASE_N((win<<1)+h->sock), 0);
        !          1313:        }
        !          1314:
        !          1315:        /* set the card type */
        !          1316:
        !          1317:        cardtype = pcmcia_card_gettype(h->pcmcia);
        !          1318:
        !          1319: #if 0
        !          1320:        reg = tcic_read_ind_2(h, TCIC_IR_SCF1_N(h->sock));
        !          1321:        reg &= ~TCIC_SCF1_IRQ_MASK;
        !          1322: #else
        !          1323:        reg = 0;
        !          1324: #endif
        !          1325:        reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
        !          1326:                TCIC_SCF1_IOSTS : 0);
        !          1327:        reg |= tcic_irqmap[h->ih_irq];          /* enable interrupts */
        !          1328:        reg &= ~TCIC_SCF1_IRQOD;
        !          1329:        tcic_write_ind_2(h, TCIC_IR_SCF1_N(h->sock), reg);
        !          1330:
        !          1331:        DPRINTF(("%s: tcic_chip_socket_enable %d cardtype %s 0x%02x\n",
        !          1332:            h->sc->dev.dv_xname, h->sock,
        !          1333:            ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg));
        !          1334:
        !          1335:        /* reinstall all the memory and io mappings */
        !          1336:
        !          1337:        for (win = 0; win < h->memwins; win++)
        !          1338:                if (h->memalloc & (1 << win))
        !          1339:                        tcic_chip_do_mem_map(h, win);
        !          1340:
        !          1341:        for (win = 0; win < TCIC_IO_WINS; win++)
        !          1342:                if (h->ioalloc & (1 << win))
        !          1343:                        tcic_chip_do_io_map(h, win);
        !          1344: }
        !          1345:
        !          1346: void
        !          1347: tcic_chip_socket_disable(pch)
        !          1348:        pcmcia_chipset_handle_t pch;
        !          1349: {
        !          1350:        struct tcic_handle *h = (struct tcic_handle *) pch;
        !          1351:        int val;
        !          1352:
        !          1353:        DPRINTF(("tcic_chip_socket_disable\n"));
        !          1354:
        !          1355:        tcic_sel_sock(h);
        !          1356:
        !          1357:        /* disable interrupts */
        !          1358:        val = tcic_read_ind_2(h, TCIC_IR_SCF1_N(h->sock));
        !          1359:        val &= TCIC_SCF1_IRQ_MASK;
        !          1360:        tcic_write_ind_2(h, TCIC_IR_SCF1_N(h->sock), val);
        !          1361:
        !          1362:        /* disable the output signals */
        !          1363:        tcic_write_1(h, TCIC_R_SCTRL, 0);
        !          1364:        val = tcic_read_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK);
        !          1365:        val &= ~TCIC_ILOCK_CRESENA;
        !          1366:        tcic_write_aux_2(h->sc->iot, h->sc->ioh, TCIC_AR_ILOCK, val);
        !          1367:
        !          1368:        /* power down the socket */
        !          1369:        tcic_write_1(h, TCIC_R_PWR, 0);
        !          1370: }
        !          1371:
        !          1372: /*
        !          1373:  * XXX The following is Linux driver but doesn't match the table
        !          1374:  * in the manual.
        !          1375:  */
        !          1376: int
        !          1377: tcic_ns2wscnt(ns)
        !          1378:        int ns;
        !          1379: {
        !          1380:        if (ns < 14) {
        !          1381:                return 0;
        !          1382:        } else {
        !          1383:                return (2*(ns-14))/70;  /* XXX assumes 14.31818 MHz clock. */
        !          1384:        }
        !          1385: }
        !          1386:
        !          1387: int
        !          1388: tcic_log2(val)
        !          1389:        u_int val;
        !          1390: {
        !          1391:        int i, l2;
        !          1392:
        !          1393:        l2 = i = 0;
        !          1394:        while (val) {
        !          1395:                if (val & 1)
        !          1396:                        l2 = i;
        !          1397:                i++;
        !          1398:                val >>= 1;
        !          1399:        }
        !          1400:        return l2;
        !          1401: }

CVSweb