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

Annotation of sys/dev/cardbus/cardbus_map.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: cardbus_map.c,v 1.7 2006/07/31 11:06:27 mickey Exp $  */
        !             2: /*     $NetBSD: cardbus_map.c,v 1.10 2000/03/07 00:31:46 mycroft Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 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:  *
        !            23:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            24:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
        !            25:  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
        !            26:  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
        !            27:  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
        !            28:  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
        !            29:  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            31:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
        !            32:  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            33:  * POSSIBILITY OF SUCH DAMAGE.
        !            34:  */
        !            35:
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/systm.h>
        !            39: #include <sys/device.h>
        !            40:
        !            41: #include <machine/bus.h>
        !            42:
        !            43: #include <dev/cardbus/cardbusvar.h>
        !            44:
        !            45: #include <dev/pci/pcireg.h>    /* XXX */
        !            46:
        !            47: #if defined DEBUG && !defined CARDBUS_MAP_DEBUG
        !            48: #define CARDBUS_MAP_DEBUG
        !            49: #endif
        !            50:
        !            51: #if defined CARDBUS_MAP_DEBUG
        !            52: #define STATIC
        !            53: #define DPRINTF(a) printf a
        !            54: #else
        !            55: #define STATIC static
        !            56: #define DPRINTF(a)
        !            57: #endif
        !            58:
        !            59:
        !            60: static int cardbus_io_find(cardbus_chipset_tag_t, cardbus_function_tag_t,
        !            61:               cardbustag_t, int, cardbusreg_t, bus_addr_t *, bus_size_t *,
        !            62:               int *);
        !            63: static int cardbus_mem_find(cardbus_chipset_tag_t, cardbus_function_tag_t,
        !            64:               cardbustag_t, int, cardbusreg_t, bus_addr_t *, bus_size_t *,
        !            65:               int *);
        !            66:
        !            67: int
        !            68: cardbus_mapreg_probe(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
        !            69:     cardbustag_t tag, int reg, pcireg_t *typep)
        !            70: {
        !            71:        pcireg_t address, mask;
        !            72:        int s;
        !            73:
        !            74:        s = splhigh();
        !            75:        address = cardbus_conf_read(cc, cf, tag, reg);
        !            76:        cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
        !            77:        mask = cardbus_conf_read(cc, cf, tag, reg);
        !            78:        cardbus_conf_write(cc, cf, tag, reg, address);
        !            79:        splx(s);
        !            80:
        !            81:        if (mask == 0) /* unimplemented mapping register */
        !            82:                return (0);
        !            83:
        !            84:        if (typep)
        !            85:                *typep = _PCI_MAPREG_TYPEBITS(address);
        !            86:        return (1);
        !            87: }
        !            88:
        !            89: /*
        !            90:  * static int cardbus_io_find(cardbus_chipset_tag_t cc,
        !            91:  *                           cardbus_function_tag_t cf, cardbustag_t tag,
        !            92:  *                           int reg, cardbusreg_t type, bus_addr_t *basep,
        !            93:  *                           bus_size_t *sizep, int *flagsp)
        !            94:  * This code is stolen from sys/dev/pci_map.c.
        !            95:  */
        !            96: static int
        !            97: cardbus_io_find(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
        !            98:     cardbustag_t tag, int reg, cardbusreg_t type, bus_addr_t *basep,
        !            99:     bus_size_t *sizep, int *flagsp)
        !           100: {
        !           101:        cardbusreg_t address, mask;
        !           102:        int s;
        !           103:
        !           104:        /* EXT ROM is able to map on memory space ONLY. */
        !           105:        if (reg == CARDBUS_ROM_REG)
        !           106:                return (1);
        !           107:
        !           108:        if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) {
        !           109:                panic("cardbus_io_find: bad request");
        !           110:        }
        !           111:
        !           112:        /*
        !           113:         * Section 6.2.5.1, `Address Maps', tells us that:
        !           114:         *
        !           115:         * 1) The builtin software should have already mapped the device in a
        !           116:         * reasonable way.
        !           117:         *
        !           118:         * 2) A device which wants 2^n bytes of memory will hardwire the bottom
        !           119:         * n bits of the address to 0.  As recommended, we write all 1s and see
        !           120:         * what we get back.
        !           121:         */
        !           122:        s = splhigh();
        !           123:        address = cardbus_conf_read(cc, cf, tag, reg);
        !           124:        cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
        !           125:        mask = cardbus_conf_read(cc, cf, tag, reg);
        !           126:        cardbus_conf_write(cc, cf, tag, reg, address);
        !           127:        splx(s);
        !           128:
        !           129:        if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) {
        !           130:                printf("cardbus_io_find: expected type i/o, found mem\n");
        !           131:                return (1);
        !           132:        }
        !           133:
        !           134:        if (PCI_MAPREG_IO_SIZE(mask) == 0) {
        !           135:                printf("cardbus_io_find: void region\n");
        !           136:                return (1);
        !           137:        }
        !           138:
        !           139:        if (basep != 0)
        !           140:                *basep = PCI_MAPREG_IO_ADDR(address);
        !           141:        if (sizep != 0)
        !           142:                *sizep = PCI_MAPREG_IO_SIZE(mask);
        !           143:        if (flagsp != 0)
        !           144:                *flagsp = 0;
        !           145:
        !           146:        return (0);
        !           147: }
        !           148:
        !           149: /*
        !           150:  * static int cardbus_mem_find(cardbus_chipset_tag_t cc,
        !           151:  *                            cardbus_function_tag_t cf, cardbustag_t tag,
        !           152:  *                            int reg, cardbusreg_t type, bus_addr_t *basep,
        !           153:  *                            bus_size_t *sizep, int *flagsp)
        !           154:  * This code is stolen from sys/dev/pci_map.c.
        !           155:  */
        !           156: static int
        !           157: cardbus_mem_find(cardbus_chipset_tag_t cc, cardbus_function_tag_t cf,
        !           158:     cardbustag_t tag, int reg, cardbusreg_t type, bus_addr_t *basep,
        !           159:     bus_size_t *sizep, int *flagsp)
        !           160: {
        !           161:        cardbusreg_t address, mask;
        !           162:        int s;
        !           163:
        !           164:        if (reg != CARDBUS_ROM_REG &&
        !           165:            (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3))) {
        !           166:                panic("cardbus_mem_find: bad request");
        !           167:        }
        !           168:
        !           169:        /*
        !           170:         * Section 6.2.5.1, `Address Maps', tells us that:
        !           171:         *
        !           172:         * 1) The builtin software should have already mapped the device in a
        !           173:         * reasonable way.
        !           174:         *
        !           175:         * 2) A device which wants 2^n bytes of memory will hardwire the bottom
        !           176:         * n bits of the address to 0.  As recommended, we write all 1s and see
        !           177:         * what we get back.
        !           178:         */
        !           179:        s = splhigh();
        !           180:        address = cardbus_conf_read(cc, cf, tag, reg);
        !           181:        cardbus_conf_write(cc, cf, tag, reg, 0xffffffff);
        !           182:        mask = cardbus_conf_read(cc, cf, tag, reg);
        !           183:        cardbus_conf_write(cc, cf, tag, reg, address);
        !           184:        splx(s);
        !           185:
        !           186:        if (reg != CARDBUS_ROM_REG) {
        !           187:                /* memory space BAR */
        !           188:
        !           189:                if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) {
        !           190:                        printf("cardbus_mem_find: expected type mem, "
        !           191:                            "found i/o\n");
        !           192:                        return (1);
        !           193:                }
        !           194:                if (PCI_MAPREG_MEM_TYPE(address) != PCI_MAPREG_MEM_TYPE(type)) {
        !           195:                        printf("cardbus_mem_find: expected mem type %08x, "
        !           196:                            "found %08x\n", PCI_MAPREG_MEM_TYPE(type),
        !           197:                            PCI_MAPREG_MEM_TYPE(address));
        !           198:                        return (1);
        !           199:                }
        !           200:        }
        !           201:
        !           202:        if (PCI_MAPREG_MEM_SIZE(mask) == 0) {
        !           203:                printf("cardbus_mem_find: void region\n");
        !           204:                return (1);
        !           205:        }
        !           206:
        !           207:        switch (PCI_MAPREG_MEM_TYPE(address)) {
        !           208:        case PCI_MAPREG_MEM_TYPE_32BIT:
        !           209:        case PCI_MAPREG_MEM_TYPE_32BIT_1M:
        !           210:                break;
        !           211:        case PCI_MAPREG_MEM_TYPE_64BIT:
        !           212:                printf("cardbus_mem_find: 64-bit memory mapping register\n");
        !           213:                return (1);
        !           214:        default:
        !           215:                printf("cardbus_mem_find: reserved mapping register type\n");
        !           216:                return (1);
        !           217:        }
        !           218:
        !           219:        if (basep != 0)
        !           220:                *basep = PCI_MAPREG_MEM_ADDR(address);
        !           221:        if (sizep != 0)
        !           222:                *sizep = PCI_MAPREG_MEM_SIZE(mask);
        !           223:        if (flagsp != 0) {
        !           224:                *flagsp =
        !           225: #ifdef BUS_SPACE_MAP_PREFETCHABLE
        !           226:                    PCI_MAPREG_MEM_PREFETCHABLE(address) ?
        !           227:                      BUS_SPACE_MAP_PREFETCHABLE :
        !           228: #endif
        !           229:                0;
        !           230:        }
        !           231:
        !           232:        return (0);
        !           233: }
        !           234:
        !           235: /*
        !           236:  * int cardbus_mapreg_map(struct cardbus_softc *, int, int, cardbusreg_t,
        !           237:  *                       int bus_space_tag_t *, bus_space_handle_t *,
        !           238:  *                       bus_addr_t *, bus_size_t *)
        !           239:  *    This function maps bus-space on the value of Base Address
        !           240:  *   Register (BAR) indexed by the argument `reg' (the second argument).
        !           241:  *   When the value of the BAR is not valid, such as 0x00000000, a new
        !           242:  *   address should be allocated for the BAR and new address values is
        !           243:  *   written on the BAR.
        !           244:  */
        !           245: int
        !           246: cardbus_mapreg_map(struct cardbus_softc *sc, int func, int reg,
        !           247:     cardbusreg_t type, int busflags, bus_space_tag_t *tagp,
        !           248:     bus_space_handle_t *handlep, bus_addr_t *basep, bus_size_t *sizep)
        !           249: {
        !           250:        cardbus_chipset_tag_t cc = sc->sc_cc;
        !           251:        cardbus_function_tag_t cf = sc->sc_cf;
        !           252:        bus_space_tag_t bustag;
        !           253:        rbus_tag_t rbustag;
        !           254:        bus_space_handle_t handle;
        !           255:        bus_addr_t base;
        !           256:        bus_size_t size;
        !           257:        int flags;
        !           258:        int status = 0;
        !           259:
        !           260:        cardbustag_t tag = cardbus_make_tag(cc, cf, sc->sc_bus,
        !           261:            sc->sc_device, func);
        !           262:
        !           263:        DPRINTF(("cardbus_mapreg_map called: %s %x\n", sc->sc_dev.dv_xname,
        !           264:           type));
        !           265:
        !           266:        if (PCI_MAPREG_TYPE(type) == PCI_MAPREG_TYPE_IO) {
        !           267:                if (cardbus_io_find(cc, cf, tag, reg, type, &base, &size,
        !           268:                    &flags))
        !           269:                        status = 1;
        !           270:                bustag = sc->sc_iot;
        !           271:                rbustag = sc->sc_rbus_iot;
        !           272:        } else {
        !           273:                if (cardbus_mem_find(cc, cf, tag, reg, type, &base, &size,
        !           274:                    &flags))
        !           275:                        status = 1;
        !           276:                bustag = sc->sc_memt;
        !           277:                rbustag = sc->sc_rbus_memt;
        !           278:        }
        !           279:        if (status == 0) {
        !           280:                bus_addr_t mask = size - 1;
        !           281:                if (base != 0)
        !           282:                        mask = 0xffffffff;
        !           283:                if ((*cf->cardbus_space_alloc)(cc, rbustag, base, size, mask,
        !           284:                    size, busflags | flags, &base, &handle)) {
        !           285:                        panic("io alloc");
        !           286:                }
        !           287:        }
        !           288:        cardbus_conf_write(cc, cf, tag, reg, base);
        !           289:
        !           290:        DPRINTF(("cardbus_mapreg_map: physaddr %lx\n", (unsigned long)base));
        !           291:
        !           292:        if (tagp != 0)
        !           293:                *tagp = bustag;
        !           294:        if (handlep != 0)
        !           295:                *handlep = handle;
        !           296:        if (basep != 0)
        !           297:                *basep = base;
        !           298:        if (sizep != 0)
        !           299:                *sizep = size;
        !           300:        cardbus_free_tag(cc, cf, tag);
        !           301:
        !           302:        return (0);
        !           303: }
        !           304:
        !           305: /*
        !           306:  * int cardbus_mapreg_unmap(struct cardbus_softc *sc, int func, int reg,
        !           307:  *                         bus_space_tag_t tag, bus_space_handle_t handle,
        !           308:  *                         bus_size_t size)
        !           309:  *
        !           310:  *   This function releases bus-space region and close memory or io
        !           311:  *   window on the bridge.
        !           312:  *
        !           313:  *  Arguments:
        !           314:  *   struct cardbus_softc *sc; the pointer to the device structure of cardbus.
        !           315:  *   int func; the number of function on the device.
        !           316:  *   int reg; the offset of BAR register.
        !           317:  */
        !           318: int
        !           319: cardbus_mapreg_unmap(struct cardbus_softc *sc, int func, int reg,
        !           320:     bus_space_tag_t tag, bus_space_handle_t handle, bus_size_t size)
        !           321: {
        !           322:        cardbus_chipset_tag_t cc = sc->sc_cc;
        !           323:        cardbus_function_tag_t cf = sc->sc_cf;
        !           324:        int st = 1;
        !           325:        cardbustag_t cardbustag;
        !           326:        rbus_tag_t rbustag;
        !           327:
        !           328:        if (sc->sc_iot == tag) {
        !           329:                /* bus space is io space */
        !           330:                DPRINTF(("%s: unmap i/o space\n", sc->sc_dev.dv_xname));
        !           331:                rbustag = sc->sc_rbus_iot;
        !           332:        } else if (sc->sc_memt == tag) {
        !           333:                /* bus space is memory space */
        !           334:                DPRINTF(("%s: unmap mem space\n", sc->sc_dev.dv_xname));
        !           335:                rbustag = sc->sc_rbus_memt;
        !           336:        } else
        !           337:                return (1);
        !           338:
        !           339:        cardbustag = cardbus_make_tag(cc, cf, sc->sc_bus, sc->sc_device, func);
        !           340:
        !           341:        cardbus_conf_write(cc, cf, cardbustag, reg, 0);
        !           342:
        !           343:        (*cf->cardbus_space_free)(cc, rbustag, handle, size);
        !           344:
        !           345:        cardbus_free_tag(cc, cf, cardbustag);
        !           346:
        !           347:        return (st);
        !           348: }
        !           349:
        !           350: /*
        !           351:  * int cardbus_save_bar(cardbus_devfunc_t);
        !           352:  *
        !           353:  *   This function saves the Base Address Registers at the CardBus
        !           354:  *   function denoted by the argument.
        !           355:  */
        !           356: int
        !           357: cardbus_save_bar(cardbus_devfunc_t ct)
        !           358: {
        !           359:        cardbustag_t tag = Cardbus_make_tag(ct);
        !           360:        cardbus_chipset_tag_t cc = ct->ct_cc;
        !           361:        cardbus_function_tag_t cf = ct->ct_cf;
        !           362:
        !           363:        ct->ct_bar[0] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE0_REG);
        !           364:        ct->ct_bar[1] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE1_REG);
        !           365:        ct->ct_bar[2] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE2_REG);
        !           366:        ct->ct_bar[3] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE3_REG);
        !           367:        ct->ct_bar[4] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE4_REG);
        !           368:        ct->ct_bar[5] = cardbus_conf_read(cc, cf, tag, CARDBUS_BASE5_REG);
        !           369:
        !           370:        DPRINTF(("cardbus_save_bar: %x %x\n", ct->ct_bar[0], ct->ct_bar[1]));
        !           371:
        !           372:        Cardbus_free_tag(ct, tag);
        !           373:
        !           374:        return (0);
        !           375: }
        !           376:
        !           377: /*
        !           378:  * int cardbus_restore_bar(cardbus_devfunc_t);
        !           379:  *
        !           380:  *   This function saves the Base Address Registers at the CardBus
        !           381:  *   function denoted by the argument.
        !           382:  */
        !           383: int
        !           384: cardbus_restore_bar(cardbus_devfunc_t ct)
        !           385: {
        !           386:        cardbustag_t tag = Cardbus_make_tag(ct);
        !           387:        cardbus_chipset_tag_t cc = ct->ct_cc;
        !           388:        cardbus_function_tag_t cf = ct->ct_cf;
        !           389:
        !           390:        cardbus_conf_write(cc, cf, tag, CARDBUS_BASE0_REG, ct->ct_bar[0]);
        !           391:        cardbus_conf_write(cc, cf, tag, CARDBUS_BASE1_REG, ct->ct_bar[1]);
        !           392:        cardbus_conf_write(cc, cf, tag, CARDBUS_BASE2_REG, ct->ct_bar[2]);
        !           393:        cardbus_conf_write(cc, cf, tag, CARDBUS_BASE3_REG, ct->ct_bar[3]);
        !           394:        cardbus_conf_write(cc, cf, tag, CARDBUS_BASE4_REG, ct->ct_bar[4]);
        !           395:        cardbus_conf_write(cc, cf, tag, CARDBUS_BASE5_REG, ct->ct_bar[5]);
        !           396:
        !           397:        Cardbus_free_tag(ct, tag);
        !           398:
        !           399:        return (0);
        !           400: }

CVSweb