[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

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