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

Annotation of sys/dev/pci/pccbb.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: pccbb.c,v 1.47 2006/10/12 16:35:51 grange Exp $       */
        !             2: /*     $NetBSD: pccbb.c,v 1.96 2004/03/28 09:49:31 nakayama Exp $      */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1998, 1999 and 2000
        !             6:  *      HAYAKAWA Koichi.  All rights reserved.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by HAYAKAWA Koichi.
        !            19:  * 4. The name of the author may not be used to endorse or promote products
        !            20:  *    derived from this software without specific prior written permission.
        !            21:  *
        !            22:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            23:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            24:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            25:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            26:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            27:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            28:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            29:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            30:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            31:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            32:  */
        !            33:
        !            34: /*
        !            35: #define CBB_DEBUG
        !            36: #define SHOW_REGS
        !            37: #define PCCBB_PCMCIA_POLL
        !            38: */
        !            39:
        !            40: /*
        !            41: #define CB_PCMCIA_POLL
        !            42: #define CB_PCMCIA_POLL_ONLY
        !            43: #define LEVEL2
        !            44: */
        !            45:
        !            46: #include <sys/types.h>
        !            47: #include <sys/param.h>
        !            48: #include <sys/systm.h>
        !            49: #include <sys/kernel.h>
        !            50: #include <sys/errno.h>
        !            51: #include <sys/evcount.h>
        !            52: #include <sys/ioctl.h>
        !            53: #include <sys/syslog.h>
        !            54: #include <sys/device.h>
        !            55: #include <sys/malloc.h>
        !            56:
        !            57: #include <machine/intr.h>
        !            58: #include <machine/bus.h>
        !            59:
        !            60: #include <dev/pci/pcivar.h>
        !            61: #include <dev/pci/pcireg.h>
        !            62: #include <dev/pci/pcidevs.h>
        !            63:
        !            64: #include <dev/pci/pccbbreg.h>
        !            65:
        !            66: #include <dev/cardbus/cardslotvar.h>
        !            67:
        !            68: #include <dev/cardbus/cardbusvar.h>
        !            69:
        !            70: #include <dev/pcmcia/pcmciareg.h>
        !            71: #include <dev/pcmcia/pcmciavar.h>
        !            72:
        !            73: #include <dev/ic/i82365reg.h>
        !            74: #include <dev/ic/i82365var.h>
        !            75: #include <dev/pci/pccbbvar.h>
        !            76:
        !            77: #ifndef __NetBSD_Version__
        !            78: struct cfdriver cbb_cd = {
        !            79:        NULL, "cbb", DV_DULL
        !            80: };
        !            81: #endif
        !            82:
        !            83: #if defined CBB_DEBUG
        !            84: #define DPRINTF(x) printf x
        !            85: #else
        !            86: #define DPRINTF(x)
        !            87: #endif
        !            88:
        !            89: int    pcicbbmatch(struct device *, void *, void *);
        !            90: void   pccbbattach(struct device *, struct device *, void *);
        !            91: int    pccbbintr(void *);
        !            92: void   pccbb_shutdown(void *);
        !            93: void   pci113x_insert(void *);
        !            94: int    pccbbintr_function(struct pccbb_softc *);
        !            95:
        !            96: int    pccbb_detect_card(struct pccbb_softc *);
        !            97:
        !            98: void   pccbb_pcmcia_write(struct pcic_handle *, int, int);
        !            99: u_int8_t pccbb_pcmcia_read(struct pcic_handle *, int);
        !           100: #define Pcic_read(ph, reg) ((ph)->ph_read((ph), (reg)))
        !           101: #define Pcic_write(ph, reg, val) ((ph)->ph_write((ph), (reg), (val)))
        !           102:
        !           103: int    cb_reset(struct pccbb_softc *);
        !           104: int    cb_detect_voltage(struct pccbb_softc *);
        !           105: int    cbbprint(void *, const char *);
        !           106:
        !           107: int    cb_chipset(u_int32_t, int *);
        !           108: void   pccbb_pcmcia_attach_setup(struct pccbb_softc *,
        !           109:     struct pcmciabus_attach_args *);
        !           110: #if 0
        !           111: void   pccbb_pcmcia_attach_card(struct pcic_handle *);
        !           112: void   pccbb_pcmcia_detach_card(struct pcic_handle *, int);
        !           113: void   pccbb_pcmcia_deactivate_card(struct pcic_handle *);
        !           114: #endif
        !           115:
        !           116: int    pccbb_ctrl(cardbus_chipset_tag_t, int);
        !           117: int    pccbb_power(cardbus_chipset_tag_t, int);
        !           118: int    pccbb_cardenable(struct pccbb_softc * sc, int function);
        !           119: void   *pccbb_intr_establish(struct pccbb_softc *, int irq, int level,
        !           120:     int (*ih) (void *), void *sc, const char *);
        !           121: void   pccbb_intr_disestablish(struct pccbb_softc *, void *ih);
        !           122:
        !           123: void   *pccbb_cb_intr_establish(cardbus_chipset_tag_t, int irq, int level,
        !           124:     int (*ih) (void *), void *sc, const char *);
        !           125: void   pccbb_cb_intr_disestablish(cardbus_chipset_tag_t ct, void *ih);
        !           126:
        !           127: cardbustag_t pccbb_make_tag(cardbus_chipset_tag_t, int, int, int);
        !           128: void   pccbb_free_tag(cardbus_chipset_tag_t, cardbustag_t);
        !           129: cardbusreg_t pccbb_conf_read(cardbus_chipset_tag_t, cardbustag_t, int);
        !           130: void   pccbb_conf_write(cardbus_chipset_tag_t, cardbustag_t, int,
        !           131:     cardbusreg_t);
        !           132: void   pccbb_chipinit(struct pccbb_softc *);
        !           133:
        !           134: int    pccbb_pcmcia_mem_alloc(pcmcia_chipset_handle_t, bus_size_t,
        !           135:     struct pcmcia_mem_handle *);
        !           136: void   pccbb_pcmcia_mem_free(pcmcia_chipset_handle_t,
        !           137:     struct pcmcia_mem_handle *);
        !           138: int    pccbb_pcmcia_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t,
        !           139:     bus_size_t, struct pcmcia_mem_handle *, bus_size_t *, int *);
        !           140: void   pccbb_pcmcia_mem_unmap(pcmcia_chipset_handle_t, int);
        !           141: int    pccbb_pcmcia_io_alloc(pcmcia_chipset_handle_t, bus_addr_t,
        !           142:     bus_size_t, bus_size_t, struct pcmcia_io_handle *);
        !           143: void   pccbb_pcmcia_io_free(pcmcia_chipset_handle_t,
        !           144:     struct pcmcia_io_handle *);
        !           145: int    pccbb_pcmcia_io_map(pcmcia_chipset_handle_t, int, bus_addr_t,
        !           146:     bus_size_t, struct pcmcia_io_handle *, int *);
        !           147: void   pccbb_pcmcia_io_unmap(pcmcia_chipset_handle_t, int);
        !           148: void   *pccbb_pcmcia_intr_establish(pcmcia_chipset_handle_t,
        !           149:     struct pcmcia_function *, int, int (*)(void *), void *, char *);
        !           150: void   pccbb_pcmcia_intr_disestablish(pcmcia_chipset_handle_t, void *);
        !           151: const char *pccbb_pcmcia_intr_string(pcmcia_chipset_handle_t, void *);
        !           152: void   pccbb_pcmcia_socket_enable(pcmcia_chipset_handle_t);
        !           153: void   pccbb_pcmcia_socket_disable(pcmcia_chipset_handle_t);
        !           154: int    pccbb_pcmcia_card_detect(pcmcia_chipset_handle_t pch);
        !           155:
        !           156: void   pccbb_pcmcia_do_io_map(struct pcic_handle *, int);
        !           157: void   pccbb_pcmcia_wait_ready(struct pcic_handle *);
        !           158: void   pccbb_pcmcia_do_mem_map(struct pcic_handle *, int);
        !           159: void   pccbb_powerhook(int, void *);
        !           160:
        !           161: /* bus-space allocation and deallocation functions */
        !           162: int    pccbb_rbus_cb_space_alloc(cardbus_chipset_tag_t, rbus_tag_t,
        !           163:     bus_addr_t addr, bus_size_t size, bus_addr_t mask, bus_size_t align,
        !           164:     int flags, bus_addr_t * addrp, bus_space_handle_t * bshp);
        !           165: int    pccbb_rbus_cb_space_free(cardbus_chipset_tag_t, rbus_tag_t,
        !           166:     bus_space_handle_t, bus_size_t);
        !           167:
        !           168: int    pccbb_open_win(struct pccbb_softc *, bus_space_tag_t,
        !           169:     bus_addr_t, bus_size_t, bus_space_handle_t, int flags);
        !           170: int    pccbb_close_win(struct pccbb_softc *, bus_space_tag_t,
        !           171:     bus_space_handle_t, bus_size_t);
        !           172: int    pccbb_winlist_insert(struct pccbb_win_chain_head *, bus_addr_t,
        !           173:     bus_size_t, bus_space_handle_t, int);
        !           174: int    pccbb_winlist_delete(struct pccbb_win_chain_head *,
        !           175:     bus_space_handle_t, bus_size_t);
        !           176: void   pccbb_winset(bus_addr_t align, struct pccbb_softc *,
        !           177:     bus_space_tag_t);
        !           178: void   pccbb_winlist_show(struct pccbb_win_chain *);
        !           179:
        !           180: /* for config_defer */
        !           181: void   pccbb_pci_callback(struct device *);
        !           182:
        !           183: #if defined SHOW_REGS
        !           184: void   cb_show_regs(pci_chipset_tag_t, pcitag_t, bus_space_tag_t,
        !           185:     bus_space_handle_t memh);
        !           186: #endif
        !           187:
        !           188: struct cfattach cbb_pci_ca = {
        !           189:        sizeof(struct pccbb_softc), pcicbbmatch, pccbbattach
        !           190: };
        !           191:
        !           192: static struct pcmcia_chip_functions pccbb_pcmcia_funcs = {
        !           193:        pccbb_pcmcia_mem_alloc,
        !           194:        pccbb_pcmcia_mem_free,
        !           195:        pccbb_pcmcia_mem_map,
        !           196:        pccbb_pcmcia_mem_unmap,
        !           197:        pccbb_pcmcia_io_alloc,
        !           198:        pccbb_pcmcia_io_free,
        !           199:        pccbb_pcmcia_io_map,
        !           200:        pccbb_pcmcia_io_unmap,
        !           201:        pccbb_pcmcia_intr_establish,
        !           202:        pccbb_pcmcia_intr_disestablish,
        !           203:        pccbb_pcmcia_intr_string,
        !           204:        pccbb_pcmcia_socket_enable,
        !           205:        pccbb_pcmcia_socket_disable,
        !           206:        pccbb_pcmcia_card_detect
        !           207: };
        !           208:
        !           209: static struct cardbus_functions pccbb_funcs = {
        !           210:        pccbb_rbus_cb_space_alloc,
        !           211:        pccbb_rbus_cb_space_free,
        !           212:        pccbb_cb_intr_establish,
        !           213:        pccbb_cb_intr_disestablish,
        !           214:        pccbb_ctrl,
        !           215:        pccbb_power,
        !           216:        pccbb_make_tag,
        !           217:        pccbb_free_tag,
        !           218:        pccbb_conf_read,
        !           219:        pccbb_conf_write,
        !           220: };
        !           221:
        !           222: int
        !           223: pcicbbmatch(parent, match, aux)
        !           224:        struct device *parent;
        !           225:        void *match;
        !           226:        void *aux;
        !           227: {
        !           228:        struct pci_attach_args *pa = (struct pci_attach_args *)aux;
        !           229:
        !           230:        if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
        !           231:            PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_CARDBUS &&
        !           232:            PCI_INTERFACE(pa->pa_class) == 0) {
        !           233:                return 1;
        !           234:        }
        !           235:
        !           236:        return 0;
        !           237: }
        !           238:
        !           239: #define MAKEID(vendor, prod) (((vendor) << PCI_VENDOR_SHIFT) \
        !           240:                                | ((prod) << PCI_PRODUCT_SHIFT))
        !           241:
        !           242: struct yenta_chipinfo {
        !           243:        pcireg_t yc_id;                /* vendor tag | product tag */
        !           244:        int yc_chiptype;
        !           245:        int yc_flags;
        !           246: } yc_chipsets[] = {
        !           247:        /* Texas Instruments chips */
        !           248:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1130), CB_TI113X,
        !           249:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           250:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1131), CB_TI113X,
        !           251:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           252:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1250), CB_TI125X,
        !           253:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           254:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1220), CB_TI12XX,
        !           255:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           256:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1221), CB_TI12XX,
        !           257:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           258:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1225), CB_TI12XX,
        !           259:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           260:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251), CB_TI125X,
        !           261:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           262:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1251B), CB_TI125X,
        !           263:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           264:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1211), CB_TI12XX,
        !           265:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           266:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1410), CB_TI12XX,
        !           267:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           268:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1420), CB_TI12XX,
        !           269:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           270:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1450), CB_TI125X,
        !           271:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           272:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI1451), CB_TI12XX,
        !           273:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           274:        { MAKEID(PCI_VENDOR_TI, PCI_PRODUCT_TI_PCI7XX1), CB_TI12XX,
        !           275:            PCCBB_PCMCIA_IO_RELOC | PCCBB_PCMCIA_MEM_32},
        !           276:
        !           277:        /* Ricoh chips */
        !           278:        { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C475), CB_RX5C47X,
        !           279:            PCCBB_PCMCIA_MEM_32},
        !           280:        { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C476), CB_RX5C47X,
        !           281:            PCCBB_PCMCIA_MEM_32},
        !           282:        { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C477), CB_RX5C47X,
        !           283:            PCCBB_PCMCIA_MEM_32},
        !           284:        { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C478), CB_RX5C47X,
        !           285:            PCCBB_PCMCIA_MEM_32},
        !           286:        { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C465), CB_RX5C46X,
        !           287:            PCCBB_PCMCIA_MEM_32},
        !           288:        { MAKEID(PCI_VENDOR_RICOH, PCI_PRODUCT_RICOH_RF5C466), CB_RX5C46X,
        !           289:            PCCBB_PCMCIA_MEM_32},
        !           290:
        !           291:        /* Toshiba products */
        !           292:        { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95),
        !           293:            CB_TOPIC95, PCCBB_PCMCIA_MEM_32},
        !           294:        { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC95B),
        !           295:            CB_TOPIC95B, PCCBB_PCMCIA_MEM_32},
        !           296:        { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC97),
        !           297:            CB_TOPIC97, PCCBB_PCMCIA_MEM_32},
        !           298:        { MAKEID(PCI_VENDOR_TOSHIBA2, PCI_PRODUCT_TOSHIBA2_ToPIC100),
        !           299:            CB_TOPIC97, PCCBB_PCMCIA_MEM_32},
        !           300:
        !           301:        /* Cirrus Logic products */
        !           302:        { MAKEID(PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6832),
        !           303:            CB_CIRRUS, PCCBB_PCMCIA_MEM_32},
        !           304:        { MAKEID(PCI_VENDOR_CIRRUS, PCI_PRODUCT_CIRRUS_CL_PD6833),
        !           305:            CB_CIRRUS, PCCBB_PCMCIA_MEM_32},
        !           306:
        !           307:        /* older O2Micro bridges */
        !           308:        { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6729),
        !           309:            CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
        !           310:        { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6730),
        !           311:            CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
        !           312:        { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6872), /* 68[71]2 */
        !           313:            CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
        !           314:        { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6832),
        !           315:            CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
        !           316:        { MAKEID(PCI_VENDOR_O2MICRO, PCI_PRODUCT_O2MICRO_OZ6836),
        !           317:            CB_OLDO2MICRO, PCCBB_PCMCIA_MEM_32},
        !           318:
        !           319:        /* sentinel, or Generic chip */
        !           320:        { 0 /* null id */ , CB_UNKNOWN, PCCBB_PCMCIA_MEM_32},
        !           321: };
        !           322:
        !           323: int
        !           324: cb_chipset(pci_id, flagp)
        !           325:        u_int32_t pci_id;
        !           326:        int *flagp;
        !           327: {
        !           328:        struct yenta_chipinfo *yc;
        !           329:
        !           330:        /* Loop over except the last default entry. */
        !           331:        for (yc = yc_chipsets; yc < yc_chipsets +
        !           332:            sizeof(yc_chipsets) / sizeof(yc_chipsets[0]) - 1; yc++)
        !           333:                if (pci_id == yc->yc_id)
        !           334:                        break;
        !           335:
        !           336:        if (flagp != NULL)
        !           337:                *flagp = yc->yc_flags;
        !           338:
        !           339:        return (yc->yc_chiptype);
        !           340: }
        !           341:
        !           342: void
        !           343: pccbb_shutdown(void *arg)
        !           344: {
        !           345:        struct pccbb_softc *sc = arg;
        !           346:        pcireg_t command;
        !           347:
        !           348:        DPRINTF(("%s: shutdown\n", sc->sc_dev.dv_xname));
        !           349:
        !           350:        /* turn off power */
        !           351:        pccbb_power((cardbus_chipset_tag_t)sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
        !           352:
        !           353:        bus_space_write_4(sc->sc_base_memt, sc->sc_base_memh, CB_SOCKET_MASK,
        !           354:            0);
        !           355:
        !           356:        command = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG);
        !           357:
        !           358:        command &= ~(PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
        !           359:            PCI_COMMAND_MASTER_ENABLE);
        !           360:        pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, command);
        !           361: }
        !           362:
        !           363: void
        !           364: pccbbattach(parent, self, aux)
        !           365:        struct device *parent;
        !           366:        struct device *self;
        !           367:        void *aux;
        !           368: {
        !           369:        struct pccbb_softc *sc = (void *)self;
        !           370:        struct pci_attach_args *pa = aux;
        !           371:        pci_chipset_tag_t pc = pa->pa_pc;
        !           372:        pcireg_t busreg, reg, sock_base;
        !           373:        pci_intr_handle_t ih;
        !           374:        const char *intrstr = NULL;
        !           375:        bus_addr_t sockbase;
        !           376:        int flags;
        !           377:
        !           378: #ifdef __HAVE_PCCBB_ATTACH_HOOK
        !           379:        pccbb_attach_hook(parent, self, pa);
        !           380: #endif
        !           381:
        !           382:        sc->sc_chipset = cb_chipset(pa->pa_id, &flags);
        !           383:
        !           384: #ifdef CBB_DEBUG
        !           385:        printf(" (chipflags %x)", flags);
        !           386: #endif
        !           387:
        !           388:        TAILQ_INIT(&sc->sc_memwindow);
        !           389:        TAILQ_INIT(&sc->sc_iowindow);
        !           390:
        !           391:        sc->sc_rbus_iot = rbus_pccbb_parent_io(self, pa);
        !           392:        sc->sc_rbus_memt = rbus_pccbb_parent_mem(self, pa);
        !           393:
        !           394:        sc->sc_flags &= ~CBB_MEMHMAPPED;
        !           395:
        !           396:        /*
        !           397:         * MAP socket registers and ExCA registers on memory-space
        !           398:         * When no valid address is set on socket base registers (on pci
        !           399:         * config space), get it not polite way.
        !           400:         */
        !           401:        sock_base = pci_conf_read(pc, pa->pa_tag, PCI_SOCKBASE);
        !           402:
        !           403:        if (PCI_MAPREG_MEM_ADDR(sock_base) >= 0x100000 &&
        !           404:            PCI_MAPREG_MEM_ADDR(sock_base) != 0xfffffff0) {
        !           405:                /* The address must be valid. */
        !           406:                if (pci_mapreg_map(pa, PCI_SOCKBASE, PCI_MAPREG_TYPE_MEM, 0,
        !           407:                    &sc->sc_base_memt, &sc->sc_base_memh, &sockbase, NULL, 0))
        !           408:                    {
        !           409:                        printf("%s: can't map socket base address 0x%x\n",
        !           410:                            sc->sc_dev.dv_xname, sock_base);
        !           411:                        /*
        !           412:                         * I think it's funny: socket base registers must be
        !           413:                         * mapped on memory space, but ...
        !           414:                         */
        !           415:                        if (pci_mapreg_map(pa, PCI_SOCKBASE,
        !           416:                            PCI_MAPREG_TYPE_IO, 0, &sc->sc_base_memt,
        !           417:                            &sc->sc_base_memh, &sockbase, NULL, 0)) {
        !           418:                                printf("%s: can't map socket base address"
        !           419:                                    " 0x%lx: io mode\n", sc->sc_dev.dv_xname,
        !           420:                                    sockbase);
        !           421:                                /* give up... allocate reg space via rbus. */
        !           422:                                pci_conf_write(pc, pa->pa_tag, PCI_SOCKBASE, 0);
        !           423:                        } else
        !           424:                                sc->sc_flags |= CBB_MEMHMAPPED;
        !           425:                } else {
        !           426:                        DPRINTF(("%s: socket base address 0x%lx\n",
        !           427:                            sc->sc_dev.dv_xname, sockbase));
        !           428:                        sc->sc_flags |= CBB_MEMHMAPPED;
        !           429:                }
        !           430:        }
        !           431:
        !           432:        sc->sc_mem_start = 0;          /* XXX */
        !           433:        sc->sc_mem_end = 0xffffffff;   /* XXX */
        !           434:
        !           435:        /*
        !           436:         * When bus number isn't set correctly, give up using 32-bit CardBus
        !           437:         * mode.
        !           438:         */
        !           439:        busreg = pci_conf_read(pc, pa->pa_tag, PCI_BUSNUM);
        !           440: #if notyet
        !           441:        if (((busreg >> 8) & 0xff) == 0) {
        !           442:                printf(": CardBus support disabled because of unconfigured bus number\n");
        !           443:                flags |= PCCBB_PCMCIA_16BITONLY;
        !           444:        }
        !           445: #endif
        !           446:
        !           447:        /* pccbb_machdep.c end */
        !           448:
        !           449: #if defined CBB_DEBUG
        !           450:        {
        !           451:                static char *intrname[5] = { "NON", "A", "B", "C", "D" };
        !           452:                printf(": intrpin %s, intrtag %d\n",
        !           453:                    intrname[pa->pa_intrpin], pa->pa_intrline);
        !           454:        }
        !           455: #endif
        !           456:
        !           457:        /* setup softc */
        !           458:        sc->sc_pc = pc;
        !           459:        sc->sc_iot = pa->pa_iot;
        !           460:        sc->sc_memt = pa->pa_memt;
        !           461:        sc->sc_dmat = pa->pa_dmat;
        !           462:        sc->sc_tag = pa->pa_tag;
        !           463:        sc->sc_function = pa->pa_function;
        !           464:        sc->sc_sockbase = sock_base;
        !           465:        sc->sc_busnum = busreg;
        !           466:        sc->sc_intrtag = pa->pa_intrtag;
        !           467:        sc->sc_intrpin = pa->pa_intrpin;
        !           468:
        !           469:        sc->sc_pcmcia_flags = flags;   /* set PCMCIA facility */
        !           470:
        !           471:        /* Map and establish the interrupt. */
        !           472:        if (pci_intr_map(pa, &ih)) {
        !           473:                printf(": couldn't map interrupt\n");
        !           474:                return;
        !           475:        }
        !           476:        intrstr = pci_intr_string(pc, ih);
        !           477:        /* must do this after intr is mapped and established */
        !           478:        sc->sc_intrline = pci_intr_line(ih);
        !           479:
        !           480:        /*
        !           481:         * XXX pccbbintr should be called under the priority lower
        !           482:         * than any other hard interrupts.
        !           483:         */
        !           484:        sc->sc_ih = pci_intr_establish(pc, ih, IPL_BIO, pccbbintr, sc,
        !           485:            sc->sc_dev.dv_xname);
        !           486:
        !           487:        if (sc->sc_ih == NULL) {
        !           488:                printf(": couldn't establish interrupt");
        !           489:                if (intrstr != NULL) {
        !           490:                        printf(" at %s", intrstr);
        !           491:                }
        !           492:                printf("\n");
        !           493:                return;
        !           494:        }
        !           495:        printf(": %s\n", intrstr);
        !           496:
        !           497:        shutdownhook_establish(pccbb_shutdown, sc);
        !           498:
        !           499:        /* Disable legacy register mapping. */
        !           500:        switch (sc->sc_chipset) {
        !           501:        case CB_RX5C46X:               /* fallthrough */
        !           502: #if 0
        !           503:        /* The RX5C47X-series requires writes to the PCI_LEGACY register. */
        !           504:        case CB_RX5C47X:
        !           505: #endif
        !           506:                /*
        !           507:                 * The legacy pcic io-port on Ricoh RX5C46X CardBus bridges
        !           508:                 * cannot be disabled by substituting 0 into PCI_LEGACY
        !           509:                 * register.  Ricoh CardBus bridges have special bits on Bridge
        !           510:                 * control reg (addr 0x3e on PCI config space).
        !           511:                 */
        !           512:                reg = pci_conf_read(pc, pa->pa_tag, PCI_BCR_INTR);
        !           513:                reg &= ~(CB_BCRI_RL_3E0_ENA | CB_BCRI_RL_3E2_ENA);
        !           514:                pci_conf_write(pc, pa->pa_tag, PCI_BCR_INTR, reg);
        !           515:                break;
        !           516:
        !           517:        default:
        !           518:                /* XXX I don't know proper way to kill legacy I/O. */
        !           519:                pci_conf_write(pc, pa->pa_tag, PCI_LEGACY, 0x0);
        !           520:                break;
        !           521:        }
        !           522:
        !           523:        timeout_set(&sc->sc_ins_tmo, pci113x_insert, sc);
        !           524:        config_defer(self, pccbb_pci_callback);
        !           525: }
        !           526:
        !           527: /*
        !           528:  * void pccbb_pci_callback(struct device *self)
        !           529:  *
        !           530:  *   The actual attach routine: get memory space for YENTA register
        !           531:  *   space, setup YENTA register and route interrupt.
        !           532:  *
        !           533:  *   This function should be deferred because this device may obtain
        !           534:  *   memory space dynamically.  This function must avoid obtaining
        !           535:  *   memory area which has already kept for another device.  Also,
        !           536:  *   this function MUST be done before ISA attach process because this
        !           537:  *   function kills pcic compatible port used by ISA pcic.
        !           538:  */
        !           539: void
        !           540: pccbb_pci_callback(self)
        !           541:        struct device *self;
        !           542: {
        !           543:        struct pccbb_softc *sc = (void *)self;
        !           544:        pci_chipset_tag_t pc = sc->sc_pc;
        !           545:        bus_space_tag_t base_memt;
        !           546:        bus_space_handle_t base_memh;
        !           547:        u_int32_t maskreg;
        !           548:        bus_addr_t sockbase;
        !           549:        struct cbslot_attach_args cba;
        !           550:        struct pcmciabus_attach_args paa;
        !           551:        struct cardslot_attach_args caa;
        !           552:        struct cardslot_softc *csc;
        !           553:
        !           554:        if (!(sc->sc_flags & CBB_MEMHMAPPED)) {
        !           555:                /* The socket registers aren't mapped correctly. */
        !           556:                if (rbus_space_alloc(sc->sc_rbus_memt, 0, 0x1000, 0x0fff,
        !           557:                    (sc->sc_chipset == CB_RX5C47X
        !           558:                    || sc->sc_chipset == CB_TI113X) ? 0x10000 : 0x1000,
        !           559:                    0, &sockbase, &sc->sc_base_memh)) {
        !           560:                        return;
        !           561:                }
        !           562:                sc->sc_base_memt = sc->sc_memt;
        !           563:                pci_conf_write(pc, sc->sc_tag, PCI_SOCKBASE, sockbase);
        !           564:                DPRINTF(("%s: CardBus register address 0x%lx -> 0x%x\n",
        !           565:                    sc->sc_dev.dv_xname, sockbase, pci_conf_read(pc, sc->sc_tag,
        !           566:                    PCI_SOCKBASE)));
        !           567:                sc->sc_flags |= CBB_MEMHMAPPED;
        !           568:        }
        !           569:
        !           570:        /* bus bridge initialization */
        !           571:        pccbb_chipinit(sc);
        !           572:
        !           573:        base_memt = sc->sc_base_memt;  /* socket regs memory tag */
        !           574:        base_memh = sc->sc_base_memh;  /* socket regs memory handle */
        !           575:
        !           576:        /* clear data structure for child device interrupt handlers */
        !           577:        sc->sc_pil = NULL;
        !           578:        sc->sc_pil_intr_enable = 1;
        !           579:
        !           580:        powerhook_establish(pccbb_powerhook, sc);
        !           581:
        !           582:        {
        !           583:                u_int32_t sockstat =
        !           584:                    bus_space_read_4(base_memt, base_memh, CB_SOCKET_STAT);
        !           585:                if (0 == (sockstat & CB_SOCKET_STAT_CD)) {
        !           586:                        sc->sc_flags |= CBB_CARDEXIST;
        !           587:                }
        !           588:        }
        !           589:
        !           590:        /*
        !           591:         * attach cardbus
        !           592:         */
        !           593:        if (!(sc->sc_pcmcia_flags & PCCBB_PCMCIA_16BITONLY)) {
        !           594:                pcireg_t busreg = pci_conf_read(pc, sc->sc_tag, PCI_BUSNUM);
        !           595:                pcireg_t bhlc = pci_conf_read(pc, sc->sc_tag, PCI_BHLC_REG);
        !           596:
        !           597:                /* initialize cbslot_attach */
        !           598:                cba.cba_busname = "cardbus";
        !           599:                cba.cba_iot = sc->sc_iot;
        !           600:                cba.cba_memt = sc->sc_memt;
        !           601:                cba.cba_dmat = sc->sc_dmat;
        !           602:                cba.cba_bus = (busreg >> 8) & 0x0ff;
        !           603:                cba.cba_cc = (void *)sc;
        !           604:                cba.cba_cf = &pccbb_funcs;
        !           605:                cba.cba_intrline = sc->sc_intrline;
        !           606:
        !           607:                cba.cba_rbus_iot = sc->sc_rbus_iot;
        !           608:                cba.cba_rbus_memt = sc->sc_rbus_memt;
        !           609:
        !           610:                cba.cba_cacheline = PCI_CACHELINE(bhlc);
        !           611:                cba.cba_lattimer = PCI_CB_LATENCY(busreg);
        !           612:
        !           613: #if defined CBB_DEBUG
        !           614:                printf("%s: cacheline 0x%x lattimer 0x%x\n",
        !           615:                    sc->sc_dev.dv_xname, cba.cba_cacheline, cba.cba_lattimer);
        !           616:                printf("%s: bhlc 0x%x lscp 0x%x\n", sc->sc_dev.dv_xname, bhlc,
        !           617:                    busreg);
        !           618: #endif
        !           619: #if defined SHOW_REGS
        !           620:                cb_show_regs(sc->sc_pc, sc->sc_tag, sc->sc_base_memt,
        !           621:                    sc->sc_base_memh);
        !           622: #endif
        !           623:        }
        !           624:
        !           625:        pccbb_pcmcia_attach_setup(sc, &paa);
        !           626:        caa.caa_cb_attach = NULL;
        !           627:        if (!(sc->sc_pcmcia_flags & PCCBB_PCMCIA_16BITONLY)) {
        !           628:                caa.caa_cb_attach = &cba;
        !           629:        }
        !           630:        caa.caa_16_attach = &paa;
        !           631:        caa.caa_ph = &sc->sc_pcmcia_h;
        !           632:
        !           633:        if (NULL != (csc = (void *)config_found(self, &caa, cbbprint))) {
        !           634:                DPRINTF(("pccbbattach: found cardslot\n"));
        !           635:                sc->sc_csc = csc;
        !           636:        }
        !           637:
        !           638:        sc->sc_ints_on = 1;
        !           639:
        !           640:        /* CSC Interrupt: Card detect interrupt on */
        !           641:        maskreg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK);
        !           642:        maskreg |= CB_SOCKET_MASK_CD;  /* Card detect intr is turned on. */
        !           643:        bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, maskreg);
        !           644:        /* reset interrupt */
        !           645:        bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT,
        !           646:            bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT));
        !           647:
        !           648:        return;
        !           649: }
        !           650:
        !           651: /*
        !           652:  * void pccbb_chipinit(struct pccbb_softc *sc)
        !           653:  *
        !           654:  *   This function initialize YENTA chip registers listed below:
        !           655:  *     1) PCI command reg,
        !           656:  *     2) PCI and CardBus latency timer,
        !           657:  *     3) route PCI interrupt,
        !           658:  *     4) close all memory and io windows.
        !           659:  */
        !           660: void
        !           661: pccbb_chipinit(sc)
        !           662:        struct pccbb_softc *sc;
        !           663: {
        !           664:        pci_chipset_tag_t pc = sc->sc_pc;
        !           665:        pcitag_t tag = sc->sc_tag;
        !           666:        pcireg_t reg;
        !           667:
        !           668:        /*
        !           669:         * Set PCI command reg.
        !           670:         * Some laptop's BIOSes (i.e. TICO) do not enable CardBus chip.
        !           671:         */
        !           672:        reg = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
        !           673:        /* I believe it is harmless. */
        !           674:        reg |= (PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
        !           675:            PCI_COMMAND_MASTER_ENABLE);
        !           676:        pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, reg);
        !           677:
        !           678:        /*
        !           679:         * Set CardBus latency timer.
        !           680:         */
        !           681:        reg = pci_conf_read(pc, tag, PCI_CB_LSCP_REG);
        !           682:        if (PCI_CB_LATENCY(reg) < 0x20) {
        !           683:                reg &= ~(PCI_CB_LATENCY_MASK << PCI_CB_LATENCY_SHIFT);
        !           684:                reg |= (0x20 << PCI_CB_LATENCY_SHIFT);
        !           685:                pci_conf_write(pc, tag, PCI_CB_LSCP_REG, reg);
        !           686:        }
        !           687:        DPRINTF(("CardBus latency timer 0x%x (%x)\n",
        !           688:            PCI_CB_LATENCY(reg), pci_conf_read(pc, tag, PCI_CB_LSCP_REG)));
        !           689:
        !           690:        /*
        !           691:         * Set PCI latency timer.
        !           692:         */
        !           693:        reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
        !           694:        if (PCI_LATTIMER(reg) < 0x10) {
        !           695:                reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
        !           696:                reg |= (0x10 << PCI_LATTIMER_SHIFT);
        !           697:                pci_conf_write(pc, tag, PCI_BHLC_REG, reg);
        !           698:        }
        !           699:        DPRINTF(("PCI latency timer 0x%x (%x)\n",
        !           700:            PCI_LATTIMER(reg), pci_conf_read(pc, tag, PCI_BHLC_REG)));
        !           701:
        !           702:        /* Route functional interrupts to PCI. */
        !           703:        reg = pci_conf_read(pc, tag, PCI_BCR_INTR);
        !           704:        reg |= CB_BCR_INTR_IREQ_ENABLE;         /* disable PCI Intr */
        !           705:        reg |= CB_BCR_WRITE_POST_ENABLE;        /* enable write post */
        !           706:        reg |= CB_BCR_RESET_ENABLE;             /* assert reset */
        !           707:        pci_conf_write(pc, tag, PCI_BCR_INTR, reg);
        !           708:
        !           709:        switch (sc->sc_chipset) {
        !           710:        case CB_TI113X:
        !           711:                reg = pci_conf_read(pc, tag, PCI_CBCTRL);
        !           712:                /* This bit is shared, but may read as 0 on some chips, so set
        !           713:                   it explicitly on both functions. */
        !           714:                reg |= PCI113X_CBCTRL_PCI_IRQ_ENA;
        !           715:                /* CSC intr enable */
        !           716:                reg |= PCI113X_CBCTRL_PCI_CSC;
        !           717:                /* functional intr prohibit | prohibit ISA routing */
        !           718:                reg &= ~(PCI113X_CBCTRL_PCI_INTR | PCI113X_CBCTRL_INT_MASK);
        !           719:                pci_conf_write(pc, tag, PCI_CBCTRL, reg);
        !           720:                break;
        !           721:
        !           722:        case CB_TI12XX:
        !           723:                /*
        !           724:                 * Some TI 12xx (and [14][45]xx) based pci cards
        !           725:                 * sometimes have issues with the MFUNC register not
        !           726:                 * being initialized due to a bad EEPROM on board.
        !           727:                 * Laptops that this matters on have this register
        !           728:                 * properly initialized.
        !           729:                 *
        !           730:                 * The TI125X parts have a different register.
        !           731:                 */
        !           732:                reg = pci_conf_read(pc, tag, PCI12XX_MFUNC);
        !           733:                if (reg == 0) {
        !           734:                        reg &= ~PCI12XX_MFUNC_PIN0;
        !           735:                        reg |= PCI12XX_MFUNC_PIN0_INTA;
        !           736:                        if ((pci_conf_read(pc, tag, PCI_SYSCTRL) &
        !           737:                             PCI12XX_SYSCTRL_INTRTIE) == 0) {
        !           738:                                reg &= ~PCI12XX_MFUNC_PIN1;
        !           739:                                reg |= PCI12XX_MFUNC_PIN1_INTB;
        !           740:                        }
        !           741:                        pci_conf_write(pc, tag, PCI12XX_MFUNC, reg);
        !           742:                }
        !           743:                /* FALLTHROUGH */
        !           744:
        !           745:        case CB_TI125X:
        !           746:                /*
        !           747:                 * Disable zoom video.  Some machines initialize this
        !           748:                 * improperly and experience has shown that this helps
        !           749:                 * prevent strange behavior.
        !           750:                 */
        !           751:                pci_conf_write(pc, tag, PCI12XX_MMCTRL, 0);
        !           752:
        !           753:                reg = pci_conf_read(pc, tag, PCI_SYSCTRL);
        !           754:                reg |= PCI12XX_SYSCTRL_VCCPROT;
        !           755:                pci_conf_write(pc, tag, PCI_SYSCTRL, reg);
        !           756:                reg = pci_conf_read(pc, tag, PCI_CBCTRL);
        !           757:                reg |= PCI12XX_CBCTRL_CSC;
        !           758:                pci_conf_write(pc, tag, PCI_CBCTRL, reg);
        !           759:                break;
        !           760:
        !           761:        case CB_TOPIC95B:
        !           762:                reg = pci_conf_read(pc, tag, TOPIC_SOCKET_CTRL);
        !           763:                reg |= TOPIC_SOCKET_CTRL_SCR_IRQSEL;
        !           764:                pci_conf_write(pc, tag, TOPIC_SOCKET_CTRL, reg);
        !           765:
        !           766:                reg = pci_conf_read(pc, tag, TOPIC_SLOT_CTRL);
        !           767:                DPRINTF(("%s: topic slot ctrl reg 0x%x -> ",
        !           768:                    sc->sc_dev.dv_xname, reg));
        !           769:                reg |= (TOPIC_SLOT_CTRL_SLOTON | TOPIC_SLOT_CTRL_SLOTEN |
        !           770:                    TOPIC_SLOT_CTRL_ID_LOCK | TOPIC_SLOT_CTRL_CARDBUS);
        !           771:                reg &= ~TOPIC_SLOT_CTRL_SWDETECT;
        !           772:                DPRINTF(("0x%x\n", reg));
        !           773:                pci_conf_write(pc, tag, TOPIC_SLOT_CTRL, reg);
        !           774:                break;
        !           775:
        !           776:        case CB_TOPIC97:
        !           777:                reg = pci_conf_read(pc, tag, TOPIC_SLOT_CTRL);
        !           778:                DPRINTF(("%s: topic slot ctrl reg 0x%x -> ",
        !           779:                    sc->sc_dev.dv_xname, reg));
        !           780:                reg |= (TOPIC_SLOT_CTRL_SLOTON | TOPIC_SLOT_CTRL_SLOTEN |
        !           781:                    TOPIC_SLOT_CTRL_ID_LOCK | TOPIC_SLOT_CTRL_CARDBUS);
        !           782:                reg &= ~TOPIC_SLOT_CTRL_SWDETECT;
        !           783:                reg |= TOPIC97_SLOT_CTRL_PCIINT;
        !           784:                reg &= ~(TOPIC97_SLOT_CTRL_STSIRQP | TOPIC97_SLOT_CTRL_IRQP);
        !           785:                DPRINTF(("0x%x\n", reg));
        !           786:                pci_conf_write(pc, tag, TOPIC_SLOT_CTRL, reg);
        !           787:
        !           788:                /* make sure to assert LV card support bits */
        !           789:                bus_space_write_1(sc->sc_base_memt, sc->sc_base_memh,
        !           790:                    0x800 + 0x3e, bus_space_read_1(sc->sc_base_memt,
        !           791:                    sc->sc_base_memh, 0x800 + 0x3e) | 0x03);
        !           792:
        !           793:                /* Power on the controller if the BIOS didn't */
        !           794:                reg = pci_conf_read(pc, tag, TOPIC100_PMCSR);
        !           795:                if ((reg & TOPIC100_PMCSR_MASK) != TOPIC100_PMCSR_D0)
        !           796:                        pci_conf_write(pc, tag, TOPIC100_PMCSR,
        !           797:                            (reg & ~TOPIC100_PMCSR_MASK) | TOPIC100_PMCSR_D0);
        !           798:                break;
        !           799:
        !           800:        case CB_OLDO2MICRO:
        !           801:                /*
        !           802:                 * older bridges have problems with both read prefetch and
        !           803:                 * write bursting depending on the combination of the chipset,
        !           804:                 * bridge and the cardbus card. so disable them to be on the
        !           805:                 * safe side. One example is O2Micro 6812 with Atheros AR5012
        !           806:                 * chipsets
        !           807:                 */
        !           808:                DPRINTF(("%s: old O2Micro bridge found\n",
        !           809:                    sc->sc_dev.dv_xname, reg));
        !           810:                reg = pci_conf_read(pc, tag, O2MICRO_RESERVED1);
        !           811:                pci_conf_write(pc, tag, O2MICRO_RESERVED1, reg &
        !           812:                    ~(O2MICRO_RES_READ_PREFETCH | O2MICRO_RES_WRITE_BURST));
        !           813:                reg = pci_conf_read(pc, tag, O2MICRO_RESERVED2);
        !           814:                pci_conf_write(pc, tag, O2MICRO_RESERVED2, reg &
        !           815:                    ~(O2MICRO_RES_READ_PREFETCH | O2MICRO_RES_WRITE_BURST));
        !           816:                break;
        !           817:        }
        !           818:
        !           819:        /* Close all memory and I/O windows. */
        !           820:        pci_conf_write(pc, tag, PCI_CB_MEMBASE0, 0xffffffff);
        !           821:        pci_conf_write(pc, tag, PCI_CB_MEMLIMIT0, 0);
        !           822:        pci_conf_write(pc, tag, PCI_CB_MEMBASE1, 0xffffffff);
        !           823:        pci_conf_write(pc, tag, PCI_CB_MEMLIMIT1, 0);
        !           824:        pci_conf_write(pc, tag, PCI_CB_IOBASE0, 0xffffffff);
        !           825:        pci_conf_write(pc, tag, PCI_CB_IOLIMIT0, 0);
        !           826:        pci_conf_write(pc, tag, PCI_CB_IOBASE1, 0xffffffff);
        !           827:        pci_conf_write(pc, tag, PCI_CB_IOLIMIT1, 0);
        !           828:
        !           829:        /* reset 16-bit pcmcia bus */
        !           830:        bus_space_write_1(sc->sc_base_memt, sc->sc_base_memh,
        !           831:            0x800 + PCIC_INTR,
        !           832:            bus_space_read_1(sc->sc_base_memt, sc->sc_base_memh,
        !           833:                0x800 + PCIC_INTR) & ~PCIC_INTR_RESET);
        !           834:
        !           835:        /* turn off power */
        !           836:        pccbb_power((cardbus_chipset_tag_t)sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
        !           837: }
        !           838:
        !           839:
        !           840:
        !           841:
        !           842: /*
        !           843:  * void pccbb_pcmcia_attach_setup(struct pccbb_softc *sc,
        !           844:  *                                      struct pcmciabus_attach_args *paa)
        !           845:  *
        !           846:  *   This function attaches 16-bit PCcard bus.
        !           847:  */
        !           848: void
        !           849: pccbb_pcmcia_attach_setup(sc, paa)
        !           850:        struct pccbb_softc *sc;
        !           851:        struct pcmciabus_attach_args *paa;
        !           852: {
        !           853:        struct pcic_handle *ph = &sc->sc_pcmcia_h;
        !           854:        rbus_tag_t rb;
        !           855:
        !           856:        /* initialize pcmcia part in pccbb_softc */
        !           857:        ph->ph_parent = (struct device *)sc;
        !           858:        ph->sock = sc->sc_function;
        !           859:        ph->flags = 0;
        !           860:        ph->shutdown = 0;
        !           861:        ph->ih_irq = sc->sc_intrline;
        !           862:        ph->ph_bus_t = sc->sc_base_memt;
        !           863:        ph->ph_bus_h = sc->sc_base_memh;
        !           864:        ph->ph_read = pccbb_pcmcia_read;
        !           865:        ph->ph_write = pccbb_pcmcia_write;
        !           866:        sc->sc_pct = &pccbb_pcmcia_funcs;
        !           867:
        !           868:        /*
        !           869:         * We need to do a few things here:
        !           870:         * 1) Disable routing of CSC and functional interrupts to ISA IRQs by
        !           871:         *    setting the IRQ numbers to 0.
        !           872:         * 2) Set bit 4 of PCIC_INTR, which is needed on some chips to enable
        !           873:         *    routing of CSC interrupts (e.g. card removal) to PCI while in
        !           874:         *    PCMCIA mode.  We just leave this set all the time.
        !           875:         * 3) Enable card insertion/removal interrupts in case the chip also
        !           876:         *    needs that while in PCMCIA mode.
        !           877:         * 4) Clear any pending CSC interrupt.
        !           878:         */
        !           879:        Pcic_write(ph, PCIC_INTR, PCIC_INTR_ENABLE | PCIC_INTR_RESET);
        !           880:        if (sc->sc_chipset == CB_TI113X) {
        !           881:                Pcic_write(ph, PCIC_CSC_INTR, 0);
        !           882:        } else {
        !           883:                Pcic_write(ph, PCIC_CSC_INTR, PCIC_CSC_INTR_CD_ENABLE);
        !           884:                Pcic_read(ph, PCIC_CSC);
        !           885:        }
        !           886:
        !           887:        /* initialize pcmcia bus attachment */
        !           888:        paa->paa_busname = "pcmcia";
        !           889:        paa->pct = sc->sc_pct;
        !           890:        paa->pch = ph;
        !           891:        paa->iobase = 0;               /* I don't use them */
        !           892:        paa->iosize = 0;
        !           893:        rb = ((struct pccbb_softc *)(ph->ph_parent))->sc_rbus_iot;
        !           894:        paa->iobase = rb->rb_start + rb->rb_offset;
        !           895:        paa->iosize = rb->rb_end - rb->rb_start;
        !           896:
        !           897:        return;
        !           898: }
        !           899:
        !           900: #if 0
        !           901: void
        !           902: pccbb_pcmcia_attach_card(ph)
        !           903:        struct pcic_handle *ph;
        !           904: {
        !           905:        if (ph->flags & PCIC_FLAG_CARDP) {
        !           906:                panic("pccbb_pcmcia_attach_card: already attached");
        !           907:        }
        !           908:
        !           909:        /* call the MI attach function */
        !           910:        pcmcia_card_attach(ph->pcmcia);
        !           911:
        !           912:        ph->flags |= PCIC_FLAG_CARDP;
        !           913: }
        !           914:
        !           915: void
        !           916: pccbb_pcmcia_detach_card(ph, flags)
        !           917:        struct pcic_handle *ph;
        !           918:        int flags;
        !           919: {
        !           920:        if (!(ph->flags & PCIC_FLAG_CARDP)) {
        !           921:                panic("pccbb_pcmcia_detach_card: already detached");
        !           922:        }
        !           923:
        !           924:        ph->flags &= ~PCIC_FLAG_CARDP;
        !           925:
        !           926:        /* call the MI detach function */
        !           927:        pcmcia_card_detach(ph->pcmcia, flags);
        !           928: }
        !           929: #endif
        !           930:
        !           931: /*
        !           932:  * int pccbbintr(arg)
        !           933:  *    void *arg;
        !           934:  *   This routine handles the interrupt from Yenta PCI-CardBus bridge
        !           935:  *   itself.
        !           936:  */
        !           937: int
        !           938: pccbbintr(arg)
        !           939:        void *arg;
        !           940: {
        !           941:        struct pccbb_softc *sc = (struct pccbb_softc *)arg;
        !           942:        u_int32_t sockevent, sockstate;
        !           943:        bus_space_tag_t memt = sc->sc_base_memt;
        !           944:        bus_space_handle_t memh = sc->sc_base_memh;
        !           945:        struct pcic_handle *ph = &sc->sc_pcmcia_h;
        !           946:
        !           947:        if (!sc->sc_ints_on)
        !           948:                return 0;
        !           949:
        !           950:        sockevent = bus_space_read_4(memt, memh, CB_SOCKET_EVENT);
        !           951:        bus_space_write_4(memt, memh, CB_SOCKET_EVENT, sockevent);
        !           952:        Pcic_read(ph, PCIC_CSC);
        !           953:
        !           954:        if (sockevent == 0) {
        !           955:                /* This intr is not for me: it may be for my child devices. */
        !           956:                if (sc->sc_pil_intr_enable) {
        !           957:                        return pccbbintr_function(sc);
        !           958:                } else {
        !           959:                        return 0;
        !           960:                }
        !           961:        }
        !           962:
        !           963:        if (sockevent & CB_SOCKET_EVENT_CD) {
        !           964:                sockstate = bus_space_read_4(memt, memh, CB_SOCKET_STAT);
        !           965:                if (CB_SOCKET_STAT_CD == (sockstate & CB_SOCKET_STAT_CD)) {
        !           966:                        /* A card should be removed. */
        !           967:                        if (sc->sc_flags & CBB_CARDEXIST) {
        !           968:                                DPRINTF(("%s: 0x%08x", sc->sc_dev.dv_xname,
        !           969:                                    sockevent));
        !           970:                                DPRINTF((" card removed, 0x%08x\n", sockstate));
        !           971:                                sc->sc_flags &= ~CBB_CARDEXIST;
        !           972:                                if (sc->sc_csc->sc_status &
        !           973:                                    CARDSLOT_STATUS_CARD_16) {
        !           974: #if 0
        !           975:                                        struct pcic_handle *ph =
        !           976:                                            &sc->sc_pcmcia_h;
        !           977:
        !           978:                                        pcmcia_card_deactivate(ph->pcmcia);
        !           979:                                        pccbb_pcmcia_socket_disable(ph);
        !           980:                                        pccbb_pcmcia_detach_card(ph,
        !           981:                                            DETACH_FORCE);
        !           982: #endif
        !           983:                                        cardslot_event_throw(sc->sc_csc,
        !           984:                                            CARDSLOT_EVENT_REMOVAL_16);
        !           985:                                } else if (sc->sc_csc->sc_status &
        !           986:                                    CARDSLOT_STATUS_CARD_CB) {
        !           987:                                        /* Cardbus intr removed */
        !           988:                                        cardslot_event_throw(sc->sc_csc,
        !           989:                                            CARDSLOT_EVENT_REMOVAL_CB);
        !           990:                                }
        !           991:                        }
        !           992:                } else if (0x00 == (sockstate & CB_SOCKET_STAT_CD) &&
        !           993:                    /*
        !           994:                     * The pccbbintr may called from powerdown hook when
        !           995:                     * the system resumed, to detect the card
        !           996:                     * insertion/removal during suspension.
        !           997:                     */
        !           998:                    (sc->sc_flags & CBB_CARDEXIST) == 0) {
        !           999:                        if (sc->sc_flags & CBB_INSERTING) {
        !          1000:                                timeout_del(&sc->sc_ins_tmo);
        !          1001:                        }
        !          1002:                        timeout_add(&sc->sc_ins_tmo, hz / 10);
        !          1003:                        sc->sc_flags |= CBB_INSERTING;
        !          1004:                }
        !          1005:        }
        !          1006:
        !          1007:        return (1);
        !          1008: }
        !          1009:
        !          1010: /*
        !          1011:  * int pccbbintr_function(struct pccbb_softc *sc)
        !          1012:  *
        !          1013:  *    This function calls each interrupt handler registered at the
        !          1014:  *    bridge.  The interrupt handlers are called in registered order.
        !          1015:  */
        !          1016: int
        !          1017: pccbbintr_function(sc)
        !          1018:        struct pccbb_softc *sc;
        !          1019: {
        !          1020:        int retval = 0, val;
        !          1021:        struct pccbb_intrhand_list *pil;
        !          1022:        int s, splchanged;
        !          1023:
        !          1024:        for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) {
        !          1025:                /*
        !          1026:                 * XXX priority change.  gross.  I use if-else
        !          1027:                 * sentense instead of switch-case sentense because of
        !          1028:                 * avoiding duplicate case value error.  More than one
        !          1029:                 * IPL_XXX use same value.  It depends on
        !          1030:                 * implementation.
        !          1031:                 */
        !          1032:                splchanged = 1;
        !          1033: #if 0
        !          1034:                if (pil->pil_level == IPL_SERIAL) {
        !          1035:                        s = splserial();
        !          1036:                } else if (pil->pil_level == IPL_HIGH) {
        !          1037: #endif
        !          1038:                if (pil->pil_level == IPL_HIGH) {
        !          1039:                        s = splhigh();
        !          1040:                } else if (pil->pil_level == IPL_CLOCK) {
        !          1041:                        s = splclock();
        !          1042:                } else if (pil->pil_level == IPL_AUDIO) {
        !          1043:                        s = splaudio();
        !          1044:                } else if (pil->pil_level == IPL_VM) {
        !          1045:                        s = splvm();
        !          1046:                } else if (pil->pil_level == IPL_TTY) {
        !          1047:                        s = spltty();
        !          1048: #if 0
        !          1049:                } else if (pil->pil_level == IPL_SOFTSERIAL) {
        !          1050:                        s = splsoftserial();
        !          1051: #endif
        !          1052:                } else if (pil->pil_level == IPL_NET) {
        !          1053:                        s = splnet();
        !          1054:                } else {
        !          1055:                        splchanged = 0;
        !          1056:                        /* XXX: ih lower than IPL_BIO runs w/ IPL_BIO. */
        !          1057:                }
        !          1058:
        !          1059:                val = (*pil->pil_func)(pil->pil_arg);
        !          1060:                if (val != 0)
        !          1061:                        pil->pil_count.ec_count++;
        !          1062:
        !          1063:                if (splchanged != 0) {
        !          1064:                        splx(s);
        !          1065:                }
        !          1066:
        !          1067:                retval = retval == 1 ? 1 :
        !          1068:                    retval == 0 ? val : val != 0 ? val : retval;
        !          1069:        }
        !          1070:
        !          1071:        return retval;
        !          1072: }
        !          1073:
        !          1074: void
        !          1075: pci113x_insert(arg)
        !          1076:        void *arg;
        !          1077: {
        !          1078:        struct pccbb_softc *sc = (struct pccbb_softc *)arg;
        !          1079:        u_int32_t sockevent, sockstate;
        !          1080:
        !          1081:        sockevent = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
        !          1082:            CB_SOCKET_EVENT);
        !          1083:        sockstate = bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
        !          1084:            CB_SOCKET_STAT);
        !          1085:
        !          1086:        if (0 == (sockstate & CB_SOCKET_STAT_CD)) {     /* card exist */
        !          1087:                DPRINTF(("%s: 0x%08x", sc->sc_dev.dv_xname, sockevent));
        !          1088:                DPRINTF((" card inserted, 0x%08x\n", sockstate));
        !          1089:                sc->sc_flags |= CBB_CARDEXIST;
        !          1090:                /* call pccard interrupt handler here */
        !          1091:                if (sockstate & CB_SOCKET_STAT_16BIT) {
        !          1092:                        /* 16-bit card found */
        !          1093: /*      pccbb_pcmcia_attach_card(&sc->sc_pcmcia_h); */
        !          1094:                        cardslot_event_throw(sc->sc_csc,
        !          1095:                            CARDSLOT_EVENT_INSERTION_16);
        !          1096:                } else if (sockstate & CB_SOCKET_STAT_CB) {
        !          1097:                        /* cardbus card found */
        !          1098: /*      cardbus_attach_card(sc->sc_csc); */
        !          1099:                        cardslot_event_throw(sc->sc_csc,
        !          1100:                            CARDSLOT_EVENT_INSERTION_CB);
        !          1101:                } else {
        !          1102:                        /* who are you? */
        !          1103:                }
        !          1104:        } else {
        !          1105:                timeout_add(&sc->sc_ins_tmo, hz / 10);
        !          1106:        }
        !          1107: }
        !          1108:
        !          1109: #define PCCBB_PCMCIA_OFFSET 0x800
        !          1110: u_int8_t
        !          1111: pccbb_pcmcia_read(ph, reg)
        !          1112:        struct pcic_handle *ph;
        !          1113:        int reg;
        !          1114: {
        !          1115:        bus_space_barrier(ph->ph_bus_t, ph->ph_bus_h,
        !          1116:            PCCBB_PCMCIA_OFFSET + reg, 1, BUS_SPACE_BARRIER_READ);
        !          1117:
        !          1118:        return bus_space_read_1(ph->ph_bus_t, ph->ph_bus_h,
        !          1119:            PCCBB_PCMCIA_OFFSET + reg);
        !          1120: }
        !          1121:
        !          1122: void
        !          1123: pccbb_pcmcia_write(ph, reg, val)
        !          1124:        struct pcic_handle *ph;
        !          1125:        int reg;
        !          1126:        u_int8_t val;
        !          1127: {
        !          1128:        bus_space_barrier(ph->ph_bus_t, ph->ph_bus_h,
        !          1129:            PCCBB_PCMCIA_OFFSET + reg, 1, BUS_SPACE_BARRIER_WRITE);
        !          1130:
        !          1131:        bus_space_write_1(ph->ph_bus_t, ph->ph_bus_h, PCCBB_PCMCIA_OFFSET + reg,
        !          1132:            val);
        !          1133: }
        !          1134:
        !          1135: /*
        !          1136:  * int pccbb_ctrl(cardbus_chipset_tag_t, int)
        !          1137:  */
        !          1138: int
        !          1139: pccbb_ctrl(ct, command)
        !          1140:        cardbus_chipset_tag_t ct;
        !          1141:        int command;
        !          1142: {
        !          1143:        struct pccbb_softc *sc = (struct pccbb_softc *)ct;
        !          1144:
        !          1145:        switch (command) {
        !          1146:        case CARDBUS_CD:
        !          1147:                if (2 == pccbb_detect_card(sc)) {
        !          1148:                        int retval = 0;
        !          1149:                        int status = cb_detect_voltage(sc);
        !          1150:                        if (PCCARD_VCC_5V & status) {
        !          1151:                                retval |= CARDBUS_5V_CARD;
        !          1152:                        }
        !          1153:                        if (PCCARD_VCC_3V & status) {
        !          1154:                                retval |= CARDBUS_3V_CARD;
        !          1155:                        }
        !          1156:                        if (PCCARD_VCC_XV & status) {
        !          1157:                                retval |= CARDBUS_XV_CARD;
        !          1158:                        }
        !          1159:                        if (PCCARD_VCC_YV & status) {
        !          1160:                                retval |= CARDBUS_YV_CARD;
        !          1161:                        }
        !          1162:                        return retval;
        !          1163:                } else {
        !          1164:                        return 0;
        !          1165:                }
        !          1166:                break;
        !          1167:        case CARDBUS_RESET:
        !          1168:                return cb_reset(sc);
        !          1169:                break;
        !          1170:        case CARDBUS_IO_ENABLE:       /* fallthrough */
        !          1171:        case CARDBUS_IO_DISABLE:      /* fallthrough */
        !          1172:        case CARDBUS_MEM_ENABLE:      /* fallthrough */
        !          1173:        case CARDBUS_MEM_DISABLE:     /* fallthrough */
        !          1174:        case CARDBUS_BM_ENABLE:       /* fallthrough */
        !          1175:        case CARDBUS_BM_DISABLE:      /* fallthrough */
        !          1176:                return pccbb_cardenable(sc, command);
        !          1177:                break;
        !          1178:        }
        !          1179:
        !          1180:        return 0;
        !          1181: }
        !          1182:
        !          1183: /*
        !          1184:  * int pccbb_power(cardbus_chipset_tag_t, int)
        !          1185:  *   This function returns true when it succeeds and returns false when
        !          1186:  *   it fails.
        !          1187:  */
        !          1188: int
        !          1189: pccbb_power(ct, command)
        !          1190:        cardbus_chipset_tag_t ct;
        !          1191:        int command;
        !          1192: {
        !          1193:        struct pccbb_softc *sc = (struct pccbb_softc *)ct;
        !          1194:
        !          1195:        u_int32_t status, sock_ctrl;
        !          1196:        bus_space_tag_t memt = sc->sc_base_memt;
        !          1197:        bus_space_handle_t memh = sc->sc_base_memh;
        !          1198:
        !          1199:        DPRINTF(("pccbb_power: %s and %s [%x]\n",
        !          1200:            (command & CARDBUS_VCCMASK) == CARDBUS_VCC_UC ? "CARDBUS_VCC_UC" :
        !          1201:            (command & CARDBUS_VCCMASK) == CARDBUS_VCC_5V ? "CARDBUS_VCC_5V" :
        !          1202:            (command & CARDBUS_VCCMASK) == CARDBUS_VCC_3V ? "CARDBUS_VCC_3V" :
        !          1203:            (command & CARDBUS_VCCMASK) == CARDBUS_VCC_XV ? "CARDBUS_VCC_XV" :
        !          1204:            (command & CARDBUS_VCCMASK) == CARDBUS_VCC_YV ? "CARDBUS_VCC_YV" :
        !          1205:            (command & CARDBUS_VCCMASK) == CARDBUS_VCC_0V ? "CARDBUS_VCC_0V" :
        !          1206:            "UNKNOWN",
        !          1207:            (command & CARDBUS_VPPMASK) == CARDBUS_VPP_UC ? "CARDBUS_VPP_UC" :
        !          1208:            (command & CARDBUS_VPPMASK) == CARDBUS_VPP_12V ? "CARDBUS_VPP_12V" :
        !          1209:            (command & CARDBUS_VPPMASK) == CARDBUS_VPP_VCC ? "CARDBUS_VPP_VCC" :
        !          1210:            (command & CARDBUS_VPPMASK) == CARDBUS_VPP_0V ? "CARDBUS_VPP_0V" :
        !          1211:            "UNKNOWN", command));
        !          1212:
        !          1213:        status = bus_space_read_4(memt, memh, CB_SOCKET_STAT);
        !          1214:        sock_ctrl = bus_space_read_4(memt, memh, CB_SOCKET_CTRL);
        !          1215:
        !          1216:        switch (command & CARDBUS_VCCMASK) {
        !          1217:        case CARDBUS_VCC_UC:
        !          1218:                break;
        !          1219:        case CARDBUS_VCC_5V:
        !          1220:                if (CB_SOCKET_STAT_5VCARD & status) {   /* check 5 V card */
        !          1221:                        sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK;
        !          1222:                        sock_ctrl |= CB_SOCKET_CTRL_VCC_5V;
        !          1223:                } else {
        !          1224:                        printf("%s: BAD voltage request: no 5 V card\n",
        !          1225:                            sc->sc_dev.dv_xname);
        !          1226:                }
        !          1227:                break;
        !          1228:        case CARDBUS_VCC_3V:
        !          1229:                if (CB_SOCKET_STAT_3VCARD & status) {
        !          1230:                        sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK;
        !          1231:                        sock_ctrl |= CB_SOCKET_CTRL_VCC_3V;
        !          1232:                } else {
        !          1233:                        printf("%s: BAD voltage request: no 3.3 V card\n",
        !          1234:                            sc->sc_dev.dv_xname);
        !          1235:                }
        !          1236:                break;
        !          1237:        case CARDBUS_VCC_0V:
        !          1238:                sock_ctrl &= ~CB_SOCKET_CTRL_VCCMASK;
        !          1239:                break;
        !          1240:        default:
        !          1241:                return 0;              /* power NEVER changed */
        !          1242:                break;
        !          1243:        }
        !          1244:
        !          1245:        switch (command & CARDBUS_VPPMASK) {
        !          1246:        case CARDBUS_VPP_UC:
        !          1247:                break;
        !          1248:        case CARDBUS_VPP_0V:
        !          1249:                sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK;
        !          1250:                break;
        !          1251:        case CARDBUS_VPP_VCC:
        !          1252:                sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK;
        !          1253:                sock_ctrl |= ((sock_ctrl >> 4) & 0x07);
        !          1254:                break;
        !          1255:        case CARDBUS_VPP_12V:
        !          1256:                sock_ctrl &= ~CB_SOCKET_CTRL_VPPMASK;
        !          1257:                sock_ctrl |= CB_SOCKET_CTRL_VPP_12V;
        !          1258:                break;
        !          1259:        }
        !          1260:
        !          1261: #if 0
        !          1262:        DPRINTF(("sock_ctrl: %x\n", sock_ctrl));
        !          1263: #endif
        !          1264:        bus_space_write_4(memt, memh, CB_SOCKET_CTRL, sock_ctrl);
        !          1265:        status = bus_space_read_4(memt, memh, CB_SOCKET_STAT);
        !          1266:
        !          1267:        if (status & CB_SOCKET_STAT_BADVCC) {   /* bad Vcc request */
        !          1268:                printf
        !          1269:                    ("%s: bad Vcc request. sock_ctrl 0x%x, sock_status 0x%x\n",
        !          1270:                    sc->sc_dev.dv_xname, sock_ctrl, status);
        !          1271:                DPRINTF(("pccbb_power: %s and %s [%x]\n",
        !          1272:                    (command & CARDBUS_VCCMASK) ==
        !          1273:                    CARDBUS_VCC_UC ? "CARDBUS_VCC_UC" : (command &
        !          1274:                    CARDBUS_VCCMASK) ==
        !          1275:                    CARDBUS_VCC_5V ? "CARDBUS_VCC_5V" : (command &
        !          1276:                    CARDBUS_VCCMASK) ==
        !          1277:                    CARDBUS_VCC_3V ? "CARDBUS_VCC_3V" : (command &
        !          1278:                    CARDBUS_VCCMASK) ==
        !          1279:                    CARDBUS_VCC_XV ? "CARDBUS_VCC_XV" : (command &
        !          1280:                    CARDBUS_VCCMASK) ==
        !          1281:                    CARDBUS_VCC_YV ? "CARDBUS_VCC_YV" : (command &
        !          1282:                    CARDBUS_VCCMASK) ==
        !          1283:                    CARDBUS_VCC_0V ? "CARDBUS_VCC_0V" : "UNKNOWN",
        !          1284:                    (command & CARDBUS_VPPMASK) ==
        !          1285:                    CARDBUS_VPP_UC ? "CARDBUS_VPP_UC" : (command &
        !          1286:                    CARDBUS_VPPMASK) ==
        !          1287:                    CARDBUS_VPP_12V ? "CARDBUS_VPP_12V" : (command &
        !          1288:                    CARDBUS_VPPMASK) ==
        !          1289:                    CARDBUS_VPP_VCC ? "CARDBUS_VPP_VCC" : (command &
        !          1290:                    CARDBUS_VPPMASK) ==
        !          1291:                    CARDBUS_VPP_0V ? "CARDBUS_VPP_0V" : "UNKNOWN", command));
        !          1292: #if 0
        !          1293:                if (command == (CARDBUS_VCC_0V | CARDBUS_VPP_0V)) {
        !          1294:                        u_int32_t force =
        !          1295:                            bus_space_read_4(memt, memh, CB_SOCKET_FORCE);
        !          1296:                        /* Reset Bad Vcc request */
        !          1297:                        force &= ~CB_SOCKET_FORCE_BADVCC;
        !          1298:                        bus_space_write_4(memt, memh, CB_SOCKET_FORCE, force);
        !          1299:                        printf("new status 0x%x\n", bus_space_read_4(memt, memh,
        !          1300:                            CB_SOCKET_STAT));
        !          1301:                        return 1;
        !          1302:                }
        !          1303: #endif
        !          1304:                return 0;
        !          1305:        }
        !          1306:
        !          1307:        /*
        !          1308:         * XXX delay 300 ms: though the standard defines that the Vcc set-up
        !          1309:         * time is 20 ms, some PC-Card bridge requires longer duration.
        !          1310:         */
        !          1311:        delay(300 * 1000);
        !          1312:
        !          1313:        return 1;                      /* power changed correctly */
        !          1314: }
        !          1315:
        !          1316: #if defined CB_PCMCIA_POLL
        !          1317: struct cb_poll_str {
        !          1318:        void *arg;
        !          1319:        int (*func)(void *);
        !          1320:        int level;
        !          1321:        pccard_chipset_tag_t ct;
        !          1322:        int count;
        !          1323: };
        !          1324:
        !          1325: static struct cb_poll_str cb_poll[10];
        !          1326: static int cb_poll_n = 0;
        !          1327: static struct timeout cb_poll_timeout;
        !          1328:
        !          1329: void cb_pcmcia_poll(void *arg);
        !          1330:
        !          1331: void
        !          1332: cb_pcmcia_poll(arg)
        !          1333:        void *arg;
        !          1334: {
        !          1335:        struct cb_poll_str *poll = arg;
        !          1336:        struct cbb_pcmcia_softc *psc = (void *)poll->ct->v;
        !          1337:        struct pccbb_softc *sc = psc->cpc_parent;
        !          1338:        int s;
        !          1339:        u_int32_t spsr;                /* socket present-state reg */
        !          1340:
        !          1341:        timeout_set(&cb_poll_timeout, cb_pcmcia_poll, arg);
        !          1342:        timeout_add(&cb_poll_timeout, hz / 10);
        !          1343:        switch (poll->level) {
        !          1344:        case IPL_NET:
        !          1345:                s = splnet();
        !          1346:                break;
        !          1347:        case IPL_BIO:
        !          1348:                s = splbio();
        !          1349:                break;
        !          1350:        case IPL_TTY:                  /* fallthrough */
        !          1351:        default:
        !          1352:                s = spltty();
        !          1353:                break;
        !          1354:        }
        !          1355:
        !          1356:        spsr =
        !          1357:            bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
        !          1358:            CB_SOCKET_STAT);
        !          1359:
        !          1360: #if defined CB_PCMCIA_POLL_ONLY && defined LEVEL2
        !          1361:        if (!(spsr & 0x40)) {          /* CINT low */
        !          1362: #else
        !          1363:        if (1) {
        !          1364: #endif
        !          1365:                if ((*poll->func) (poll->arg) == 1) {
        !          1366:                        ++poll->count;
        !          1367:                        printf("intr: reported from poller, 0x%x\n", spsr);
        !          1368: #if defined LEVEL2
        !          1369:                } else {
        !          1370:                        printf("intr: miss! 0x%x\n", spsr);
        !          1371: #endif
        !          1372:                }
        !          1373:        }
        !          1374:        splx(s);
        !          1375: }
        !          1376: #endif /* defined CB_PCMCIA_POLL */
        !          1377:
        !          1378: /*
        !          1379:  * int pccbb_detect_card(struct pccbb_softc *sc)
        !          1380:  *   return value:  0 if no card exists.
        !          1381:  *                  1 if 16-bit card exists.
        !          1382:  *                  2 if cardbus card exists.
        !          1383:  */
        !          1384: int
        !          1385: pccbb_detect_card(sc)
        !          1386:        struct pccbb_softc *sc;
        !          1387: {
        !          1388:        bus_space_handle_t base_memh = sc->sc_base_memh;
        !          1389:        bus_space_tag_t base_memt = sc->sc_base_memt;
        !          1390:        u_int32_t sockstat =
        !          1391:            bus_space_read_4(base_memt, base_memh, CB_SOCKET_STAT);
        !          1392:        int retval = 0;
        !          1393:
        !          1394:        /*
        !          1395:         * The SCM Microsystems TI1225-based PCI-CardBus dock card that
        !          1396:         * ships with some Lucent WaveLAN cards has only one physical slot
        !          1397:         * but OpenBSD probes two. The phantom card in the second slot can
        !          1398:         * be ignored by punting on unsupported voltages.
        !          1399:         */
        !          1400:        if (sockstat & CB_SOCKET_STAT_XVCARD)
        !          1401:                return 0;
        !          1402:
        !          1403:        /* CD1 and CD2 asserted */
        !          1404:        if (0x00 == (sockstat & CB_SOCKET_STAT_CD)) {
        !          1405:                /* card must be present */
        !          1406:                if (!(CB_SOCKET_STAT_NOTCARD & sockstat)) {
        !          1407:                        /* NOTACARD DEASSERTED */
        !          1408:                        if (CB_SOCKET_STAT_CB & sockstat) {
        !          1409:                                /* CardBus mode */
        !          1410:                                retval = 2;
        !          1411:                        } else if (CB_SOCKET_STAT_16BIT & sockstat) {
        !          1412:                                /* 16-bit mode */
        !          1413:                                retval = 1;
        !          1414:                        }
        !          1415:                }
        !          1416:        }
        !          1417:        return retval;
        !          1418: }
        !          1419:
        !          1420: /*
        !          1421:  * int cb_reset(struct pccbb_softc *sc)
        !          1422:  *   This function resets CardBus card.
        !          1423:  */
        !          1424: int
        !          1425: cb_reset(sc)
        !          1426:        struct pccbb_softc *sc;
        !          1427: {
        !          1428:        /*
        !          1429:         * Reset Assert at least 20 ms
        !          1430:         * Some machines request longer duration.
        !          1431:         */
        !          1432:        int reset_duration =
        !          1433:            (sc->sc_chipset == CB_RX5C47X ? 400 * 1000 : 40 * 1000);
        !          1434:        u_int32_t bcr = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR);
        !          1435:
        !          1436:        /* Reset bit Assert (bit 6 at 0x3E) */
        !          1437:        bcr |= CB_BCR_RESET_ENABLE;
        !          1438:        pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, bcr);
        !          1439:        delay(reset_duration);
        !          1440:
        !          1441:        if (CBB_CARDEXIST & sc->sc_flags) {     /* A card exists.  Reset it! */
        !          1442:                /* Reset bit Deassert (bit 6 at 0x3E) */
        !          1443:                bcr &= ~CB_BCR_RESET_ENABLE;
        !          1444:                pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, bcr);
        !          1445:                delay(reset_duration);
        !          1446:        }
        !          1447:        /* No card found on the slot. Keep Reset. */
        !          1448:        return 1;
        !          1449: }
        !          1450:
        !          1451: /*
        !          1452:  * int cb_detect_voltage(struct pccbb_softc *sc)
        !          1453:  *  This function detect card Voltage.
        !          1454:  */
        !          1455: int
        !          1456: cb_detect_voltage(sc)
        !          1457:        struct pccbb_softc *sc;
        !          1458: {
        !          1459:        u_int32_t psr;                 /* socket present-state reg */
        !          1460:        bus_space_tag_t iot = sc->sc_base_memt;
        !          1461:        bus_space_handle_t ioh = sc->sc_base_memh;
        !          1462:        int vol = PCCARD_VCC_UKN;      /* set 0 */
        !          1463:
        !          1464:        psr = bus_space_read_4(iot, ioh, CB_SOCKET_STAT);
        !          1465:
        !          1466:        if (0x400u & psr) {
        !          1467:                vol |= PCCARD_VCC_5V;
        !          1468:        }
        !          1469:        if (0x800u & psr) {
        !          1470:                vol |= PCCARD_VCC_3V;
        !          1471:        }
        !          1472:
        !          1473:        return vol;
        !          1474: }
        !          1475:
        !          1476: int
        !          1477: cbbprint(aux, pcic)
        !          1478:        void *aux;
        !          1479:        const char *pcic;
        !          1480: {
        !          1481: /*
        !          1482:   struct cbslot_attach_args *cba = aux;
        !          1483:
        !          1484:   if (cba->cba_slot >= 0) {
        !          1485:     printf(" slot %d", cba->cba_slot);
        !          1486:   }
        !          1487: */
        !          1488:        return UNCONF;
        !          1489: }
        !          1490:
        !          1491: /*
        !          1492:  * int pccbb_cardenable(struct pccbb_softc *sc, int function)
        !          1493:  *   This function enables and disables the card
        !          1494:  */
        !          1495: int
        !          1496: pccbb_cardenable(sc, function)
        !          1497:        struct pccbb_softc *sc;
        !          1498:        int function;
        !          1499: {
        !          1500:        u_int32_t command =
        !          1501:            pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG);
        !          1502:
        !          1503:        DPRINTF(("pccbb_cardenable:"));
        !          1504:        switch (function) {
        !          1505:        case CARDBUS_IO_ENABLE:
        !          1506:                command |= PCI_COMMAND_IO_ENABLE;
        !          1507:                break;
        !          1508:        case CARDBUS_IO_DISABLE:
        !          1509:                command &= ~PCI_COMMAND_IO_ENABLE;
        !          1510:                break;
        !          1511:        case CARDBUS_MEM_ENABLE:
        !          1512:                command |= PCI_COMMAND_MEM_ENABLE;
        !          1513:                break;
        !          1514:        case CARDBUS_MEM_DISABLE:
        !          1515:                command &= ~PCI_COMMAND_MEM_ENABLE;
        !          1516:                break;
        !          1517:        case CARDBUS_BM_ENABLE:
        !          1518:                command |= PCI_COMMAND_MASTER_ENABLE;
        !          1519:                break;
        !          1520:        case CARDBUS_BM_DISABLE:
        !          1521:                command &= ~PCI_COMMAND_MASTER_ENABLE;
        !          1522:                break;
        !          1523:        default:
        !          1524:                return 0;
        !          1525:        }
        !          1526:
        !          1527:        pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_COMMAND_STATUS_REG, command);
        !          1528:        DPRINTF((" command reg 0x%x\n", command));
        !          1529:        return 1;
        !          1530: }
        !          1531:
        !          1532: /*
        !          1533:  * void *pccbb_cb_intr_establish(cardbus_chipset_tag_t ct,
        !          1534:  *                                     int irq,
        !          1535:  *                                     int level,
        !          1536:  *                                     int (* func)(void *),
        !          1537:  *                                     void *arg,
        !          1538:  *                                     const char *name)
        !          1539:  *
        !          1540:  *   This function registers an interrupt handler at the bridge, in
        !          1541:  *   order not to call the interrupt handlers of child devices when
        !          1542:  *   a card-deletion interrupt occurs.
        !          1543:  *
        !          1544:  *   The arguments irq is not used because pccbb selects intr vector.
        !          1545:  */
        !          1546: void *
        !          1547: pccbb_cb_intr_establish(ct, irq, level, func, arg, name)
        !          1548:        cardbus_chipset_tag_t ct;
        !          1549:        int irq, level;
        !          1550:        int (*func)(void *);
        !          1551:        void *arg;
        !          1552:        const char *name;
        !          1553: {
        !          1554:        struct pccbb_softc *sc = (struct pccbb_softc *)ct;
        !          1555:
        !          1556:        return pccbb_intr_establish(sc, irq, level, func, arg, name);
        !          1557: }
        !          1558:
        !          1559:
        !          1560: /*
        !          1561:  * void *pccbb_cb_intr_disestablish(cardbus_chipset_tag_t ct,
        !          1562:  *                                        void *ih)
        !          1563:  *
        !          1564:  *   This function removes an interrupt handler pointed by ih.
        !          1565:  */
        !          1566: void
        !          1567: pccbb_cb_intr_disestablish(ct, ih)
        !          1568:        cardbus_chipset_tag_t ct;
        !          1569:        void *ih;
        !          1570: {
        !          1571:        struct pccbb_softc *sc = (struct pccbb_softc *)ct;
        !          1572:
        !          1573:        pccbb_intr_disestablish(sc, ih);
        !          1574: }
        !          1575:
        !          1576:
        !          1577: /*
        !          1578:  * void *pccbb_intr_establish(struct pccbb_softc *sc,
        !          1579:  *                                  int irq,
        !          1580:  *                                  int level,
        !          1581:  *                                  int (* func)(void *),
        !          1582:  *                                  void *arg,
        !          1583:  *                                  const char *name)
        !          1584:  *
        !          1585:  *   This function registers an interrupt handler at the bridge, in
        !          1586:  *   order not to call the interrupt handlers of child devices when
        !          1587:  *   a card-deletion interrupt occurs.
        !          1588:  *
        !          1589:  *   The arguments irq and level are not used.
        !          1590:  */
        !          1591: void *
        !          1592: pccbb_intr_establish(sc, irq, level, func, arg, name)
        !          1593:        struct pccbb_softc *sc;
        !          1594:        int irq, level;
        !          1595:        int (*func)(void *);
        !          1596:        void *arg;
        !          1597:        const char *name;
        !          1598: {
        !          1599:        struct pccbb_intrhand_list *pil, *newpil;
        !          1600:        pcireg_t reg;
        !          1601:
        !          1602:        DPRINTF(("pccbb_intr_establish start. %p\n", sc->sc_pil));
        !          1603:
        !          1604:        if (sc->sc_pil == NULL) {
        !          1605:                /* initialize bridge intr routing */
        !          1606:                reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR);
        !          1607:                reg &= ~CB_BCR_INTR_IREQ_ENABLE;
        !          1608:                pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, reg);
        !          1609:
        !          1610:                switch (sc->sc_chipset) {
        !          1611:                case CB_TI113X:
        !          1612:                        reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL);
        !          1613:                        /* functional intr enabled */
        !          1614:                        reg |= PCI113X_CBCTRL_PCI_INTR;
        !          1615:                        pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, reg);
        !          1616:                        break;
        !          1617:                default:
        !          1618:                        break;
        !          1619:                }
        !          1620:        }
        !          1621:
        !          1622:        /*
        !          1623:         * Allocate a room for interrupt handler structure.
        !          1624:         */
        !          1625:        newpil = (struct pccbb_intrhand_list *)
        !          1626:                malloc(sizeof(struct pccbb_intrhand_list), M_DEVBUF, M_WAITOK);
        !          1627:
        !          1628:        newpil->pil_func = func;
        !          1629:        newpil->pil_arg = arg;
        !          1630:        newpil->pil_level = level;
        !          1631:        evcount_attach(&newpil->pil_count, name, &sc->sc_intrline,
        !          1632:            &evcount_intr);
        !          1633:        newpil->pil_next = NULL;
        !          1634:
        !          1635:        if (sc->sc_pil == NULL) {
        !          1636:                sc->sc_pil = newpil;
        !          1637:        } else {
        !          1638:                for (pil = sc->sc_pil; pil->pil_next != NULL;
        !          1639:                    pil = pil->pil_next);
        !          1640:                pil->pil_next = newpil;
        !          1641:        }
        !          1642:
        !          1643:        DPRINTF(("pccbb_intr_establish add pil. %p\n", sc->sc_pil));
        !          1644:
        !          1645:        return newpil;
        !          1646: }
        !          1647:
        !          1648: /*
        !          1649:  * void *pccbb_intr_disestablish(struct pccbb_softc *sc,
        !          1650:  *                                     void *ih)
        !          1651:  *
        !          1652:  *   This function removes an interrupt handler pointed by ih.
        !          1653:  */
        !          1654: void
        !          1655: pccbb_intr_disestablish(sc, ih)
        !          1656:        struct pccbb_softc *sc;
        !          1657:        void *ih;
        !          1658: {
        !          1659:        struct pccbb_intrhand_list *pil, **pil_prev;
        !          1660:        pcireg_t reg;
        !          1661:
        !          1662:        DPRINTF(("pccbb_intr_disestablish start. %p\n", sc->sc_pil));
        !          1663:
        !          1664:        pil_prev = &sc->sc_pil;
        !          1665:
        !          1666:        for (pil = sc->sc_pil; pil != NULL; pil = pil->pil_next) {
        !          1667:                if (pil == ih) {
        !          1668:                        evcount_detach(&pil->pil_count);
        !          1669:                        *pil_prev = pil->pil_next;
        !          1670:                        free(pil, M_DEVBUF);
        !          1671:                        DPRINTF(("pccbb_intr_disestablish frees one pil\n"));
        !          1672:                        break;
        !          1673:                }
        !          1674:                pil_prev = &pil->pil_next;
        !          1675:        }
        !          1676:
        !          1677:        if (sc->sc_pil == NULL) {
        !          1678:                /* No interrupt handlers */
        !          1679:
        !          1680:                DPRINTF(("pccbb_intr_disestablish: no interrupt handler\n"));
        !          1681:
        !          1682:                /* stop routing PCI intr */
        !          1683:                reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR);
        !          1684:                reg |= CB_BCR_INTR_IREQ_ENABLE;
        !          1685:                pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_BCR_INTR, reg);
        !          1686:
        !          1687:                switch (sc->sc_chipset) {
        !          1688:                case CB_TI113X:
        !          1689:                        reg = pci_conf_read(sc->sc_pc, sc->sc_tag, PCI_CBCTRL);
        !          1690:                        /* functional intr disabled */
        !          1691:                        reg &= ~PCI113X_CBCTRL_PCI_INTR;
        !          1692:                        pci_conf_write(sc->sc_pc, sc->sc_tag, PCI_CBCTRL, reg);
        !          1693:                        break;
        !          1694:                default:
        !          1695:                        break;
        !          1696:                }
        !          1697:        }
        !          1698: }
        !          1699:
        !          1700: #if defined SHOW_REGS
        !          1701: void
        !          1702: cb_show_regs(pc, tag, memt, memh)
        !          1703:        pci_chipset_tag_t pc;
        !          1704:        pcitag_t tag;
        !          1705:        bus_space_tag_t memt;
        !          1706:        bus_space_handle_t memh;
        !          1707: {
        !          1708:        int i;
        !          1709:        printf("PCI config regs:");
        !          1710:        for (i = 0; i < 0x50; i += 4) {
        !          1711:                if (i % 16 == 0) {
        !          1712:                        printf("\n 0x%02x:", i);
        !          1713:                }
        !          1714:                printf(" %08x", pci_conf_read(pc, tag, i));
        !          1715:        }
        !          1716:        for (i = 0x80; i < 0xb0; i += 4) {
        !          1717:                if (i % 16 == 0) {
        !          1718:                        printf("\n 0x%02x:", i);
        !          1719:                }
        !          1720:                printf(" %08x", pci_conf_read(pc, tag, i));
        !          1721:        }
        !          1722:
        !          1723:        if (memh == 0) {
        !          1724:                printf("\n");
        !          1725:                return;
        !          1726:        }
        !          1727:
        !          1728:        printf("\nsocket regs:");
        !          1729:        for (i = 0; i <= 0x10; i += 0x04) {
        !          1730:                printf(" %08x", bus_space_read_4(memt, memh, i));
        !          1731:        }
        !          1732:        printf("\nExCA regs:");
        !          1733:        for (i = 0; i < 0x08; ++i) {
        !          1734:                printf(" %02x", bus_space_read_1(memt, memh, 0x800 + i));
        !          1735:        }
        !          1736:        printf("\n");
        !          1737:        return;
        !          1738: }
        !          1739: #endif
        !          1740:
        !          1741: /*
        !          1742:  * cardbustag_t pccbb_make_tag(cardbus_chipset_tag_t cc,
        !          1743:  *                                    int busno, int devno, int function)
        !          1744:  *   This is the function to make a tag to access config space of
        !          1745:  *  a CardBus Card.  It works same as pci_conf_read.
        !          1746:  */
        !          1747: cardbustag_t
        !          1748: pccbb_make_tag(cc, busno, devno, function)
        !          1749:        cardbus_chipset_tag_t cc;
        !          1750:        int busno, devno, function;
        !          1751: {
        !          1752:        struct pccbb_softc *sc = (struct pccbb_softc *)cc;
        !          1753:
        !          1754:        return pci_make_tag(sc->sc_pc, busno, devno, function);
        !          1755: }
        !          1756:
        !          1757: void
        !          1758: pccbb_free_tag(cc, tag)
        !          1759:        cardbus_chipset_tag_t cc;
        !          1760:        cardbustag_t tag;
        !          1761: {
        !          1762: }
        !          1763:
        !          1764: /*
        !          1765:  * cardbusreg_t pccbb_conf_read(cardbus_chipset_tag_t cc,
        !          1766:  *                                     cardbustag_t tag, int offset)
        !          1767:  *   This is the function to read the config space of a CardBus Card.
        !          1768:  *  It works same as pci_conf_read.
        !          1769:  */
        !          1770: cardbusreg_t
        !          1771: pccbb_conf_read(cc, tag, offset)
        !          1772:        cardbus_chipset_tag_t cc;
        !          1773:        cardbustag_t tag;
        !          1774:        int offset;                    /* register offset */
        !          1775: {
        !          1776:        struct pccbb_softc *sc = (struct pccbb_softc *)cc;
        !          1777:
        !          1778:        return pci_conf_read(sc->sc_pc, tag, offset);
        !          1779: }
        !          1780:
        !          1781: /*
        !          1782:  * void pccbb_conf_write(cardbus_chipset_tag_t cc, cardbustag_t tag,
        !          1783:  *                              int offs, cardbusreg_t val)
        !          1784:  *   This is the function to write the config space of a CardBus Card.
        !          1785:  *  It works same as pci_conf_write.
        !          1786:  */
        !          1787: void
        !          1788: pccbb_conf_write(cc, tag, reg, val)
        !          1789:        cardbus_chipset_tag_t cc;
        !          1790:        cardbustag_t tag;
        !          1791:        int reg;                       /* register offset */
        !          1792:        cardbusreg_t val;
        !          1793: {
        !          1794:        struct pccbb_softc *sc = (struct pccbb_softc *)cc;
        !          1795:
        !          1796:        pci_conf_write(sc->sc_pc, tag, reg, val);
        !          1797: }
        !          1798:
        !          1799: #if 0
        !          1800: int
        !          1801: pccbb_new_pcmcia_io_alloc(pcmcia_chipset_handle_t pch,
        !          1802:     bus_addr_t start, bus_size_t size, bus_size_t align, bus_addr_t mask,
        !          1803:     int speed, int flags,
        !          1804:     bus_space_handle_t * iohp)
        !          1805: #endif
        !          1806: /*
        !          1807:  * int pccbb_pcmcia_io_alloc(pcmcia_chipset_handle_t pch,
        !          1808:  *                                  bus_addr_t start, bus_size_t size,
        !          1809:  *                                  bus_size_t align,
        !          1810:  *                                  struct pcmcia_io_handle *pcihp
        !          1811:  *
        !          1812:  * This function only allocates I/O region for pccard. This function
        !          1813:  * never maps the allocated region to pccard I/O area.
        !          1814:  *
        !          1815:  * XXX: The interface of this function is not very good, I believe.
        !          1816:  */
        !          1817: int
        !          1818: pccbb_pcmcia_io_alloc(pch, start, size, align, pcihp)
        !          1819:        pcmcia_chipset_handle_t pch;
        !          1820:        bus_addr_t start;              /* start address */
        !          1821:        bus_size_t size;
        !          1822:        bus_size_t align;
        !          1823:        struct pcmcia_io_handle *pcihp;
        !          1824: {
        !          1825:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          1826:        bus_addr_t ioaddr;
        !          1827:        int flags = 0;
        !          1828:        bus_space_tag_t iot;
        !          1829:        bus_space_handle_t ioh;
        !          1830:        bus_addr_t mask;
        !          1831:        rbus_tag_t rb;
        !          1832:
        !          1833:        if (align == 0) {
        !          1834:                align = size;          /* XXX: funny??? */
        !          1835:        }
        !          1836:
        !          1837:        if (start != 0) {
        !          1838:                /* XXX: assume all card decode lower 10 bits by its hardware */
        !          1839:                mask = 0x3ff;
        !          1840:                /* enforce to use only masked address */
        !          1841:                start &= mask;
        !          1842:        } else {
        !          1843:                /*
        !          1844:                 * calculate mask:
        !          1845:                 *  1. get the most significant bit of size (call it msb).
        !          1846:                 *  2. compare msb with the value of size.
        !          1847:                 *  3. if size is larger, shift msb left once.
        !          1848:                 *  4. obtain mask value to decrement msb.
        !          1849:                 */
        !          1850:                bus_size_t size_tmp = size;
        !          1851:                int shifts = 0;
        !          1852:
        !          1853:                mask = 1;
        !          1854:                while (size_tmp) {
        !          1855:                        ++shifts;
        !          1856:                        size_tmp >>= 1;
        !          1857:                }
        !          1858:                mask = (1 << shifts);
        !          1859:                if (mask < size) {
        !          1860:                        mask <<= 1;
        !          1861:                }
        !          1862:                mask--;
        !          1863:        }
        !          1864:
        !          1865:        /*
        !          1866:         * Allocate some arbitrary I/O space.
        !          1867:         */
        !          1868:
        !          1869:        iot = ((struct pccbb_softc *)(ph->ph_parent))->sc_iot;
        !          1870:
        !          1871:        rb = ((struct pccbb_softc *)(ph->ph_parent))->sc_rbus_iot;
        !          1872:        if (rbus_space_alloc(rb, start, size, mask, align, 0, &ioaddr, &ioh)) {
        !          1873:                return 1;
        !          1874:        }
        !          1875:
        !          1876:        pcihp->iot = iot;
        !          1877:        pcihp->ioh = ioh;
        !          1878:        pcihp->addr = ioaddr;
        !          1879:        pcihp->size = size;
        !          1880:        pcihp->flags = flags;
        !          1881:
        !          1882:        return 0;
        !          1883: }
        !          1884:
        !          1885: /*
        !          1886:  * int pccbb_pcmcia_io_free(pcmcia_chipset_handle_t pch,
        !          1887:  *                                 struct pcmcia_io_handle *pcihp)
        !          1888:  *
        !          1889:  * This function only frees I/O region for pccard.
        !          1890:  *
        !          1891:  * XXX: The interface of this function is not very good, I believe.
        !          1892:  */
        !          1893: void
        !          1894: pccbb_pcmcia_io_free(pch, pcihp)
        !          1895:        pcmcia_chipset_handle_t pch;
        !          1896:        struct pcmcia_io_handle *pcihp;
        !          1897: {
        !          1898:        bus_space_handle_t ioh = pcihp->ioh;
        !          1899:        bus_size_t size = pcihp->size;
        !          1900:
        !          1901:        struct pccbb_softc *sc =
        !          1902:            (struct pccbb_softc *)((struct pcic_handle *)pch)->ph_parent;
        !          1903:        rbus_tag_t rb = sc->sc_rbus_iot;
        !          1904:
        !          1905:        rbus_space_free(rb, ioh, size, NULL);
        !          1906: }
        !          1907:
        !          1908: /*
        !          1909:  * int pccbb_pcmcia_io_map(pcmcia_chipset_handle_t pch, int width,
        !          1910:  *                                bus_addr_t offset, bus_size_t size,
        !          1911:  *                                struct pcmcia_io_handle *pcihp,
        !          1912:  *                                int *windowp)
        !          1913:  *
        !          1914:  * This function maps the allocated I/O region to pccard. This function
        !          1915:  * never allocates any I/O region for pccard I/O area.  I don't
        !          1916:  * understand why the original authors of pcmciabus separated alloc and
        !          1917:  * map.  I believe the two must be unite.
        !          1918:  *
        !          1919:  * XXX: no wait timing control?
        !          1920:  */
        !          1921: int
        !          1922: pccbb_pcmcia_io_map(pch, width, offset, size, pcihp, windowp)
        !          1923:        pcmcia_chipset_handle_t pch;
        !          1924:        int width;
        !          1925:        bus_addr_t offset;
        !          1926:        bus_size_t size;
        !          1927:        struct pcmcia_io_handle *pcihp;
        !          1928:        int *windowp;
        !          1929: {
        !          1930:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          1931:        bus_addr_t ioaddr = pcihp->addr + offset;
        !          1932:        int i, win;
        !          1933: #if defined CBB_DEBUG
        !          1934:        static char *width_names[] = { "dynamic", "io8", "io16" };
        !          1935: #endif
        !          1936:
        !          1937:        /* Sanity check I/O handle. */
        !          1938:
        !          1939:        if (((struct pccbb_softc *)ph->ph_parent)->sc_iot != pcihp->iot) {
        !          1940:                panic("pccbb_pcmcia_io_map iot is bogus");
        !          1941:        }
        !          1942:
        !          1943:        /* XXX Sanity check offset/size. */
        !          1944:
        !          1945:        win = -1;
        !          1946:        for (i = 0; i < PCIC_IO_WINS; i++) {
        !          1947:                if ((ph->ioalloc & (1 << i)) == 0) {
        !          1948:                        win = i;
        !          1949:                        ph->ioalloc |= (1 << i);
        !          1950:                        break;
        !          1951:                }
        !          1952:        }
        !          1953:
        !          1954:        if (win == -1) {
        !          1955:                return 1;
        !          1956:        }
        !          1957:
        !          1958:        *windowp = win;
        !          1959:
        !          1960:        /* XXX this is pretty gross */
        !          1961:
        !          1962:        DPRINTF(("pccbb_pcmcia_io_map window %d %s port %lx+%lx\n",
        !          1963:            win, width_names[width], (u_long) ioaddr, (u_long) size));
        !          1964:
        !          1965:        /* XXX wtf is this doing here? */
        !          1966:
        !          1967: #if 0
        !          1968:        printf(" port 0x%lx", (u_long) ioaddr);
        !          1969:        if (size > 1) {
        !          1970:                printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
        !          1971:        }
        !          1972: #endif
        !          1973:
        !          1974:        ph->io[win].addr = ioaddr;
        !          1975:        ph->io[win].size = size;
        !          1976:        ph->io[win].width = width;
        !          1977:
        !          1978:        /* actual dirty register-value changing in the function below. */
        !          1979:        pccbb_pcmcia_do_io_map(ph, win);
        !          1980:
        !          1981:        return 0;
        !          1982: }
        !          1983:
        !          1984: /*
        !          1985:  * void pccbb_pcmcia_do_io_map(struct pcic_handle *h, int win)
        !          1986:  *
        !          1987:  * This function changes register-value to map I/O region for pccard.
        !          1988:  */
        !          1989: void
        !          1990: pccbb_pcmcia_do_io_map(ph, win)
        !          1991:        struct pcic_handle *ph;
        !          1992:        int win;
        !          1993: {
        !          1994:        static u_int8_t pcic_iowidth[3] = {
        !          1995:                PCIC_IOCTL_IO0_IOCS16SRC_CARD,
        !          1996:                PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
        !          1997:                    PCIC_IOCTL_IO0_DATASIZE_8BIT,
        !          1998:                PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
        !          1999:                    PCIC_IOCTL_IO0_DATASIZE_16BIT,
        !          2000:        };
        !          2001:
        !          2002: #define PCIC_SIA_START_LOW 0
        !          2003: #define PCIC_SIA_START_HIGH 1
        !          2004: #define PCIC_SIA_STOP_LOW 2
        !          2005: #define PCIC_SIA_STOP_HIGH 3
        !          2006:
        !          2007:        int regbase_win = 0x8 + win * 0x04;
        !          2008:        u_int8_t ioctl, enable;
        !          2009:
        !          2010:        DPRINTF(
        !          2011:            ("pccbb_pcmcia_do_io_map win %d addr 0x%lx size 0x%lx width %d\n",
        !          2012:            win, (long)ph->io[win].addr, (long)ph->io[win].size,
        !          2013:            ph->io[win].width * 8));
        !          2014:
        !          2015:        Pcic_write(ph, regbase_win + PCIC_SIA_START_LOW,
        !          2016:            ph->io[win].addr & 0xff);
        !          2017:        Pcic_write(ph, regbase_win + PCIC_SIA_START_HIGH,
        !          2018:            (ph->io[win].addr >> 8) & 0xff);
        !          2019:
        !          2020:        Pcic_write(ph, regbase_win + PCIC_SIA_STOP_LOW,
        !          2021:            (ph->io[win].addr + ph->io[win].size - 1) & 0xff);
        !          2022:        Pcic_write(ph, regbase_win + PCIC_SIA_STOP_HIGH,
        !          2023:            ((ph->io[win].addr + ph->io[win].size - 1) >> 8) & 0xff);
        !          2024:
        !          2025:        ioctl = Pcic_read(ph, PCIC_IOCTL);
        !          2026:        enable = Pcic_read(ph, PCIC_ADDRWIN_ENABLE);
        !          2027:        switch (win) {
        !          2028:        case 0:
        !          2029:                ioctl &= ~(PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT |
        !          2030:                    PCIC_IOCTL_IO0_IOCS16SRC_MASK |
        !          2031:                    PCIC_IOCTL_IO0_DATASIZE_MASK);
        !          2032:                ioctl |= pcic_iowidth[ph->io[win].width];
        !          2033:                enable |= PCIC_ADDRWIN_ENABLE_IO0;
        !          2034:                break;
        !          2035:        case 1:
        !          2036:                ioctl &= ~(PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT |
        !          2037:                    PCIC_IOCTL_IO1_IOCS16SRC_MASK |
        !          2038:                    PCIC_IOCTL_IO1_DATASIZE_MASK);
        !          2039:                ioctl |= (pcic_iowidth[ph->io[win].width] << 4);
        !          2040:                enable |= PCIC_ADDRWIN_ENABLE_IO1;
        !          2041:                break;
        !          2042:        }
        !          2043:        Pcic_write(ph, PCIC_IOCTL, ioctl);
        !          2044:        Pcic_write(ph, PCIC_ADDRWIN_ENABLE, enable);
        !          2045: #if defined CBB_DEBUG
        !          2046:        {
        !          2047:                u_int8_t start_low =
        !          2048:                    Pcic_read(ph, regbase_win + PCIC_SIA_START_LOW);
        !          2049:                u_int8_t start_high =
        !          2050:                    Pcic_read(ph, regbase_win + PCIC_SIA_START_HIGH);
        !          2051:                u_int8_t stop_low =
        !          2052:                    Pcic_read(ph, regbase_win + PCIC_SIA_STOP_LOW);
        !          2053:                u_int8_t stop_high =
        !          2054:                    Pcic_read(ph, regbase_win + PCIC_SIA_STOP_HIGH);
        !          2055:                printf
        !          2056:                    (" start %02x %02x, stop %02x %02x, ioctl %02x enable %02x\n",
        !          2057:                    start_low, start_high, stop_low, stop_high, ioctl, enable);
        !          2058:        }
        !          2059: #endif
        !          2060: }
        !          2061:
        !          2062: /*
        !          2063:  * void pccbb_pcmcia_io_unmap(pcmcia_chipset_handle_t *h, int win)
        !          2064:  *
        !          2065:  * This function unmaps I/O region.  No return value.
        !          2066:  */
        !          2067: void
        !          2068: pccbb_pcmcia_io_unmap(pch, win)
        !          2069:        pcmcia_chipset_handle_t pch;
        !          2070:        int win;
        !          2071: {
        !          2072:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2073:        int reg;
        !          2074:
        !          2075:        if (win >= PCIC_IO_WINS || win < 0) {
        !          2076:                panic("pccbb_pcmcia_io_unmap: window out of range");
        !          2077:        }
        !          2078:
        !          2079:        reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE);
        !          2080:        switch (win) {
        !          2081:        case 0:
        !          2082:                reg &= ~PCIC_ADDRWIN_ENABLE_IO0;
        !          2083:                break;
        !          2084:        case 1:
        !          2085:                reg &= ~PCIC_ADDRWIN_ENABLE_IO1;
        !          2086:                break;
        !          2087:        }
        !          2088:        Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg);
        !          2089:
        !          2090:        ph->ioalloc &= ~(1 << win);
        !          2091: }
        !          2092:
        !          2093: /*
        !          2094:  * void pccbb_pcmcia_wait_ready(struct pcic_handle *ph)
        !          2095:  *
        !          2096:  * This function enables the card.  All information is stored in
        !          2097:  * the first argument, pcmcia_chipset_handle_t.
        !          2098:  */
        !          2099: void
        !          2100: pccbb_pcmcia_wait_ready(ph)
        !          2101:        struct pcic_handle *ph;
        !          2102: {
        !          2103:        int i;
        !          2104:
        !          2105:        DPRINTF(("pccbb_pcmcia_wait_ready: status 0x%02x\n",
        !          2106:            Pcic_read(ph, PCIC_IF_STATUS)));
        !          2107:
        !          2108:        for (i = 0; i < 10000; i++) {
        !          2109:                if (Pcic_read(ph, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY) {
        !          2110:                        return;
        !          2111:                }
        !          2112:                delay(500);
        !          2113: #ifdef CBB_DEBUG
        !          2114:                if ((i > 5000) && (i % 100 == 99))
        !          2115:                        printf(".");
        !          2116: #endif
        !          2117:        }
        !          2118:
        !          2119: #ifdef DIAGNOSTIC
        !          2120:        printf("pcic_wait_ready: ready never happened, status = %02x\n",
        !          2121:            Pcic_read(ph, PCIC_IF_STATUS));
        !          2122: #endif
        !          2123: }
        !          2124:
        !          2125: /*
        !          2126:  * void pccbb_pcmcia_socket_enable(pcmcia_chipset_handle_t pch)
        !          2127:  *
        !          2128:  * This function enables the card.  All information is stored in
        !          2129:  * the first argument, pcmcia_chipset_handle_t.
        !          2130:  */
        !          2131: void
        !          2132: pccbb_pcmcia_socket_enable(pch)
        !          2133:        pcmcia_chipset_handle_t pch;
        !          2134: {
        !          2135:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2136:        struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
        !          2137:        int cardtype, win;
        !          2138:        u_int8_t power, intr;
        !          2139:        pcireg_t spsr;
        !          2140:        int voltage;
        !          2141:
        !          2142:        /* this bit is mostly stolen from pcic_attach_card */
        !          2143:
        !          2144:        DPRINTF(("pccbb_pcmcia_socket_enable: "));
        !          2145:
        !          2146:        /* get card Vcc info */
        !          2147:
        !          2148:        spsr =
        !          2149:            bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
        !          2150:            CB_SOCKET_STAT);
        !          2151:        if (spsr & CB_SOCKET_STAT_5VCARD) {
        !          2152:                DPRINTF(("5V card\n"));
        !          2153:                voltage = CARDBUS_VCC_5V | CARDBUS_VPP_VCC;
        !          2154:        } else if (spsr & CB_SOCKET_STAT_3VCARD) {
        !          2155:                DPRINTF(("3V card\n"));
        !          2156:                voltage = CARDBUS_VCC_3V | CARDBUS_VPP_VCC;
        !          2157:        } else {
        !          2158:                printf("?V card, 0x%x\n", spsr);        /* XXX */
        !          2159:                return;
        !          2160:        }
        !          2161:
        !          2162:        /* disable socket i/o: negate output enable bit */
        !          2163:
        !          2164:        power = 0;
        !          2165:        Pcic_write(ph, PCIC_PWRCTL, power);
        !          2166:
        !          2167:        /* power down the socket to reset it, clear the card reset pin */
        !          2168:
        !          2169:        pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
        !          2170:
        !          2171:        /*
        !          2172:         * wait 200ms until power fails (Tpf).  Then, wait 100ms since
        !          2173:         * we are changing Vcc (Toff).
        !          2174:         */
        !          2175:        /* delay(300*1000); too much */
        !          2176:
        !          2177:        /* assert reset bit */
        !          2178:        intr = Pcic_read(ph, PCIC_INTR);
        !          2179:        intr &= ~(PCIC_INTR_RESET | PCIC_INTR_CARDTYPE_MASK);
        !          2180:        Pcic_write(ph, PCIC_INTR, intr);
        !          2181:
        !          2182:        /* power up the socket and output enable */
        !          2183:        power = Pcic_read(ph, PCIC_PWRCTL);
        !          2184:        power |= PCIC_PWRCTL_OE;
        !          2185:        Pcic_write(ph, PCIC_PWRCTL, power);
        !          2186:        pccbb_power(sc, voltage);
        !          2187:
        !          2188:        /*
        !          2189:         * hold RESET at least 10us.
        !          2190:         */
        !          2191:        delay(10);
        !          2192:        delay(2 * 1000);               /* XXX: TI1130 requires it. */
        !          2193:        delay(20 * 1000);              /* XXX: TI1130 requires it. */
        !          2194:
        !          2195:        /* clear the reset flag */
        !          2196:
        !          2197:        intr |= PCIC_INTR_RESET;
        !          2198:        Pcic_write(ph, PCIC_INTR, intr);
        !          2199:
        !          2200:        /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
        !          2201:
        !          2202:        delay(20000);
        !          2203:
        !          2204:        /* wait for the chip to finish initializing */
        !          2205:
        !          2206:        pccbb_pcmcia_wait_ready(ph);
        !          2207:
        !          2208:        /* zero out the address windows */
        !          2209:
        !          2210:        Pcic_write(ph, PCIC_ADDRWIN_ENABLE, 0);
        !          2211:
        !          2212:        /* set the card type */
        !          2213:
        !          2214:        cardtype = pcmcia_card_gettype(ph->pcmcia);
        !          2215:
        !          2216:        intr |= ((cardtype == PCMCIA_IFTYPE_IO) ?
        !          2217:            PCIC_INTR_CARDTYPE_IO : PCIC_INTR_CARDTYPE_MEM);
        !          2218:        Pcic_write(ph, PCIC_INTR, intr);
        !          2219:
        !          2220:        DPRINTF(("%s: pccbb_pcmcia_socket_enable %02x cardtype %s %02x\n",
        !          2221:            ph->ph_parent->dv_xname, ph->sock,
        !          2222:            ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), intr));
        !          2223:
        !          2224:        /* reinstall all the memory and io mappings */
        !          2225:
        !          2226:        for (win = 0; win < PCIC_MEM_WINS; ++win) {
        !          2227:                if (ph->memalloc & (1 << win)) {
        !          2228:                        pccbb_pcmcia_do_mem_map(ph, win);
        !          2229:                }
        !          2230:        }
        !          2231:
        !          2232:        for (win = 0; win < PCIC_IO_WINS; ++win) {
        !          2233:                if (ph->ioalloc & (1 << win)) {
        !          2234:                        pccbb_pcmcia_do_io_map(ph, win);
        !          2235:                }
        !          2236:        }
        !          2237: }
        !          2238:
        !          2239: /*
        !          2240:  * void pccbb_pcmcia_socket_disable(pcmcia_chipset_handle_t *ph)
        !          2241:  *
        !          2242:  * This function disables the card.  All information is stored in
        !          2243:  * the first argument, pcmcia_chipset_handle_t.
        !          2244:  */
        !          2245: void
        !          2246: pccbb_pcmcia_socket_disable(pch)
        !          2247:        pcmcia_chipset_handle_t pch;
        !          2248: {
        !          2249:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2250:        struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
        !          2251:        u_int8_t power, intr;
        !          2252:
        !          2253:        DPRINTF(("pccbb_pcmcia_socket_disable\n"));
        !          2254:
        !          2255:        /* reset signal asserting... */
        !          2256:
        !          2257:        intr = Pcic_read(ph, PCIC_INTR);
        !          2258:        intr &= ~(PCIC_INTR_CARDTYPE_MASK);
        !          2259:        Pcic_write(ph, PCIC_INTR, intr);
        !          2260:        delay(2 * 1000);
        !          2261:
        !          2262:        /* power down the socket */
        !          2263:        power = Pcic_read(ph, PCIC_PWRCTL);
        !          2264:        power &= ~PCIC_PWRCTL_OE;
        !          2265:        Pcic_write(ph, PCIC_PWRCTL, power);
        !          2266:        pccbb_power(sc, CARDBUS_VCC_0V | CARDBUS_VPP_0V);
        !          2267:        /*
        !          2268:         * wait 300ms until power fails (Tpf).
        !          2269:         */
        !          2270:        delay(300 * 1000);
        !          2271: }
        !          2272:
        !          2273: /*
        !          2274:  * int pccbb_pcmcia_card_detect(pcmcia_chipset_handle_t *ph)
        !          2275:  *
        !          2276:  * This function detects whether a card is in the slot or not.
        !          2277:  * If a card is inserted, return 1.  Otherwise, return 0.
        !          2278:  */
        !          2279: int
        !          2280: pccbb_pcmcia_card_detect(pch)
        !          2281:        pcmcia_chipset_handle_t pch;
        !          2282: {
        !          2283:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2284:        struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
        !          2285:
        !          2286:        DPRINTF(("pccbb_pcmcia_card_detect\n"));
        !          2287:        return pccbb_detect_card(sc) == 1 ? 1 : 0;
        !          2288: }
        !          2289:
        !          2290: #if 0
        !          2291: int
        !          2292: pccbb_new_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch,
        !          2293:     bus_addr_t start, bus_size_t size, bus_size_t align, int speed, int flags,
        !          2294:     bus_space_tag_t * memtp bus_space_handle_t * memhp)
        !          2295: #endif
        !          2296: /*
        !          2297:  * int pccbb_pcmcia_mem_alloc(pcmcia_chipset_handle_t pch,
        !          2298:  *                                   bus_size_t size,
        !          2299:  *                                   struct pcmcia_mem_handle *pcmhp)
        !          2300:  *
        !          2301:  * This function only allocates memory region for pccard. This
        !          2302:  * function never maps the allocated region to pccard memory area.
        !          2303:  *
        !          2304:  * XXX: Why the argument of start address is not in?
        !          2305:  */
        !          2306: int
        !          2307: pccbb_pcmcia_mem_alloc(pch, size, pcmhp)
        !          2308:        pcmcia_chipset_handle_t pch;
        !          2309:        bus_size_t size;
        !          2310:        struct pcmcia_mem_handle *pcmhp;
        !          2311: {
        !          2312:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2313:        bus_space_handle_t memh;
        !          2314:        bus_addr_t addr;
        !          2315:        bus_size_t sizepg;
        !          2316:        struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
        !          2317:        rbus_tag_t rb;
        !          2318:
        !          2319:        /* out of sc->memh, allocate as many pages as necessary */
        !          2320:
        !          2321:        /* convert size to PCIC pages */
        !          2322:        /*
        !          2323:         * This is not enough; when the requested region is on the page
        !          2324:         * boundaries, this may calculate wrong result.
        !          2325:         */
        !          2326:        sizepg = (size + (PCIC_MEM_PAGESIZE - 1)) / PCIC_MEM_PAGESIZE;
        !          2327: #if 0
        !          2328:        if (sizepg > PCIC_MAX_MEM_PAGES) {
        !          2329:                return 1;
        !          2330:        }
        !          2331: #endif
        !          2332:
        !          2333:        if (!(sc->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32)) {
        !          2334:                return 1;
        !          2335:        }
        !          2336:
        !          2337:        addr = 0;                      /* XXX gcc -Wuninitialized */
        !          2338:
        !          2339:        rb = sc->sc_rbus_memt;
        !          2340:        if (rbus_space_alloc(rb, 0, sizepg * PCIC_MEM_PAGESIZE,
        !          2341:            sizepg * PCIC_MEM_PAGESIZE - 1, PCIC_MEM_PAGESIZE, 0,
        !          2342:            &addr, &memh)) {
        !          2343:                return 1;
        !          2344:        }
        !          2345:
        !          2346:        DPRINTF(
        !          2347:            ("pccbb_pcmcia_alloc_mem: addr 0x%lx size 0x%lx, realsize 0x%lx\n",
        !          2348:            addr, size, sizepg * PCIC_MEM_PAGESIZE));
        !          2349:
        !          2350:        pcmhp->memt = sc->sc_memt;
        !          2351:        pcmhp->memh = memh;
        !          2352:        pcmhp->addr = addr;
        !          2353:        pcmhp->size = size;
        !          2354:        pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
        !          2355:        /* What is mhandle?  I feel it is very dirty and it must go trush. */
        !          2356:        pcmhp->mhandle = 0;
        !          2357:        /* No offset???  Funny. */
        !          2358:
        !          2359:        return 0;
        !          2360: }
        !          2361:
        !          2362: /*
        !          2363:  * void pccbb_pcmcia_mem_free(pcmcia_chipset_handle_t pch,
        !          2364:  *                                   struct pcmcia_mem_handle *pcmhp)
        !          2365:  *
        !          2366:  * This function release the memory space allocated by the function
        !          2367:  * pccbb_pcmcia_mem_alloc().
        !          2368:  */
        !          2369: void
        !          2370: pccbb_pcmcia_mem_free(pch, pcmhp)
        !          2371:        pcmcia_chipset_handle_t pch;
        !          2372:        struct pcmcia_mem_handle *pcmhp;
        !          2373: {
        !          2374:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2375:        struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
        !          2376:
        !          2377:        rbus_space_free(sc->sc_rbus_memt, pcmhp->memh, pcmhp->realsize, NULL);
        !          2378: }
        !          2379:
        !          2380: /*
        !          2381:  * void pccbb_pcmcia_do_mem_map(struct pcic_handle *ph, int win)
        !          2382:  *
        !          2383:  * This function release the memory space allocated by the function
        !          2384:  * pccbb_pcmcia_mem_alloc().
        !          2385:  */
        !          2386: void
        !          2387: pccbb_pcmcia_do_mem_map(ph, win)
        !          2388:        struct pcic_handle *ph;
        !          2389:        int win;
        !          2390: {
        !          2391:        int regbase_win;
        !          2392:        bus_addr_t phys_addr;
        !          2393:        bus_addr_t phys_end;
        !          2394:
        !          2395: #define PCIC_SMM_START_LOW 0
        !          2396: #define PCIC_SMM_START_HIGH 1
        !          2397: #define PCIC_SMM_STOP_LOW 2
        !          2398: #define PCIC_SMM_STOP_HIGH 3
        !          2399: #define PCIC_CMA_LOW 4
        !          2400: #define PCIC_CMA_HIGH 5
        !          2401:
        !          2402:        u_int8_t start_low, start_high = 0;
        !          2403:        u_int8_t stop_low, stop_high;
        !          2404:        u_int8_t off_low, off_high;
        !          2405:        u_int8_t mem_window;
        !          2406:        int reg;
        !          2407:
        !          2408:        regbase_win = 0x10 + win * 0x08;
        !          2409:
        !          2410:        phys_addr = ph->mem[win].addr;
        !          2411:        phys_end = phys_addr + ph->mem[win].size;
        !          2412:
        !          2413:        DPRINTF(("pccbb_pcmcia_do_mem_map: start 0x%lx end 0x%lx off 0x%lx\n",
        !          2414:            phys_addr, phys_end, ph->mem[win].offset));
        !          2415:
        !          2416: #define PCIC_MEMREG_LSB_SHIFT PCIC_SYSMEM_ADDRX_SHIFT
        !          2417: #define PCIC_MEMREG_MSB_SHIFT (PCIC_SYSMEM_ADDRX_SHIFT + 8)
        !          2418: #define PCIC_MEMREG_WIN_SHIFT (PCIC_SYSMEM_ADDRX_SHIFT + 12)
        !          2419:
        !          2420:        /* bit 19:12 */
        !          2421:        start_low = (phys_addr >> PCIC_MEMREG_LSB_SHIFT) & 0xff;
        !          2422:        /* bit 23:20 and bit 7 on */
        !          2423:        start_high = ((phys_addr >> PCIC_MEMREG_MSB_SHIFT) & 0x0f)
        !          2424:            | PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT; /* bit 7 on */
        !          2425:        /* bit 31:24, for 32-bit address */
        !          2426:        mem_window = (phys_addr >> PCIC_MEMREG_WIN_SHIFT) & 0xff;
        !          2427:
        !          2428:        Pcic_write(ph, regbase_win + PCIC_SMM_START_LOW, start_low);
        !          2429:        Pcic_write(ph, regbase_win + PCIC_SMM_START_HIGH, start_high);
        !          2430:
        !          2431:        if (((struct pccbb_softc *)ph->
        !          2432:            ph_parent)->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) {
        !          2433:                Pcic_write(ph, 0x40 + win, mem_window);
        !          2434:        }
        !          2435:
        !          2436:        stop_low = (phys_end >> PCIC_MEMREG_LSB_SHIFT) & 0xff;
        !          2437:        stop_high = ((phys_end >> PCIC_MEMREG_MSB_SHIFT) & 0x0f)
        !          2438:            | PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2; /* wait 2 cycles */
        !          2439:        /* XXX Geee, WAIT2!! Crazy!!  I must rewrite this routine. */
        !          2440:
        !          2441:        Pcic_write(ph, regbase_win + PCIC_SMM_STOP_LOW, stop_low);
        !          2442:        Pcic_write(ph, regbase_win + PCIC_SMM_STOP_HIGH, stop_high);
        !          2443:
        !          2444:        off_low = (ph->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff;
        !          2445:        off_high = ((ph->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8))
        !          2446:            & PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK)
        !          2447:            | ((ph->mem[win].kind == PCMCIA_MEM_ATTR) ?
        !          2448:            PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0);
        !          2449:
        !          2450:        Pcic_write(ph, regbase_win + PCIC_CMA_LOW, off_low);
        !          2451:        Pcic_write(ph, regbase_win + PCIC_CMA_HIGH, off_high);
        !          2452:
        !          2453:        reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE);
        !          2454:        reg |= ((1 << win) | PCIC_ADDRWIN_ENABLE_MEMCS16);
        !          2455:        Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg);
        !          2456:
        !          2457: #if defined CBB_DEBUG
        !          2458:        {
        !          2459:                int r1, r2, r3, r4, r5, r6, r7 = 0;
        !          2460:
        !          2461:                r1 = Pcic_read(ph, regbase_win + PCIC_SMM_START_LOW);
        !          2462:                r2 = Pcic_read(ph, regbase_win + PCIC_SMM_START_HIGH);
        !          2463:                r3 = Pcic_read(ph, regbase_win + PCIC_SMM_STOP_LOW);
        !          2464:                r4 = Pcic_read(ph, regbase_win + PCIC_SMM_STOP_HIGH);
        !          2465:                r5 = Pcic_read(ph, regbase_win + PCIC_CMA_LOW);
        !          2466:                r6 = Pcic_read(ph, regbase_win + PCIC_CMA_HIGH);
        !          2467:                if (((struct pccbb_softc *)(ph->
        !          2468:                    ph_parent))->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) {
        !          2469:                        r7 = Pcic_read(ph, 0x40 + win);
        !          2470:                }
        !          2471:
        !          2472:                DPRINTF(("pccbb_pcmcia_do_mem_map window %d: %02x%02x %02x%02x "
        !          2473:                    "%02x%02x", win, r1, r2, r3, r4, r5, r6));
        !          2474:                if (((struct pccbb_softc *)(ph->
        !          2475:                    ph_parent))->sc_pcmcia_flags & PCCBB_PCMCIA_MEM_32) {
        !          2476:                        DPRINTF((" %02x", r7));
        !          2477:                }
        !          2478:                DPRINTF(("\n"));
        !          2479:        }
        !          2480: #endif
        !          2481: }
        !          2482:
        !          2483: /*
        !          2484:  * int pccbb_pcmcia_mem_map(pcmcia_chipset_handle_t pch, int kind,
        !          2485:  *                                 bus_addr_t card_addr, bus_size_t size,
        !          2486:  *                                 struct pcmcia_mem_handle *pcmhp,
        !          2487:  *                                 bus_size_t *offsetp, int *windowp)
        !          2488:  *
        !          2489:  * This function maps memory space allocated by the function
        !          2490:  * pccbb_pcmcia_mem_alloc().
        !          2491:  */
        !          2492: int
        !          2493: pccbb_pcmcia_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
        !          2494:        pcmcia_chipset_handle_t pch;
        !          2495:        int kind;
        !          2496:        bus_addr_t card_addr;
        !          2497:        bus_size_t size;
        !          2498:        struct pcmcia_mem_handle *pcmhp;
        !          2499:        bus_size_t *offsetp;
        !          2500:        int *windowp;
        !          2501: {
        !          2502:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2503:        bus_addr_t busaddr;
        !          2504:        long card_offset;
        !          2505:        int win;
        !          2506:
        !          2507:        for (win = 0; win < PCIC_MEM_WINS; ++win) {
        !          2508:                if ((ph->memalloc & (1 << win)) == 0) {
        !          2509:                        ph->memalloc |= (1 << win);
        !          2510:                        break;
        !          2511:                }
        !          2512:        }
        !          2513:
        !          2514:        if (win == PCIC_MEM_WINS) {
        !          2515:                return 1;
        !          2516:        }
        !          2517:
        !          2518:        *windowp = win;
        !          2519:
        !          2520:        /* XXX this is pretty gross */
        !          2521:
        !          2522:        if (((struct pccbb_softc *)ph->ph_parent)->sc_memt != pcmhp->memt) {
        !          2523:                panic("pccbb_pcmcia_mem_map memt is bogus");
        !          2524:        }
        !          2525:
        !          2526:        busaddr = pcmhp->addr;
        !          2527:
        !          2528:        /*
        !          2529:         * compute the address offset to the pcmcia address space for the
        !          2530:         * pcic.  this is intentionally signed.  The masks and shifts below
        !          2531:         * will cause TRT to happen in the pcic registers.  Deal with making
        !          2532:         * sure the address is aligned, and return the alignment offset.
        !          2533:         */
        !          2534:
        !          2535:        *offsetp = card_addr % PCIC_MEM_PAGESIZE;
        !          2536:        card_addr -= *offsetp;
        !          2537:
        !          2538:        DPRINTF(("pccbb_pcmcia_mem_map window %d bus %lx+%lx+%lx at card addr "
        !          2539:            "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
        !          2540:            (u_long) card_addr));
        !          2541:
        !          2542:        /*
        !          2543:         * include the offset in the size, and decrement size by one, since
        !          2544:         * the hw wants start/stop
        !          2545:         */
        !          2546:        size += *offsetp - 1;
        !          2547:
        !          2548:        card_offset = (((long)card_addr) - ((long)busaddr));
        !          2549:
        !          2550:        ph->mem[win].addr = busaddr;
        !          2551:        ph->mem[win].size = size;
        !          2552:        ph->mem[win].offset = card_offset;
        !          2553:        ph->mem[win].kind = kind;
        !          2554:
        !          2555:        pccbb_pcmcia_do_mem_map(ph, win);
        !          2556:
        !          2557:        return 0;
        !          2558: }
        !          2559:
        !          2560: /*
        !          2561:  * int pccbb_pcmcia_mem_unmap(pcmcia_chipset_handle_t pch,
        !          2562:  *                                   int window)
        !          2563:  *
        !          2564:  * This function unmaps memory space which mapped by the function
        !          2565:  * pccbb_pcmcia_mem_map().
        !          2566:  */
        !          2567: void
        !          2568: pccbb_pcmcia_mem_unmap(pch, window)
        !          2569:        pcmcia_chipset_handle_t pch;
        !          2570:        int window;
        !          2571: {
        !          2572:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2573:        int reg;
        !          2574:
        !          2575:        if (window >= PCIC_MEM_WINS) {
        !          2576:                panic("pccbb_pcmcia_mem_unmap: window out of range");
        !          2577:        }
        !          2578:
        !          2579:        reg = Pcic_read(ph, PCIC_ADDRWIN_ENABLE);
        !          2580:        reg &= ~(1 << window);
        !          2581:        Pcic_write(ph, PCIC_ADDRWIN_ENABLE, reg);
        !          2582:
        !          2583:        ph->memalloc &= ~(1 << window);
        !          2584: }
        !          2585:
        !          2586: #if defined PCCBB_PCMCIA_POLL
        !          2587: struct pccbb_poll_str {
        !          2588:        void *arg;
        !          2589:        int (*func)(void *);
        !          2590:        int level;
        !          2591:        struct pcic_handle *ph;
        !          2592:        int count;
        !          2593:        int num;
        !          2594: };
        !          2595:
        !          2596: static struct pccbb_poll_str pccbb_poll[10];
        !          2597: static int pccbb_poll_n = 0;
        !          2598: static struct timeout pccbb_poll_timeout;
        !          2599:
        !          2600: void pccbb_pcmcia_poll(void *arg);
        !          2601:
        !          2602: void
        !          2603: pccbb_pcmcia_poll(arg)
        !          2604:        void *arg;
        !          2605: {
        !          2606:        struct pccbb_poll_str *poll = arg;
        !          2607:        struct pcic_handle *ph = poll->ph;
        !          2608:        struct pccbb_softc *sc = ph->sc;
        !          2609:        int s;
        !          2610:        u_int32_t spsr;                /* socket present-state reg */
        !          2611:
        !          2612:        timeout_set(&pccbb_poll_timeout, pccbb_pcmcia_poll, arg);
        !          2613:        timeout_add(&pccbb_poll_timeout, hz * 2);
        !          2614:        switch (poll->level) {
        !          2615:        case IPL_NET:
        !          2616:                s = splnet();
        !          2617:                break;
        !          2618:        case IPL_BIO:
        !          2619:                s = splbio();
        !          2620:                break;
        !          2621:        case IPL_TTY:                  /* fallthrough */
        !          2622:        default:
        !          2623:                s = spltty();
        !          2624:                break;
        !          2625:        }
        !          2626:
        !          2627:        spsr =
        !          2628:            bus_space_read_4(sc->sc_base_memt, sc->sc_base_memh,
        !          2629:            CB_SOCKET_STAT);
        !          2630:
        !          2631: #if defined PCCBB_PCMCIA_POLL_ONLY && defined LEVEL2
        !          2632:        if (!(spsr & 0x40))            /* CINT low */
        !          2633: #else
        !          2634:        if (1)
        !          2635: #endif
        !          2636:        {
        !          2637:                if ((*poll->func) (poll->arg) > 0) {
        !          2638:                        ++poll->count;
        !          2639:        /* printf("intr: reported from poller, 0x%x\n", spsr); */
        !          2640: #if defined LEVEL2
        !          2641:                } else {
        !          2642:                        printf("intr: miss! 0x%x\n", spsr);
        !          2643: #endif
        !          2644:                }
        !          2645:        }
        !          2646:        splx(s);
        !          2647: }
        !          2648: #endif /* defined CB_PCMCIA_POLL */
        !          2649:
        !          2650: /*
        !          2651:  * void *pccbb_pcmcia_intr_establish(pcmcia_chipset_handle_t pch,
        !          2652:  *                                          struct pcmcia_function *pf,
        !          2653:  *                                          int ipl,
        !          2654:  *                                          int (*func)(void *),
        !          2655:  *                                          void *arg);
        !          2656:  *
        !          2657:  * This function enables PC-Card interrupt.  PCCBB uses PCI interrupt line.
        !          2658:  */
        !          2659: void *
        !          2660: pccbb_pcmcia_intr_establish(pch, pf, ipl, func, arg, xname)
        !          2661:        pcmcia_chipset_handle_t pch;
        !          2662:        struct pcmcia_function *pf;
        !          2663:        int ipl;
        !          2664:        int (*func)(void *);
        !          2665:        void *arg;
        !          2666:        char *xname;
        !          2667: {
        !          2668:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2669:        struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
        !          2670:
        !          2671:        if (!(pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)) {
        !          2672:                /* what should I do? */
        !          2673:                if ((pf->cfe->flags & PCMCIA_CFE_IRQLEVEL)) {
        !          2674:                        DPRINTF(
        !          2675:                            ("%s does not provide edge nor pulse interrupt\n",
        !          2676:                            sc->sc_dev.dv_xname));
        !          2677:                        return NULL;
        !          2678:                }
        !          2679:                /*
        !          2680:                 * XXX Noooooo!  The interrupt flag must set properly!!
        !          2681:                 * dumb pcmcia driver!!
        !          2682:                 */
        !          2683:        }
        !          2684:
        !          2685:        return pccbb_intr_establish(sc, -1, ipl, func, arg, xname);
        !          2686: }
        !          2687:
        !          2688: /*
        !          2689:  * void pccbb_pcmcia_intr_disestablish(pcmcia_chipset_handle_t pch,
        !          2690:  *                                            void *ih)
        !          2691:  *
        !          2692:  * This function disables PC-Card interrupt.
        !          2693:  */
        !          2694: void
        !          2695: pccbb_pcmcia_intr_disestablish(pch, ih)
        !          2696:        pcmcia_chipset_handle_t pch;
        !          2697:        void *ih;
        !          2698: {
        !          2699:        struct pcic_handle *ph = (struct pcic_handle *)pch;
        !          2700:        struct pccbb_softc *sc = (struct pccbb_softc *)ph->ph_parent;
        !          2701:
        !          2702:        pccbb_intr_disestablish(sc, ih);
        !          2703: }
        !          2704:
        !          2705: const char *
        !          2706: pccbb_pcmcia_intr_string(pch, ih)
        !          2707:        pcmcia_chipset_handle_t pch;
        !          2708:        void *ih;
        !          2709: {
        !          2710:        if (ih == NULL)
        !          2711:                return "couldn't establish interrupt";
        !          2712:        else
        !          2713:                return "";      /* card shares interrupt of the bridge */
        !          2714: }
        !          2715:
        !          2716: /*
        !          2717:  * int
        !          2718:  * pccbb_rbus_cb_space_alloc(cardbus_chipset_tag_t ct, rbus_tag_t rb,
        !          2719:  *                         bus_addr_t addr, bus_size_t size,
        !          2720:  *                         bus_addr_t mask, bus_size_t align,
        !          2721:  *                         int flags, bus_addr_t *addrp;
        !          2722:  *                         bus_space_handle_t *bshp)
        !          2723:  *
        !          2724:  *   This function allocates a portion of memory or io space for
        !          2725:  *   clients.  This function is called from CardBus card drivers.
        !          2726:  */
        !          2727: int
        !          2728: pccbb_rbus_cb_space_alloc(ct, rb, addr, size, mask, align, flags, addrp, bshp)
        !          2729:        cardbus_chipset_tag_t ct;
        !          2730:        rbus_tag_t rb;
        !          2731:        bus_addr_t addr;
        !          2732:        bus_size_t size;
        !          2733:        bus_addr_t mask;
        !          2734:        bus_size_t align;
        !          2735:        int flags;
        !          2736:        bus_addr_t *addrp;
        !          2737:        bus_space_handle_t *bshp;
        !          2738: {
        !          2739:        struct pccbb_softc *sc = (struct pccbb_softc *)ct;
        !          2740:
        !          2741:        DPRINTF(
        !          2742:            ("pccbb_rbus_cb_space_alloc: adr %lx, size %lx, mask %lx, align %lx\n",
        !          2743:            addr, size, mask, align));
        !          2744:
        !          2745:        if (align == 0) {
        !          2746:                align = size;
        !          2747:        }
        !          2748:
        !          2749:        if (rb->rb_bt == sc->sc_memt) {
        !          2750:                if (align < 16) {
        !          2751:                        return 1;
        !          2752:                }
        !          2753:        } else if (rb->rb_bt == sc->sc_iot) {
        !          2754:                if (align < 4) {
        !          2755:                        return 1;
        !          2756:                }
        !          2757:                /* XXX: hack for avoiding ISA image */
        !          2758:                if (mask < 0x0100) {
        !          2759:                        mask = 0x3ff;
        !          2760:                        addr = 0x300;
        !          2761:                }
        !          2762:
        !          2763:        } else {
        !          2764:                DPRINTF(
        !          2765:                    ("pccbb_rbus_cb_space_alloc: Bus space tag %x is NOT used.\n",
        !          2766:                    rb->rb_bt));
        !          2767:                return 1;
        !          2768:                /* XXX: panic here? */
        !          2769:        }
        !          2770:
        !          2771:        if (rbus_space_alloc(rb, addr, size, mask, align, flags, addrp, bshp)) {
        !          2772:                printf("%s: <rbus> no bus space\n", sc->sc_dev.dv_xname);
        !          2773:                return 1;
        !          2774:        }
        !          2775:
        !          2776:        pccbb_open_win(sc, rb->rb_bt, *addrp, size, *bshp, 0);
        !          2777:
        !          2778:        return 0;
        !          2779: }
        !          2780:
        !          2781: /*
        !          2782:  * int
        !          2783:  * pccbb_rbus_cb_space_free(cardbus_chipset_tag_t *ct, rbus_tag_t rb,
        !          2784:  *                        bus_space_handle_t *bshp, bus_size_t size);
        !          2785:  *
        !          2786:  *   This function is called from CardBus card drivers.
        !          2787:  */
        !          2788: int
        !          2789: pccbb_rbus_cb_space_free(ct, rb, bsh, size)
        !          2790:        cardbus_chipset_tag_t ct;
        !          2791:        rbus_tag_t rb;
        !          2792:        bus_space_handle_t bsh;
        !          2793:        bus_size_t size;
        !          2794: {
        !          2795:        struct pccbb_softc *sc = (struct pccbb_softc *)ct;
        !          2796:        bus_space_tag_t bt = rb->rb_bt;
        !          2797:
        !          2798:        pccbb_close_win(sc, bt, bsh, size);
        !          2799:
        !          2800:        if (bt == sc->sc_memt) {
        !          2801:        } else if (bt == sc->sc_iot) {
        !          2802:        } else {
        !          2803:                return 1;
        !          2804:                /* XXX: panic here? */
        !          2805:        }
        !          2806:
        !          2807:        return rbus_space_free(rb, bsh, size, NULL);
        !          2808: }
        !          2809:
        !          2810: int
        !          2811: pccbb_open_win(sc, bst, addr, size, bsh, flags)
        !          2812:        struct pccbb_softc *sc;
        !          2813:        bus_space_tag_t bst;
        !          2814:        bus_addr_t addr;
        !          2815:        bus_size_t size;
        !          2816:        bus_space_handle_t bsh;
        !          2817:        int flags;
        !          2818: {
        !          2819:        struct pccbb_win_chain_head *head;
        !          2820:        bus_addr_t align;
        !          2821:
        !          2822:        head = &sc->sc_iowindow;
        !          2823:        align = 0x04;
        !          2824:        if (sc->sc_memt == bst) {
        !          2825:                head = &sc->sc_memwindow;
        !          2826:                align = 0x1000;
        !          2827:                DPRINTF(("using memory window, %x %x %x\n\n",
        !          2828:                    sc->sc_iot, sc->sc_memt, bst));
        !          2829:        }
        !          2830:
        !          2831:        if (pccbb_winlist_insert(head, addr, size, bsh, flags)) {
        !          2832:                printf("%s: pccbb_open_win: %s winlist insert failed\n",
        !          2833:                    sc->sc_dev.dv_xname,
        !          2834:                    (head == &sc->sc_memwindow) ? "mem" : "io");
        !          2835:        }
        !          2836:        pccbb_winset(align, sc, bst);
        !          2837:
        !          2838:        return 0;
        !          2839: }
        !          2840:
        !          2841: int
        !          2842: pccbb_close_win(sc, bst, bsh, size)
        !          2843:        struct pccbb_softc *sc;
        !          2844:        bus_space_tag_t bst;
        !          2845:        bus_space_handle_t bsh;
        !          2846:        bus_size_t size;
        !          2847: {
        !          2848:        struct pccbb_win_chain_head *head;
        !          2849:        bus_addr_t align;
        !          2850:
        !          2851:        head = &sc->sc_iowindow;
        !          2852:        align = 0x04;
        !          2853:        if (sc->sc_memt == bst) {
        !          2854:                head = &sc->sc_memwindow;
        !          2855:                align = 0x1000;
        !          2856:        }
        !          2857:
        !          2858:        if (pccbb_winlist_delete(head, bsh, size)) {
        !          2859:                printf("%s: pccbb_close_win: %s winlist delete failed\n",
        !          2860:                    sc->sc_dev.dv_xname,
        !          2861:                    (head == &sc->sc_memwindow) ? "mem" : "io");
        !          2862:        }
        !          2863:        pccbb_winset(align, sc, bst);
        !          2864:
        !          2865:        return 0;
        !          2866: }
        !          2867:
        !          2868: int
        !          2869: pccbb_winlist_insert(head, start, size, bsh, flags)
        !          2870:        struct pccbb_win_chain_head *head;
        !          2871:        bus_addr_t start;
        !          2872:        bus_size_t size;
        !          2873:        bus_space_handle_t bsh;
        !          2874:        int flags;
        !          2875: {
        !          2876:        struct pccbb_win_chain *chainp, *elem;
        !          2877:
        !          2878:        if ((elem = malloc(sizeof(struct pccbb_win_chain), M_DEVBUF,
        !          2879:            M_NOWAIT)) == NULL)
        !          2880:                return (1);             /* fail */
        !          2881:
        !          2882:        elem->wc_start = start;
        !          2883:        elem->wc_end = start + (size - 1);
        !          2884:        elem->wc_handle = bsh;
        !          2885:        elem->wc_flags = flags;
        !          2886:
        !          2887:        for (chainp = TAILQ_FIRST(head); chainp != NULL;
        !          2888:            chainp = TAILQ_NEXT(chainp, wc_list)) {
        !          2889:                if (chainp->wc_end < start)
        !          2890:                        continue;
        !          2891:                TAILQ_INSERT_AFTER(head, chainp, elem, wc_list);
        !          2892:                return (0);
        !          2893:        }
        !          2894:
        !          2895:        TAILQ_INSERT_TAIL(head, elem, wc_list);
        !          2896:        return (0);
        !          2897: }
        !          2898:
        !          2899: int
        !          2900: pccbb_winlist_delete(head, bsh, size)
        !          2901:        struct pccbb_win_chain_head *head;
        !          2902:        bus_space_handle_t bsh;
        !          2903:        bus_size_t size;
        !          2904: {
        !          2905:        struct pccbb_win_chain *chainp;
        !          2906:
        !          2907:        for (chainp = TAILQ_FIRST(head); chainp != NULL;
        !          2908:             chainp = TAILQ_NEXT(chainp, wc_list)) {
        !          2909:                if (memcmp(&chainp->wc_handle, &bsh, sizeof(bsh)))
        !          2910:                        continue;
        !          2911:                if ((chainp->wc_end - chainp->wc_start) != (size - 1)) {
        !          2912:                        printf("pccbb_winlist_delete: window 0x%lx size "
        !          2913:                            "inconsistent: 0x%lx, 0x%lx\n",
        !          2914:                            chainp->wc_start,
        !          2915:                            chainp->wc_end - chainp->wc_start,
        !          2916:                            size - 1);
        !          2917:                        return 1;
        !          2918:                }
        !          2919:
        !          2920:                TAILQ_REMOVE(head, chainp, wc_list);
        !          2921:                free(chainp, M_DEVBUF);
        !          2922:
        !          2923:                return 0;
        !          2924:        }
        !          2925:
        !          2926:        return 1;              /* fail: no candidate to remove */
        !          2927: }
        !          2928:
        !          2929: void
        !          2930: pccbb_winset(align, sc, bst)
        !          2931:        bus_addr_t align;
        !          2932:        struct pccbb_softc *sc;
        !          2933:        bus_space_tag_t bst;
        !          2934: {
        !          2935:        pci_chipset_tag_t pc;
        !          2936:        pcitag_t tag;
        !          2937:        bus_addr_t mask = ~(align - 1);
        !          2938:        struct {
        !          2939:                cardbusreg_t win_start;
        !          2940:                cardbusreg_t win_limit;
        !          2941:                int win_flags;
        !          2942:        } win[2];
        !          2943:        struct pccbb_win_chain *chainp;
        !          2944:        int offs;
        !          2945:
        !          2946:        win[0].win_start = win[1].win_start = 0xffffffff;
        !          2947:        win[0].win_limit = win[1].win_limit = 0;
        !          2948:        win[0].win_flags = win[1].win_flags = 0;
        !          2949:
        !          2950:        chainp = TAILQ_FIRST(&sc->sc_iowindow);
        !          2951:        offs = 0x2c;
        !          2952:        if (sc->sc_memt == bst) {
        !          2953:                chainp = TAILQ_FIRST(&sc->sc_memwindow);
        !          2954:                offs = 0x1c;
        !          2955:        }
        !          2956:
        !          2957:        if (chainp != NULL) {
        !          2958:                win[0].win_start = chainp->wc_start & mask;
        !          2959:                win[0].win_limit = chainp->wc_end & mask;
        !          2960:                win[0].win_flags = chainp->wc_flags;
        !          2961:                chainp = TAILQ_NEXT(chainp, wc_list);
        !          2962:        }
        !          2963:
        !          2964:        for (; chainp != NULL; chainp = TAILQ_NEXT(chainp, wc_list)) {
        !          2965:                if (win[1].win_start == 0xffffffff) {
        !          2966:                        /* window 1 is not used */
        !          2967:                        if ((win[0].win_flags == chainp->wc_flags) &&
        !          2968:                            (win[0].win_limit + align >=
        !          2969:                            (chainp->wc_start & mask))) {
        !          2970:                                /* concatenate */
        !          2971:                                win[0].win_limit = chainp->wc_end & mask;
        !          2972:                        } else {
        !          2973:                                /* make new window */
        !          2974:                                win[1].win_start = chainp->wc_start & mask;
        !          2975:                                win[1].win_limit = chainp->wc_end & mask;
        !          2976:                                win[1].win_flags = chainp->wc_flags;
        !          2977:                        }
        !          2978:                        continue;
        !          2979:                }
        !          2980:
        !          2981:                /* Both windows are engaged. */
        !          2982:                if (win[0].win_flags == win[1].win_flags) {
        !          2983:                        /* same flags */
        !          2984:                        if (win[0].win_flags == chainp->wc_flags) {
        !          2985:                                if (win[1].win_start - (win[0].win_limit +
        !          2986:                                    align) <
        !          2987:                                    (chainp->wc_start & mask) -
        !          2988:                                    ((chainp->wc_end & mask) + align)) {
        !          2989:                                        /*
        !          2990:                                         * merge window 0 and 1, and set win1
        !          2991:                                         * to chainp
        !          2992:                                         */
        !          2993:                                        win[0].win_limit = win[1].win_limit;
        !          2994:                                        win[1].win_start =
        !          2995:                                            chainp->wc_start & mask;
        !          2996:                                        win[1].win_limit =
        !          2997:                                            chainp->wc_end & mask;
        !          2998:                                } else {
        !          2999:                                        win[1].win_limit =
        !          3000:                                            chainp->wc_end & mask;
        !          3001:                                }
        !          3002:                        } else {
        !          3003:                                /* different flags */
        !          3004:
        !          3005:                                /* concatenate win0 and win1 */
        !          3006:                                win[0].win_limit = win[1].win_limit;
        !          3007:                                /* allocate win[1] to new space */
        !          3008:                                win[1].win_start = chainp->wc_start & mask;
        !          3009:                                win[1].win_limit = chainp->wc_end & mask;
        !          3010:                                win[1].win_flags = chainp->wc_flags;
        !          3011:                        }
        !          3012:                } else {
        !          3013:                        /* the flags of win[0] and win[1] is different */
        !          3014:                        if (win[0].win_flags == chainp->wc_flags) {
        !          3015:                                win[0].win_limit = chainp->wc_end & mask;
        !          3016:                                /*
        !          3017:                                 * XXX this creates overlapping windows, so
        !          3018:                                 * what should the poor bridge do if one is
        !          3019:                                 * cachable, and the other is not?
        !          3020:                                 */
        !          3021:                                printf("%s: overlapping windows\n",
        !          3022:                                    sc->sc_dev.dv_xname);
        !          3023:                        } else {
        !          3024:                                win[1].win_limit = chainp->wc_end & mask;
        !          3025:                        }
        !          3026:                }
        !          3027:        }
        !          3028:
        !          3029:        pc = sc->sc_pc;
        !          3030:        tag = sc->sc_tag;
        !          3031:        pci_conf_write(pc, tag, offs, win[0].win_start);
        !          3032:        pci_conf_write(pc, tag, offs + 4, win[0].win_limit);
        !          3033:        pci_conf_write(pc, tag, offs + 8, win[1].win_start);
        !          3034:        pci_conf_write(pc, tag, offs + 12, win[1].win_limit);
        !          3035:        DPRINTF(("--pccbb_winset: win0 [%x, %lx), win1 [%x, %lx)\n",
        !          3036:            pci_conf_read(pc, tag, offs),
        !          3037:            pci_conf_read(pc, tag, offs + 4) + align,
        !          3038:            pci_conf_read(pc, tag, offs + 8),
        !          3039:            pci_conf_read(pc, tag, offs + 12) + align));
        !          3040:
        !          3041:        if (bst == sc->sc_memt) {
        !          3042:                pcireg_t bcr = pci_conf_read(pc, tag, PCI_BCR_INTR);
        !          3043:
        !          3044:                bcr &= ~(CB_BCR_PREFETCH_MEMWIN0 | CB_BCR_PREFETCH_MEMWIN1);
        !          3045:                if (win[0].win_flags & PCCBB_MEM_CACHABLE)
        !          3046:                        bcr |= CB_BCR_PREFETCH_MEMWIN0;
        !          3047:                if (win[1].win_flags & PCCBB_MEM_CACHABLE)
        !          3048:                        bcr |= CB_BCR_PREFETCH_MEMWIN1;
        !          3049:                pci_conf_write(pc, tag, PCI_BCR_INTR, bcr);
        !          3050:        }
        !          3051: }
        !          3052:
        !          3053: void
        !          3054: pccbb_powerhook(why, arg)
        !          3055:        int why;
        !          3056:        void *arg;
        !          3057: {
        !          3058:        struct pccbb_softc *sc = arg;
        !          3059:        u_int32_t reg;
        !          3060:        bus_space_tag_t base_memt = sc->sc_base_memt;   /* socket regs memory */
        !          3061:        bus_space_handle_t base_memh = sc->sc_base_memh;
        !          3062:
        !          3063:        DPRINTF(("%s: power: why %d\n", sc->sc_dev.dv_xname, why));
        !          3064:
        !          3065:        if (why == PWR_SUSPEND || why == PWR_STANDBY) {
        !          3066:                DPRINTF(("%s: power: why %d stopping intr\n",
        !          3067:                    sc->sc_dev.dv_xname, why));
        !          3068:                if (sc->sc_pil_intr_enable) {
        !          3069:                        (void)pccbbintr_function(sc);
        !          3070:                }
        !          3071:                sc->sc_pil_intr_enable = 0;
        !          3072:
        !          3073:                /* ToDo: deactivate or suspend child devices */
        !          3074:
        !          3075:        }
        !          3076:
        !          3077:        if (why == PWR_RESUME) {
        !          3078:                if (pci_conf_read (sc->sc_pc, sc->sc_tag, PCI_SOCKBASE) == 0)
        !          3079:                        /* BIOS did not recover this register */
        !          3080:                        pci_conf_write (sc->sc_pc, sc->sc_tag,
        !          3081:                                        PCI_SOCKBASE, sc->sc_sockbase);
        !          3082:                if (pci_conf_read (sc->sc_pc, sc->sc_tag, PCI_BUSNUM) == 0)
        !          3083:                        /* BIOS did not recover this register */
        !          3084:                        pci_conf_write (sc->sc_pc, sc->sc_tag,
        !          3085:                                        PCI_BUSNUM, sc->sc_busnum);
        !          3086:                /* CSC Interrupt: Card detect interrupt on */
        !          3087:                reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_MASK);
        !          3088:                /* Card detect intr is turned on. */
        !          3089:                reg |= CB_SOCKET_MASK_CD;
        !          3090:                bus_space_write_4(base_memt, base_memh, CB_SOCKET_MASK, reg);
        !          3091:                /* reset interrupt */
        !          3092:                reg = bus_space_read_4(base_memt, base_memh, CB_SOCKET_EVENT);
        !          3093:                bus_space_write_4(base_memt, base_memh, CB_SOCKET_EVENT, reg);
        !          3094:
        !          3095:                /*
        !          3096:                 * check for card insertion or removal during suspend period.
        !          3097:                 * XXX: the code can't cope with card swap (remove then
        !          3098:                 * insert).  how can we detect such situation?
        !          3099:                 */
        !          3100:                (void)pccbbintr(sc);
        !          3101:
        !          3102:                sc->sc_pil_intr_enable = 1;
        !          3103:                DPRINTF(("%s: power: RESUME enabling intr\n",
        !          3104:                    sc->sc_dev.dv_xname));
        !          3105:
        !          3106:                /* ToDo: activate or wakeup child devices */
        !          3107:        }
        !          3108: }

CVSweb