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

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

1.1     ! nbrk        1: /*     $OpenBSD: sti_pci.c,v 1.6 2007/06/17 12:07:10 miod Exp $        */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2006, 2007 Miodrag Vallat.
        !             5:  *
        !             6:  * Permission to use, copy, modify, and distribute this software for any
        !             7:  * purpose with or without fee is hereby granted, provided that the above
        !             8:  * copyright notice, this permission notice, and the disclaimer below
        !             9:  * appear in all copies.
        !            10:  *
        !            11:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
        !            12:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
        !            13:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
        !            14:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
        !            15:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
        !            16:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
        !            17:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
        !            18:  */
        !            19:
        !            20: #include <sys/param.h>
        !            21: #include <sys/systm.h>
        !            22: #include <sys/device.h>
        !            23:
        !            24: #include <dev/pci/pcireg.h>
        !            25: #include <dev/pci/pcivar.h>
        !            26: #include <dev/pci/pcidevs.h>
        !            27:
        !            28: #include <dev/wscons/wsdisplayvar.h>
        !            29:
        !            30: #include <dev/ic/stireg.h>
        !            31: #include <dev/ic/stivar.h>
        !            32:
        !            33: int    sti_pci_match(struct device *, void *, void *);
        !            34: void   sti_pci_attach(struct device *, struct device *, void *);
        !            35:
        !            36: struct sti_pci_softc {
        !            37:        struct sti_softc        sc_base;
        !            38:
        !            39:        pci_chipset_tag_t       sc_pc;
        !            40:        pcitag_t                sc_tag;
        !            41: };
        !            42:
        !            43: struct cfattach sti_pci_ca = {
        !            44:        sizeof(struct sti_pci_softc), sti_pci_match, sti_pci_attach
        !            45: };
        !            46:
        !            47: const struct pci_matchid sti_pci_devices[] = {
        !            48:        { PCI_VENDOR_HP, PCI_PRODUCT_HP_VISUALIZE_EG },
        !            49:        { PCI_VENDOR_HP, PCI_PRODUCT_HP_VISUALIZE_FX2 },
        !            50:        { PCI_VENDOR_HP, PCI_PRODUCT_HP_VISUALIZE_FX4 },
        !            51:        { PCI_VENDOR_HP, PCI_PRODUCT_HP_VISUALIZE_FX6 },
        !            52:        { PCI_VENDOR_HP, PCI_PRODUCT_HP_VISUALIZE_FXE },
        !            53: };
        !            54:
        !            55: int    sti_readbar(struct sti_softc *, struct pci_attach_args *, u_int, int);
        !            56: int    sti_check_rom(struct sti_pci_softc *, struct pci_attach_args *);
        !            57: void   sti_pci_enable_rom(struct sti_softc *);
        !            58: void   sti_pci_disable_rom(struct sti_softc *);
        !            59:
        !            60: int    sti_pci_is_console(struct pci_attach_args *, bus_addr_t *);
        !            61:
        !            62: int
        !            63: sti_pci_match(struct device *parent, void *cf, void *aux)
        !            64: {
        !            65:        struct pci_attach_args *paa = aux;
        !            66:
        !            67:        return (pci_matchbyid(paa, sti_pci_devices,
        !            68:            sizeof(sti_pci_devices) / sizeof(sti_pci_devices[0])));
        !            69: }
        !            70:
        !            71: void
        !            72: sti_pci_attach(struct device *parent, struct device *self, void *aux)
        !            73: {
        !            74:        struct sti_pci_softc *spc = (void *)self;
        !            75:        struct pci_attach_args *paa = aux;
        !            76:
        !            77:        spc->sc_pc = paa->pa_pc;
        !            78:        spc->sc_tag = paa->pa_tag;
        !            79:        spc->sc_base.sc_enable_rom = sti_pci_enable_rom;
        !            80:        spc->sc_base.sc_disable_rom = sti_pci_disable_rom;
        !            81:
        !            82:        printf("\n");
        !            83:
        !            84:        if (sti_check_rom(spc, paa) != 0)
        !            85:                return;
        !            86:
        !            87:        printf("%s", self->dv_xname);
        !            88:        if (sti_attach_common(&spc->sc_base, STI_CODEBASE_MAIN) == 0) {
        !            89:                if (sti_pci_is_console(paa, spc->sc_base.bases) != 0)
        !            90:                        spc->sc_base.sc_flags |= STI_CONSOLE;
        !            91:                startuphook_establish(sti_end_attach, spc);
        !            92:        }
        !            93: }
        !            94:
        !            95: /*
        !            96:  * Grovel the STI ROM image.
        !            97:  */
        !            98: int
        !            99: sti_check_rom(struct sti_pci_softc *spc, struct pci_attach_args *pa)
        !           100: {
        !           101:        struct sti_softc *sc = &spc->sc_base;
        !           102:        pcireg_t address, mask;
        !           103:        bus_space_handle_t romh;
        !           104:        bus_size_t romsize, subsize, stiromsize;
        !           105:        bus_addr_t selected, offs, suboffs;
        !           106:        u_int32_t tmp;
        !           107:        int i;
        !           108:        int rc;
        !           109:
        !           110:        /* sort of inline sti_pci_enable_rom(sc) */
        !           111:        address = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
        !           112:        pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, ~PCI_ROM_ENABLE);
        !           113:        mask = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_ROM_REG);
        !           114:        address |= PCI_ROM_ENABLE;
        !           115:        pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_ROM_REG, address);
        !           116:        sc->sc_flags |= STI_ROM_ENABLED;
        !           117:
        !           118:        /*
        !           119:         * Map the complete ROM for now.
        !           120:         */
        !           121:
        !           122:        romsize = PCI_ROM_SIZE(mask);
        !           123:        rc = bus_space_map(pa->pa_memt, PCI_ROM_ADDR(address), romsize,
        !           124:            0, &romh);
        !           125:        sti_pci_disable_rom(sc);
        !           126:        if (rc != 0) {
        !           127:                printf("%s: can't map PCI ROM (%d)\n",
        !           128:                    sc->sc_dev.dv_xname, rc);
        !           129:                goto fail2;
        !           130:        }
        !           131:
        !           132:        /*
        !           133:         * Iterate over the ROM images, pick the best candidate.
        !           134:         */
        !           135:
        !           136:        selected = (bus_addr_t)-1;
        !           137:        for (offs = 0; offs < romsize; offs += subsize) {
        !           138:                sti_pci_enable_rom(sc);
        !           139:                /*
        !           140:                 * Check for a valid ROM header.
        !           141:                 */
        !           142:                tmp = bus_space_read_4(pa->pa_memt, romh, offs + 0);
        !           143:                tmp = letoh32(tmp);
        !           144:                if (tmp != 0x55aa0000) {
        !           145:                        sti_pci_disable_rom(sc);
        !           146:                        if (offs == 0) {
        !           147:                                printf("%s: invalid PCI ROM header signature"
        !           148:                                    " (%08x)\n",
        !           149:                                    sc->sc_dev.dv_xname, tmp);
        !           150:                                rc = EINVAL;
        !           151:                        }
        !           152:                        break;
        !           153:                }
        !           154:
        !           155:                /*
        !           156:                 * Check ROM type.
        !           157:                 */
        !           158:                tmp = bus_space_read_4(pa->pa_memt, romh, offs + 4);
        !           159:                tmp = letoh32(tmp);
        !           160:                if (tmp != 0x00000001) {        /* 1 == STI ROM */
        !           161:                        sti_pci_disable_rom(sc);
        !           162:                        if (offs == 0) {
        !           163:                                printf("%s: invalid PCI ROM type (%08x)\n",
        !           164:                                    sc->sc_dev.dv_xname, tmp);
        !           165:                                rc = EINVAL;
        !           166:                        }
        !           167:                        break;
        !           168:                }
        !           169:
        !           170:                subsize = (bus_addr_t)bus_space_read_2(pa->pa_memt, romh,
        !           171:                    offs + 0x0c);
        !           172:                subsize <<= 9;
        !           173:
        !           174: #ifdef STIDEBUG
        !           175:                sti_pci_disable_rom(sc);
        !           176:                printf("ROM offset %08x size %08x type %08x",
        !           177:                    offs, subsize, tmp);
        !           178:                sti_pci_enable_rom(sc);
        !           179: #endif
        !           180:
        !           181:                /*
        !           182:                 * Check for a valid ROM data structure.
        !           183:                 * We do not need it except to know what architecture the ROM
        !           184:                 * code is for.
        !           185:                 */
        !           186:
        !           187:                suboffs = offs +(bus_addr_t)bus_space_read_2(pa->pa_memt, romh,
        !           188:                    offs + 0x18);
        !           189:                tmp = bus_space_read_4(pa->pa_memt, romh, suboffs + 0);
        !           190:                tmp = letoh32(tmp);
        !           191:                if (tmp != 0x50434952) {        /* PCIR */
        !           192:                        sti_pci_disable_rom(sc);
        !           193:                        if (offs == 0) {
        !           194:                                printf("%s: invalid PCI data signature"
        !           195:                                    " (%08x)\n",
        !           196:                                    sc->sc_dev.dv_xname, tmp);
        !           197:                                rc = EINVAL;
        !           198:                        } else {
        !           199: #ifdef STIDEBUG
        !           200:                                printf(" invalid PCI data signature %08x\n",
        !           201:                                    tmp);
        !           202: #endif
        !           203:                                continue;
        !           204:                        }
        !           205:                }
        !           206:
        !           207:                tmp = bus_space_read_1(pa->pa_memt, romh, suboffs + 0x14);
        !           208:                sti_pci_disable_rom(sc);
        !           209: #ifdef STIDEBUG
        !           210:                printf(" code %02x", tmp);
        !           211: #endif
        !           212:
        !           213:                switch (tmp) {
        !           214: #ifdef __hppa__
        !           215:                case 0x10:
        !           216:                        if (selected == (bus_addr_t)-1)
        !           217:                                selected = offs;
        !           218:                        break;
        !           219: #endif
        !           220: #ifdef __i386__
        !           221:                case 0x00:
        !           222:                        if (selected == (bus_addr_t)-1)
        !           223:                                selected = offs;
        !           224:                        break;
        !           225: #endif
        !           226:                default:
        !           227: #ifdef STIDEBUG
        !           228:                        printf(" (wrong architecture)");
        !           229: #endif
        !           230:                        break;
        !           231:                }
        !           232:
        !           233: #ifdef STIDEBUG
        !           234:                if (selected == offs)
        !           235:                        printf(" -> SELECTED");
        !           236:                printf("\n");
        !           237: #endif
        !           238:        }
        !           239:
        !           240:        if (selected == (bus_addr_t)-1) {
        !           241:                if (rc == 0) {
        !           242:                        printf("%s: found no ROM with correct microcode"
        !           243:                            " architecture\n", sc->sc_dev.dv_xname);
        !           244:                        rc = ENOEXEC;
        !           245:                }
        !           246:                goto fail;
        !           247:        }
        !           248:
        !           249:        /*
        !           250:         * Read the STI region BAR assignments.
        !           251:         */
        !           252:
        !           253:        sti_pci_enable_rom(sc);
        !           254:        offs = selected +
        !           255:            (bus_addr_t)bus_space_read_2(pa->pa_memt, romh, selected + 0x0e);
        !           256:        for (i = 0; i < STI_REGION_MAX; i++) {
        !           257:                rc = sti_readbar(sc, pa, i,
        !           258:                    bus_space_read_1(pa->pa_memt, romh, offs + i));
        !           259:                if (rc != 0)
        !           260:                        goto fail;
        !           261:        }
        !           262:
        !           263:        /*
        !           264:         * Find out where the STI ROM itself lies, and its size.
        !           265:         */
        !           266:
        !           267:        offs = selected +
        !           268:            (bus_addr_t)bus_space_read_4(pa->pa_memt, romh, selected + 0x08);
        !           269:        stiromsize = (bus_addr_t)bus_space_read_4(pa->pa_memt, romh,
        !           270:            offs + 0x18);
        !           271:        stiromsize = letoh32(stiromsize);
        !           272:        sti_pci_disable_rom(sc);
        !           273:
        !           274:        /*
        !           275:         * Replace our mapping with a smaller mapping of only the area
        !           276:         * we are interested in.
        !           277:         */
        !           278:
        !           279:        bus_space_unmap(pa->pa_memt, romh, romsize);
        !           280:        rc = bus_space_map(pa->pa_memt, PCI_ROM_ADDR(address) + offs,
        !           281:            stiromsize, 0, &sc->romh);
        !           282:        if (rc != 0) {
        !           283:                printf("%s: can't map STI ROM (%d)\n",
        !           284:                    sc->sc_dev.dv_xname, rc);
        !           285:                goto fail2;
        !           286:        }
        !           287:        sc->memt = pa->pa_memt;
        !           288:
        !           289:        return (0);
        !           290:
        !           291: fail:
        !           292:        bus_space_unmap(pa->pa_memt, romh, romsize);
        !           293: fail2:
        !           294:        sti_pci_disable_rom(sc);
        !           295:
        !           296:        return (rc);
        !           297: }
        !           298:
        !           299: /*
        !           300:  * Decode a BAR register.
        !           301:  */
        !           302: int
        !           303: sti_readbar(struct sti_softc *sc, struct pci_attach_args *pa, u_int region,
        !           304:     int bar)
        !           305: {
        !           306:        bus_addr_t addr;
        !           307:        bus_size_t size;
        !           308:        u_int32_t cf;
        !           309:        int rc;
        !           310:
        !           311:        if (bar == 0) {
        !           312:                sc->bases[region] = 0;
        !           313:                return (0);
        !           314:        }
        !           315:
        !           316: #ifdef DIAGNOSTIC
        !           317:        if (bar < PCI_MAPREG_START || bar > PCI_MAPREG_PPB_END) {
        !           318:                sti_pci_disable_rom(sc);
        !           319:                printf("%s: unexpected bar %02x for region %d\n",
        !           320:                    sc->sc_dev.dv_xname, bar, region);
        !           321:                sti_pci_enable_rom(sc);
        !           322:        }
        !           323: #endif
        !           324:
        !           325:        cf = pci_conf_read(pa->pa_pc, pa->pa_tag, bar);
        !           326:
        !           327:        if (PCI_MAPREG_TYPE(cf) == PCI_MAPREG_TYPE_IO)
        !           328:                rc = pci_io_find(pa->pa_pc, pa->pa_tag, bar, &addr, &size);
        !           329:        else
        !           330:                rc = pci_mem_find(pa->pa_pc, pa->pa_tag, bar, &addr, &size,
        !           331:                    NULL);
        !           332:
        !           333:        if (rc != 0) {
        !           334:                sti_pci_disable_rom(sc);
        !           335:                printf("%s: invalid bar %02x for region %d\n",
        !           336:                    sc->sc_dev.dv_xname, bar, region);
        !           337:                sti_pci_enable_rom(sc);
        !           338:                return (rc);
        !           339:        }
        !           340:
        !           341:        sc->bases[region] = addr;
        !           342:        return (0);
        !           343: }
        !           344:
        !           345: /*
        !           346:  * Enable PCI ROM.
        !           347:  */
        !           348: void
        !           349: sti_pci_enable_rom(struct sti_softc *sc)
        !           350: {
        !           351:        struct sti_pci_softc *spc = (struct sti_pci_softc *)sc;
        !           352:        pcireg_t address;
        !           353:
        !           354:        if (!ISSET(sc->sc_flags, STI_ROM_ENABLED)) {
        !           355:                address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_ROM_REG);
        !           356:                address |= PCI_ROM_ENABLE;
        !           357:                pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_ROM_REG, address);
        !           358:                SET(sc->sc_flags, STI_ROM_ENABLED);
        !           359:        }
        !           360: }
        !           361:
        !           362: /*
        !           363:  * Disable PCI ROM.
        !           364:  */
        !           365: void
        !           366: sti_pci_disable_rom(struct sti_softc *sc)
        !           367: {
        !           368:        struct sti_pci_softc *spc = (struct sti_pci_softc *)sc;
        !           369:        pcireg_t address;
        !           370:
        !           371:        if (ISSET(sc->sc_flags, STI_ROM_ENABLED)) {
        !           372:                address = pci_conf_read(spc->sc_pc, spc->sc_tag, PCI_ROM_REG);
        !           373:                address &= ~PCI_ROM_ENABLE;
        !           374:                pci_conf_write(spc->sc_pc, spc->sc_tag, PCI_ROM_REG, address);
        !           375:
        !           376:                CLR(sc->sc_flags, STI_ROM_ENABLED);
        !           377:        }
        !           378: }

CVSweb