[BACK]Return to macepcimap.c CVS log [TXT][DIR] Up to [local] / sys / arch / sgi / pci

Annotation of sys/arch/sgi/pci/macepcimap.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: macepcimap.c,v 1.3 2004/09/09 22:11:39 pefo Exp $ */
        !             2: /*     $NetBSD: pci_mace.c,v 1.2 2004/01/19 10:28:28 sekiya Exp $      */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 2001,2003 Christopher Sekiya
        !             6:  * Copyright (c) 2000 Soren S. Jorvang
        !             7:  * All rights reserved.
        !             8:  *
        !             9:  * Redistribution and use in source and binary forms, with or without
        !            10:  * modification, are permitted provided that the following conditions
        !            11:  * are met:
        !            12:  * 1. Redistributions of source code must retain the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer.
        !            14:  * 2. Redistributions in binary form must reproduce the above copyright
        !            15:  *    notice, this list of conditions and the following disclaimer in the
        !            16:  *    documentation and/or other materials provided with the distribution.
        !            17:  * 3. All advertising materials mentioning features or use of this software
        !            18:  *    must display the following acknowledgement:
        !            19:  *          This product includes software developed for the
        !            20:  *          NetBSD Project.  See http://www.NetBSD.org/ for
        !            21:  *          information about NetBSD.
        !            22:  * 4. The name of the author may not be used to endorse or promote products
        !            23:  *    derived from this software without specific prior written permission.
        !            24:  *
        !            25:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            26:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            27:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            28:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            29:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            30:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            31:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            32:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            33:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            34:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            35:  */
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/device.h>
        !            39: #include <sys/systm.h>
        !            40:
        !            41: #include <machine/cpu.h>
        !            42: #include <machine/autoconf.h>
        !            43: #include <machine/vmparam.h>
        !            44: #include <machine/bus.h>
        !            45:
        !            46: #include <dev/pci/pcivar.h>
        !            47: #include <dev/pci/pcireg.h>
        !            48: #include <dev/pci/pcidevs.h>
        !            49:
        !            50:
        !            51: void pciaddr_remap(pci_chipset_tag_t);
        !            52: void pciaddr_resource_manage(pci_chipset_tag_t, pcitag_t, void *);
        !            53: bus_addr_t pciaddr_ioaddr(u_int32_t);
        !            54: int pciaddr_do_resource_allocate(pci_chipset_tag_t, pcitag_t, int, void *,
        !            55:        int, bus_addr_t *, bus_size_t);
        !            56: void pciaddr_print_devid(pci_chipset_tag_t, pcitag_t);
        !            57:
        !            58:
        !            59: #define PAGE_ALIGN(x)  (((x) + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1))
        !            60: #define MEG_ALIGN(x)   (((x) + 0x100000 - 1) & ~(0x100000 - 1))
        !            61:
        !            62:
        !            63: unsigned int ioaddr_base = 0x1000;
        !            64: unsigned int memaddr_base = 0x80100000;
        !            65:
        !            66: #ifdef DEBUG
        !            67: int pcibiosverbose = 1;
        !            68: #endif
        !            69:
        !            70:
        !            71: void
        !            72: pciaddr_remap(pci_chipset_tag_t pc)
        !            73: {
        !            74:        pcitag_t devtag;
        !            75:        int device;
        !            76:
        !            77:        /* Must fix up all PCI devices, ahc_pci expects proper i/o mapping */
        !            78:        for (device = 1; device < 4; device++) {
        !            79:                const struct pci_quirkdata *qd;
        !            80:                int function, nfuncs;
        !            81:                pcireg_t bhlcr, id;
        !            82:
        !            83:                devtag = pci_make_tag(pc, 0, device, 0);
        !            84:                id = pci_conf_read(pc, devtag, PCI_ID_REG);
        !            85:
        !            86:                /* Invalid vendor ID value? */
        !            87:                if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
        !            88:                        continue;
        !            89:                /* XXX Not invalid, but we've done this ~forever. */
        !            90:                if (PCI_VENDOR(id) == 0)
        !            91:                        continue;
        !            92:
        !            93:                qd = pci_lookup_quirkdata(PCI_VENDOR(id), PCI_PRODUCT(id));
        !            94:                bhlcr = pci_conf_read(pc, devtag, PCI_BHLC_REG);
        !            95:
        !            96:                if (PCI_HDRTYPE_MULTIFN(bhlcr) ||
        !            97:                    (qd != NULL &&
        !            98:                    (qd->quirks & PCI_QUIRK_MULTIFUNCTION) != 0))
        !            99:                        nfuncs = 8;
        !           100:                else
        !           101:                        nfuncs = 1;
        !           102:
        !           103:                for (function = 0; function < nfuncs; function++) {
        !           104:                        devtag = pci_make_tag(pc, 0, device, function);
        !           105:                        id = pci_conf_read(pc, devtag, PCI_ID_REG);
        !           106:
        !           107:                        /* Invalid vendor ID value? */
        !           108:                        if (PCI_VENDOR(id) == PCI_VENDOR_INVALID)
        !           109:                                continue;
        !           110:                        /* Not invalid, but we've done this ~forever */
        !           111:                        if (PCI_VENDOR(id) == 0)
        !           112:                                continue;
        !           113:
        !           114:                        pciaddr_resource_manage(pc, devtag, NULL);
        !           115:                }
        !           116:        }
        !           117: }
        !           118:
        !           119:
        !           120: void
        !           121: pciaddr_resource_manage(pc, tag, ctx)
        !           122:        pci_chipset_tag_t pc;
        !           123:        pcitag_t tag;
        !           124:        void *ctx;
        !           125: {
        !           126:        pcireg_t val, mask;
        !           127:        bus_addr_t addr;
        !           128:        bus_size_t size;
        !           129:        int error, mapreg, type, reg_start, reg_end, width;
        !           130:
        !           131:        val = pci_conf_read(pc, tag, PCI_BHLC_REG);
        !           132:        switch (PCI_HDRTYPE_TYPE(val)) {
        !           133:        default:
        !           134:                printf("WARNING: unknown PCI device header.");
        !           135:                return;
        !           136:        case 0:
        !           137:                reg_start = PCI_MAPREG_START;
        !           138:                reg_end   = PCI_MAPREG_END;
        !           139:                break;
        !           140:        case 1: /* PCI-PCI bridge */
        !           141:                reg_start = PCI_MAPREG_START;
        !           142:                reg_end   = PCI_MAPREG_PPB_END;
        !           143:                break;
        !           144:        case 2: /* PCI-CardBus bridge */
        !           145:                reg_start = PCI_MAPREG_START;
        !           146:                reg_end   = PCI_MAPREG_PCB_END;
        !           147:                break;
        !           148:        }
        !           149:        error = 0;
        !           150:
        !           151:        for (mapreg = reg_start; mapreg < reg_end; mapreg += width) {
        !           152:                /* inquire PCI device bus space requirement */
        !           153:                val = pci_conf_read(pc, tag, mapreg);
        !           154:                pci_conf_write(pc, tag, mapreg, ~0);
        !           155:
        !           156:                mask = pci_conf_read(pc, tag, mapreg);
        !           157:                pci_conf_write(pc, tag, mapreg, val);
        !           158:
        !           159:                type = PCI_MAPREG_TYPE(val);
        !           160:                width = 4;
        !           161:
        !           162:                if (type == PCI_MAPREG_TYPE_MEM) {
        !           163:                        size = PCI_MAPREG_MEM_SIZE(mask);
        !           164:
        !           165:                        /*
        !           166:                         * XXXrkb: for MEM64 BARs, to be totally kosher
        !           167:                         * about the requested size, need to read mask
        !           168:                         * from top 32bits of BAR and stir that into the
        !           169:                         * size calculation, like so:
        !           170:                         *
        !           171:                         * case PCI_MAPREG_MEM_TYPE_64BIT:
        !           172:                         *      bar64 = pci_conf_read(pb->pc, tag, br + 4);
        !           173:                         *      pci_conf_write(pb->pc, tag, br + 4, 0xffffffff);
        !           174:                         *      mask64 = pci_conf_read(pb->pc, tag, br + 4);
        !           175:                         *      pci_conf_write(pb->pc, tag, br + 4, bar64);
        !           176:                         *      size = (u_int64_t) PCI_MAPREG_MEM64_SIZE(
        !           177:                         *            (((u_int64_t) mask64) << 32) | mask);
        !           178:                         *      width = 8;
        !           179:                         *
        !           180:                         * Fortunately, anything with all-zeros mask in the
        !           181:                         * lower 32-bits will have size no less than 1 << 32,
        !           182:                         * which we're not prepared to deal with, so I don't
        !           183:                         * feel bad punting on it...
        !           184:                         */
        !           185:                        if (PCI_MAPREG_MEM_TYPE(val) ==
        !           186:                            PCI_MAPREG_MEM_TYPE_64BIT) {
        !           187:                                /*
        !           188:                                 * XXX We could examine the upper 32 bits
        !           189:                                 * XXX of the BAR here, but we are totally
        !           190:                                 * XXX unprepared to handle a non-zero value,
        !           191:                                 * XXX either here or anywhere else in the
        !           192:                                 * XXX sgimips code (not sure about MI code).
        !           193:                                 * XXX
        !           194:                                 * XXX So just arrange to skip the top 32
        !           195:                                 * XXX bits of the BAR and zero then out
        !           196:                                 * XXX if the BAR is in use.
        !           197:                                 */
        !           198:                                width = 8;
        !           199:
        !           200:                                if (size != 0)
        !           201:                                        pci_conf_write(pc, tag,
        !           202:                                            mapreg + 4, 0);
        !           203:                        }
        !           204:                } else {
        !           205:                        /*
        !           206:                         * Upper 16 bits must be one.  Devices may hardwire
        !           207:                         * them to zero, though, per PCI 2.2, 6.2.5.1, p 203.
        !           208:                         */
        !           209:                        mask |= 0xffff0000;
        !           210:                        size = PCI_MAPREG_IO_SIZE(mask);
        !           211:                }
        !           212:
        !           213:                if (size == 0) /* unused register */
        !           214:                        continue;
        !           215:
        !           216:                addr = pciaddr_ioaddr(val);
        !           217:
        !           218:                /* reservation/allocation phase */
        !           219:                error += pciaddr_do_resource_allocate(pc, tag, mapreg,
        !           220:                    ctx, type, &addr, size);
        !           221:
        !           222:        }
        !           223:
        !           224:        /* enable/disable PCI device */
        !           225:        val = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
        !           226:
        !           227:        if (error == 0)
        !           228:                val |= (PCI_COMMAND_IO_ENABLE |
        !           229:                        PCI_COMMAND_MEM_ENABLE |
        !           230:                        PCI_COMMAND_MASTER_ENABLE |
        !           231:                        PCI_COMMAND_SPECIAL_ENABLE |
        !           232:                        PCI_COMMAND_INVALIDATE_ENABLE |
        !           233:                        PCI_COMMAND_PARITY_ENABLE);
        !           234:        else
        !           235:                val &= ~(PCI_COMMAND_IO_ENABLE |
        !           236:                         PCI_COMMAND_MEM_ENABLE |
        !           237:                         PCI_COMMAND_MASTER_ENABLE);
        !           238:
        !           239:        pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, val);
        !           240:
        !           241: }
        !           242:
        !           243: bus_addr_t
        !           244: pciaddr_ioaddr(val)
        !           245:        u_int32_t val;
        !           246: {
        !           247:
        !           248:        return ((PCI_MAPREG_TYPE(val) == PCI_MAPREG_TYPE_MEM) ?
        !           249:            PCI_MAPREG_MEM_ADDR(val) : PCI_MAPREG_IO_ADDR(val));
        !           250: }
        !           251:
        !           252: int
        !           253: pciaddr_do_resource_allocate(pc, tag, mapreg, ctx, type, addr, size)
        !           254:        pci_chipset_tag_t pc;
        !           255:        pcitag_t tag;
        !           256:        void *ctx;
        !           257:        int mapreg, type;
        !           258:        bus_addr_t *addr;
        !           259:        bus_size_t size;
        !           260: {
        !           261:
        !           262:        switch (type) {
        !           263:        case PCI_MAPREG_TYPE_IO:
        !           264:                *addr = ioaddr_base;
        !           265:                ioaddr_base += PAGE_ALIGN(size);
        !           266:                break;
        !           267:
        !           268:        case PCI_MAPREG_TYPE_MEM:
        !           269:                *addr = memaddr_base;
        !           270:                memaddr_base += MEG_ALIGN(size);
        !           271:                break;
        !           272:
        !           273:        default:
        !           274:                printf("attempt to remap unknown region (addr 0x%lx, "
        !           275:                    "size 0x%lx, type %d)\n", *addr, size, type);
        !           276:                return 0;
        !           277:        }
        !           278:
        !           279:
        !           280:        /* write new address to PCI device configuration header */
        !           281:        pci_conf_write(pc, tag, mapreg, *addr);
        !           282:
        !           283:        /* check */
        !           284: #ifdef DEBUG
        !           285:        if (!pcibiosverbose) {
        !           286:                printf("pci_addr_fixup: ");
        !           287:                pciaddr_print_devid(pc, tag);
        !           288:        }
        !           289: #endif
        !           290:        if (pciaddr_ioaddr(pci_conf_read(pc, tag, mapreg)) != *addr) {
        !           291:                pci_conf_write(pc, tag, mapreg, 0); /* clear */
        !           292:                printf("fixup failed. (new address=%#x)\n", (unsigned)*addr);
        !           293:                return (1);
        !           294:        }
        !           295: #ifdef DEBUG
        !           296:        if (!pcibiosverbose)
        !           297:                printf("new address 0x%08x (size 0x%x)\n", (unsigned)*addr,
        !           298:                    (unsigned)size);
        !           299: #endif
        !           300:
        !           301:        return (0);
        !           302: }
        !           303:
        !           304: void
        !           305: pciaddr_print_devid(pci_chipset_tag_t pc, pcitag_t tag)
        !           306: {
        !           307:        int bus, device, function;
        !           308:        pcireg_t id;
        !           309:
        !           310:        id = pci_conf_read(pc, tag, PCI_ID_REG);
        !           311:        pci_decompose_tag(pc, tag, &bus, &device, &function);
        !           312:        printf("%03d:%02d:%d 0x%04x 0x%04x ", bus, device, function,
        !           313:            PCI_VENDOR(id), PCI_PRODUCT(id));
        !           314: }
        !           315:

CVSweb