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

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

1.1     ! nbrk        1: /*     $OpenBSD: ahd_pci.c,v 1.15 2006/10/19 10:55:56 tom Exp $        */
        !             2:
        !             3: /*
        !             4:  * Copyright (c) 2004 Milos Urbanek, Kenneth R. Westerback & Marco Peereboom
        !             5:  * All rights reserved.
        !             6:  *
        !             7:  * Redistribution and use in source and binary forms, with or without
        !             8:  * modification, are permitted provided that the following conditions
        !             9:  * are met:
        !            10:  * 1. Redistributions of source code must retain the above copyright
        !            11:  *    notice, this list of conditions and the following disclaimer.
        !            12:  * 2. Redistributions in binary form must reproduce the above copyright
        !            13:  *    notice, this list of conditions and the following disclaimer in the
        !            14:  *    documentation and/or other materials provided with the distribution.
        !            15:  *
        !            16:  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
        !            17:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            18:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            19:  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR
        !            20:  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            21:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            22:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            23:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            24:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            25:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            26:  * SUCH DAMAGE.
        !            27:  *
        !            28:  */
        !            29:
        !            30: /*
        !            31:  * Product specific probe and attach routines for:
        !            32:  *     aic7901 and aic7902 SCSI controllers
        !            33:  *
        !            34:  * Copyright (c) 1994-2001 Justin T. Gibbs.
        !            35:  * Copyright (c) 2000-2002 Adaptec Inc.
        !            36:  * All rights reserved.
        !            37:  *
        !            38:  * Redistribution and use in source and binary forms, with or without
        !            39:  * modification, are permitted provided that the following conditions
        !            40:  * are met:
        !            41:  * 1. Redistributions of source code must retain the above copyright
        !            42:  *    notice, this list of conditions, and the following disclaimer,
        !            43:  *    without modification.
        !            44:  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
        !            45:  *    substantially similar to the "NO WARRANTY" disclaimer below
        !            46:  *    ("Disclaimer") and any redistribution must be conditioned upon
        !            47:  *    including a substantially similar Disclaimer requirement for further
        !            48:  *    binary redistribution.
        !            49:  * 3. Neither the names of the above-listed copyright holders nor the names
        !            50:  *    of any contributors may be used to endorse or promote products derived
        !            51:  *    from this software without specific prior written permission.
        !            52:  *
        !            53:  * Alternatively, this software may be distributed under the terms of the
        !            54:  * GNU General Public License ("GPL") version 2 as published by the Free
        !            55:  * Software Foundation.
        !            56:  *
        !            57:  * NO WARRANTY
        !            58:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        !            59:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        !            60:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
        !            61:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
        !            62:  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            63:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            64:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            65:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            66:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
        !            67:  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            68:  * POSSIBILITY OF SUCH DAMAGES.
        !            69:  *
        !            70:  */
        !            71:
        !            72: #include <sys/cdefs.h>
        !            73: /*
        !            74: __FBSDID("$FreeBSD: src/sys/dev/aic7xxx/aic79xx_pci.c,v 1.18 2004/02/04 16:38:38 gibbs Exp $");
        !            75: */
        !            76:
        !            77: #include <dev/ic/aic79xx_openbsd.h>
        !            78: #include <dev/ic/aic79xx_inline.h>
        !            79: #include <dev/ic/aic79xx.h>
        !            80:
        !            81: #include <dev/pci/pcivar.h>
        !            82:
        !            83: __inline uint64_t ahd_compose_id(u_int, u_int, u_int, u_int);
        !            84: __inline uint64_t
        !            85: ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
        !            86: {
        !            87:        uint64_t id;
        !            88:
        !            89:        id = subvendor
        !            90:           | (subdevice << 16)
        !            91:           | ((uint64_t)vendor << 32)
        !            92:           | ((uint64_t)device << 48);
        !            93:
        !            94:        return (id);
        !            95: }
        !            96:
        !            97: #define ID_ALL_MASK                    0xFFFFFFFFFFFFFFFFull
        !            98: #define ID_ALL_IROC_MASK               0xFF7FFFFFFFFFFFFFull
        !            99: #define ID_DEV_VENDOR_MASK             0xFFFFFFFF00000000ull
        !           100: #define ID_9005_GENERIC_MASK           0xFFF0FFFF00000000ull
        !           101: #define ID_9005_GENERIC_IROC_MASK      0xFF70FFFF00000000ull
        !           102:
        !           103: #define ID_AIC7901                     0x800F9005FFFF9005ull
        !           104: #define ID_AHA_29320A                  0x8000900500609005ull
        !           105: #define ID_AHA_29320ALP                        0x8017900500449005ull
        !           106:
        !           107: #define ID_AIC7901A                    0x801E9005FFFF9005ull
        !           108: #define ID_AHA_29320LP                 0x8014900500449005ull
        !           109:
        !           110: #define ID_AIC7902                     0x801F9005FFFF9005ull
        !           111: #define ID_AIC7902_B                   0x801D9005FFFF9005ull
        !           112: #define ID_AHA_39320                   0x8010900500409005ull
        !           113: #define ID_AHA_29320                   0x8012900500429005ull
        !           114: #define ID_AHA_29320B                  0x8013900500439005ull
        !           115: #define ID_AHA_39320_B                 0x8015900500409005ull
        !           116: #define ID_AHA_39320_B_DELL            0x8015900501681028ull
        !           117: #define ID_AHA_39320A                  0x8016900500409005ull
        !           118: #define ID_AHA_39320D                  0x8011900500419005ull
        !           119: #define ID_AHA_39320D_B                        0x801C900500419005ull
        !           120: #define ID_AHA_39320D_HP               0x8011900500AC0E11ull
        !           121: #define ID_AHA_39320D_B_HP             0x801C900500AC0E11ull
        !           122: #define ID_AIC7902_PCI_REV_A4          0x3
        !           123: #define ID_AIC7902_PCI_REV_B0          0x10
        !           124: #define SUBID_HP                       0x0E11
        !           125:
        !           126: #define DEVID_9005_HOSTRAID(id) ((id) & 0x80)
        !           127:
        !           128: #define DEVID_9005_TYPE(id) ((id) & 0xF)
        !           129: #define                DEVID_9005_TYPE_HBA             0x0     /* Standard Card */
        !           130: #define                DEVID_9005_TYPE_HBA_2EXT        0x1     /* 2 External Ports */
        !           131: #define                DEVID_9005_TYPE_MB              0xF     /* On Motherboard */
        !           132:
        !           133: #define DEVID_9005_MFUNC(id) ((id) & 0x10)
        !           134:
        !           135: #define DEVID_9005_PACKETIZED(id) ((id) & 0x8000)
        !           136:
        !           137: #define SUBID_9005_TYPE(id) ((id) & 0xF)
        !           138: #define                SUBID_9005_TYPE_HBA             0x0     /* Standard Card */
        !           139: #define                SUBID_9005_TYPE_MB              0xF     /* On Motherboard */
        !           140:
        !           141: #define SUBID_9005_AUTOTERM(id)        (((id) & 0x10) == 0)
        !           142:
        !           143: #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)
        !           144:
        !           145: #define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6)
        !           146: #define                SUBID_9005_SEEPTYPE_NONE        0x0
        !           147: #define                SUBID_9005_SEEPTYPE_4K          0x1
        !           148:
        !           149: ahd_device_setup_t ahd_aic7901_setup;
        !           150: ahd_device_setup_t ahd_aic7901A_setup;
        !           151: ahd_device_setup_t ahd_aic7902_setup;
        !           152: ahd_device_setup_t ahd_aic790X_setup;
        !           153:
        !           154: struct ahd_pci_identity ahd_pci_ident_table [] =
        !           155: {
        !           156:        /* aic7901 based controllers */
        !           157:        {
        !           158:                ID_AHA_29320A,
        !           159:                ID_ALL_MASK,
        !           160:                ahd_aic7901_setup
        !           161:        },
        !           162:        {
        !           163:                ID_AHA_29320ALP,
        !           164:                ID_ALL_MASK,
        !           165:                ahd_aic7901_setup
        !           166:        },
        !           167:        /* aic7901A based controllers */
        !           168:        {
        !           169:                ID_AHA_29320LP,
        !           170:                ID_ALL_MASK,
        !           171:                ahd_aic7901A_setup
        !           172:        },
        !           173:        /* aic7902 based controllers */
        !           174:        {
        !           175:                ID_AHA_29320,
        !           176:                ID_ALL_MASK,
        !           177:                ahd_aic7902_setup
        !           178:        },
        !           179:        {
        !           180:                ID_AHA_29320B,
        !           181:                ID_ALL_MASK,
        !           182:                ahd_aic7902_setup
        !           183:        },
        !           184:        {
        !           185:                ID_AHA_39320,
        !           186:                ID_ALL_MASK,
        !           187:                ahd_aic7902_setup
        !           188:        },
        !           189:        {
        !           190:                ID_AHA_39320_B,
        !           191:                ID_ALL_MASK,
        !           192:                ahd_aic7902_setup
        !           193:        },
        !           194:        {
        !           195:                ID_AHA_39320_B_DELL,
        !           196:                ID_ALL_MASK,
        !           197:                ahd_aic7902_setup
        !           198:        },
        !           199:        {
        !           200:                ID_AHA_39320A,
        !           201:                ID_ALL_MASK,
        !           202:                ahd_aic7902_setup
        !           203:        },
        !           204:        {
        !           205:                ID_AHA_39320D,
        !           206:                ID_ALL_MASK,
        !           207:                ahd_aic7902_setup
        !           208:        },
        !           209:        {
        !           210:                ID_AHA_39320D_HP,
        !           211:                ID_ALL_MASK,
        !           212:                ahd_aic7902_setup
        !           213:        },
        !           214:        {
        !           215:                ID_AHA_39320D_B,
        !           216:                ID_ALL_MASK,
        !           217:                ahd_aic7902_setup
        !           218:        },
        !           219:        {
        !           220:                ID_AHA_39320D_B_HP,
        !           221:                ID_ALL_MASK,
        !           222:                ahd_aic7902_setup
        !           223:        },
        !           224:        /* Generic chip probes for devices we don't know 'exactly' */
        !           225:        {
        !           226:                ID_AIC7901 & ID_9005_GENERIC_MASK,
        !           227:                ID_9005_GENERIC_MASK,
        !           228:                ahd_aic7901_setup
        !           229:        },
        !           230:        {
        !           231:                ID_AIC7901A & ID_DEV_VENDOR_MASK,
        !           232:                ID_DEV_VENDOR_MASK,
        !           233:                ahd_aic7901A_setup
        !           234:        },
        !           235:        {
        !           236:                ID_AIC7902 & ID_9005_GENERIC_MASK,
        !           237:                ID_9005_GENERIC_MASK,
        !           238:                ahd_aic7902_setup
        !           239:        }
        !           240: };
        !           241:
        !           242: const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table);
        !           243:
        !           244: #define                        DEVCONFIG               0x40
        !           245: #define                        PCIXINITPAT             0x0000E000ul
        !           246: #define                        PCIXINIT_PCI33_66       0x0000E000ul
        !           247: #define                        PCIXINIT_PCIX50_66      0x0000C000ul
        !           248: #define                        PCIXINIT_PCIX66_100     0x0000A000ul
        !           249: #define                        PCIXINIT_PCIX100_133    0x00008000ul
        !           250: #define        PCI_BUS_MODES_INDEX(devconfig)  \
        !           251:        (((devconfig) & PCIXINITPAT) >> 13)
        !           252:
        !           253: static const char *pci_bus_modes[] =
        !           254: {
        !           255:        "PCI bus mode unknown",
        !           256:        "PCI bus mode unknown",
        !           257:        "PCI bus mode unknown",
        !           258:        "PCI bus mode unknown",
        !           259:        "PCI-X 101-133MHz",
        !           260:        "PCI-X 67-100MHz",
        !           261:        "PCI-X 50-66MHz",
        !           262:        "PCI 33 or 66MHz"
        !           263: };
        !           264:
        !           265: #define                TESTMODE        0x00000800ul
        !           266: #define                IRDY_RST        0x00000200ul
        !           267: #define                FRAME_RST       0x00000100ul
        !           268: #define                PCI64BIT        0x00000080ul
        !           269: #define                MRDCEN          0x00000040ul
        !           270: #define                ENDIANSEL       0x00000020ul
        !           271: #define                MIXQWENDIANEN   0x00000008ul
        !           272: #define                DACEN           0x00000004ul
        !           273: #define                STPWLEVEL       0x00000002ul
        !           274: #define                QWENDIANSEL     0x00000001ul
        !           275:
        !           276: #define        DEVCONFIG1              0x44
        !           277: #define                PREQDIS         0x01
        !           278:
        !           279: #define        CSIZE_LATTIME           0x0c
        !           280: #define                CACHESIZE       0x000000fful
        !           281: #define                LATTIME         0x0000ff00ul
        !           282:
        !           283: int    ahd_pci_probe(struct device *, void *, void *);
        !           284: void   ahd_pci_attach(struct device *, struct device *, void *);
        !           285:
        !           286: struct cfattach ahd_pci_ca = {
        !           287:                sizeof(struct ahd_softc), ahd_pci_probe, ahd_pci_attach
        !           288: };
        !           289:
        !           290: int    ahd_check_extport(struct ahd_softc *ahd);
        !           291: void   ahd_configure_termination(struct ahd_softc *ahd,
        !           292:                                          u_int adapter_control);
        !           293: void   ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
        !           294:
        !           295: const struct ahd_pci_identity *
        !           296: ahd_find_pci_device(pcireg_t id, pcireg_t subid)
        !           297: {
        !           298:        const struct ahd_pci_identity *entry;
        !           299:        u_int64_t full_id;
        !           300:        u_int i;
        !           301:
        !           302:        full_id = ahd_compose_id(PCI_PRODUCT(id), PCI_VENDOR(id),
        !           303:            PCI_PRODUCT(subid), PCI_VENDOR(subid));
        !           304:
        !           305:        /*
        !           306:         * If we are configured to attach to HostRAID
        !           307:         * controllers, mask out the IROC/HostRAID bit
        !           308:         * in the
        !           309:         */
        !           310:        if (ahd_attach_to_HostRAID_controllers)
        !           311:                full_id &= ID_ALL_IROC_MASK;
        !           312:
        !           313:        for (i = 0; i < ahd_num_pci_devs; i++) {
        !           314:                entry = &ahd_pci_ident_table[i];
        !           315:                if (entry->full_id == (full_id & entry->id_mask)) {
        !           316:                        return (entry);
        !           317:                }
        !           318:        }
        !           319:        return (NULL);
        !           320: }
        !           321:
        !           322: int
        !           323: ahd_pci_probe(struct device *parent, void *match, void *aux)
        !           324: {
        !           325:        const struct ahd_pci_identity *entry;
        !           326:        struct pci_attach_args *pa = aux;
        !           327:        pcireg_t subid;
        !           328:
        !           329:        subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
        !           330:        entry = ahd_find_pci_device(pa->pa_id, subid);
        !           331:        return entry != NULL ? 1 : 0;
        !           332: }
        !           333:
        !           334: void
        !           335: ahd_pci_attach(struct device *parent, struct device *self, void *aux)
        !           336: {
        !           337:        const struct ahd_pci_identity *entry;
        !           338:        struct pci_attach_args *pa = aux;
        !           339:        struct ahd_softc *ahd = (void *)self;
        !           340:        pci_intr_handle_t ih;
        !           341:        const char *intrstr;
        !           342:        pcireg_t devconfig, memtype, reg, subid;
        !           343:        uint16_t device, subvendor;
        !           344:        int error, ioh_valid, ioh2_valid, l, memh_valid, offset;
        !           345:
        !           346:        ahd->dev_softc = pa;
        !           347:        ahd->parent_dmat = pa->pa_dmat;
        !           348:
        !           349:        if (ahd_alloc(ahd, ahd->sc_dev.dv_xname) == NULL)
        !           350:                return;
        !           351:
        !           352:        subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
        !           353:        entry = ahd_find_pci_device(pa->pa_id, subid);
        !           354:        if (entry == NULL)
        !           355:                return;
        !           356:
        !           357:        /*
        !           358:         * Record if this is a HostRAID board.
        !           359:         */
        !           360:        device = PCI_PRODUCT(pa->pa_id);
        !           361:        if (DEVID_9005_HOSTRAID(device))
        !           362:                ahd->flags |= AHD_HOSTRAID_BOARD;
        !           363:
        !           364:        /*
        !           365:         * Record if this is an HP board.
        !           366:         */
        !           367:        subvendor = PCI_VENDOR(subid);
        !           368:        if (subvendor == SUBID_HP)
        !           369:                ahd->flags |= AHD_HP_BOARD;
        !           370:
        !           371:        error = entry->setup(ahd, pa);
        !           372:        if (error != 0)
        !           373:                return;
        !           374:
        !           375:        /* XXX ahc on sparc64 needs this twice */
        !           376:        devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
        !           377:
        !           378:        if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) {
        !           379:                ahd->chip |= AHD_PCI;
        !           380:                /* Disable PCIX workarounds when running in PCI mode. */
        !           381:                ahd->bugs &= ~AHD_PCIX_BUG_MASK;
        !           382:        } else {
        !           383:                ahd->chip |= AHD_PCIX;
        !           384:        }
        !           385:        ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];
        !           386:
        !           387:        memh_valid = ioh_valid = ioh2_valid = 0;
        !           388:
        !           389:        if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIX,
        !           390:            &ahd->pcix_off, NULL)) {
        !           391:                if (ahd->chip & AHD_PCIX)
        !           392:                        printf("%s: warning: can't find PCI-X capability\n",
        !           393:                            ahd_name(ahd));
        !           394:                ahd->chip &= ~AHD_PCIX;
        !           395:                ahd->chip |= AHD_PCI;
        !           396:                ahd->bugs &= ~AHD_PCIX_BUG_MASK;
        !           397:        }
        !           398:
        !           399:        /*
        !           400:         * Map PCI registers
        !           401:         */
        !           402:        if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0) {
        !           403:                memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag,
        !           404:                    AHD_PCI_MEMADDR);
        !           405:                switch (memtype) {
        !           406:                case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
        !           407:                case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
        !           408:                        memh_valid = (pci_mapreg_map(pa, AHD_PCI_MEMADDR,
        !           409:                            memtype, 0, &ahd->tags[0], &ahd->bshs[0], NULL,
        !           410:                            NULL, 0) == 0);
        !           411:                        if (memh_valid) {
        !           412:                                ahd->tags[1] = ahd->tags[0];
        !           413:                                bus_space_subregion(ahd->tags[0], ahd->bshs[0],
        !           414:                                    /*offset*/0x100, /*size*/0x100,
        !           415:                                    &ahd->bshs[1]);
        !           416:                                if (ahd_pci_test_register_access(ahd) != 0)
        !           417:                                        memh_valid = 0;
        !           418:                        }
        !           419:                        break;
        !           420:                default:
        !           421:                        memh_valid = 0;
        !           422:                        printf("%s: unknown memory type: 0x%x\n",
        !           423:                        ahd_name(ahd), memtype);
        !           424:                        break;
        !           425:                }
        !           426:
        !           427: #ifdef AHD_DEBUG
        !           428:                printf("%s: doing memory mapping tag0 0x%x, tag1 0x%x, shs0 "
        !           429:                    "0x%lx, shs1 0x%lx\n", ahd_name(ahd), ahd->tags[0],
        !           430:                    ahd->tags[1], ahd->bshs[0], ahd->bshs[1]);
        !           431: #endif
        !           432:        }
        !           433:
        !           434:        if (!memh_valid) {
        !           435:                /* First BAR */
        !           436:                ioh_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR,
        !           437:                    PCI_MAPREG_TYPE_IO, 0, &ahd->tags[0], &ahd->bshs[0], NULL,
        !           438:                    NULL, 0) == 0);
        !           439:
        !           440:                /* 2nd BAR */
        !           441:                ioh2_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR1,
        !           442:                    PCI_MAPREG_TYPE_IO, 0, &ahd->tags[1], &ahd->bshs[1], NULL,
        !           443:                    NULL, 0) == 0);
        !           444:
        !           445: #ifdef AHD_DEBUG
        !           446:                printf("%s: doing io mapping tag0 0x%x, tag1 0x%x, shs0 0x%lx, "
        !           447:                    "shs1 0x%lx\n", ahd_name(ahd), ahd->tags[0], ahd->tags[1],
        !           448:                    ahd->bshs[0], ahd->bshs[1]);
        !           449: #endif
        !           450:        }
        !           451:
        !           452:        if (memh_valid == 0 && (ioh_valid == 0 || ioh2_valid == 0)) {
        !           453:                printf("%s: unable to map registers\n", ahd_name(ahd));
        !           454:                return;
        !           455:        }
        !           456:
        !           457:        /*
        !           458:         * Set Power State D0.
        !           459:         */
        !           460:        if (pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PWRMGMT, &offset,
        !           461:            NULL)) {
        !           462:                /* Increment offset from cap register to csr register. */
        !           463:                offset += 4;
        !           464:                reg = pci_conf_read(pa->pa_pc, pa->pa_tag, offset);
        !           465:                if ((reg & PCI_PMCSR_STATE_MASK) != PCI_PMCSR_STATE_D0) {
        !           466:                        pci_conf_write(pa->pa_pc, pa->pa_tag, offset,
        !           467:                            (reg & ~PCI_PMCSR_STATE_MASK) | PCI_PMCSR_STATE_D0);
        !           468:                }
        !           469:        }
        !           470:
        !           471:        /*
        !           472:         * Should we bother disabling 39Bit addressing
        !           473:         * based on installed memory?
        !           474:         */
        !           475:        if (sizeof(bus_addr_t) > 4)
        !           476:                ahd->flags |= AHD_39BIT_ADDRESSING;
        !           477:
        !           478:        /*
        !           479:         * If we need to support high memory, enable dual
        !           480:         * address cycles.  This bit must be set to enable
        !           481:         * high address bit generation even if we are on a
        !           482:         * 64bit bus (PCI64BIT set in devconfig).
        !           483:         */
        !           484:        if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) {
        !           485:                pcireg_t devconfig;
        !           486:
        !           487:                if (bootverbose)
        !           488:                        printf("%s: Enabling 39Bit Addressing\n",
        !           489:                               ahd_name(ahd));
        !           490:                devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
        !           491:                devconfig |= DACEN;
        !           492:                pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG, devconfig);
        !           493:        }
        !           494:
        !           495:        ahd_softc_init(ahd);
        !           496:
        !           497:        /*
        !           498:         * Map the interrupts routines
        !           499:         */
        !           500:        ahd->bus_intr = ahd_pci_intr;
        !           501:
        !           502:        error = ahd_reset(ahd, /*reinit*/FALSE);
        !           503:        if (error != 0) {
        !           504:                ahd_free(ahd);
        !           505:                return;
        !           506:        }
        !           507:
        !           508:        if (pci_intr_map(pa, &ih)) {
        !           509:                printf("%s: couldn't map interrupt\n", ahd_name(ahd));
        !           510:                ahd_free(ahd);
        !           511:                return;
        !           512:        }
        !           513:        intrstr = pci_intr_string(pa->pa_pc, ih);
        !           514:        ahd->ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
        !           515:        ahd_platform_intr, ahd, ahd->sc_dev.dv_xname);
        !           516:        if (ahd->ih == NULL) {
        !           517:                printf("%s: couldn't establish interrupt", ahd_name(ahd));
        !           518:                if (intrstr != NULL)
        !           519:                        printf(" at %s", intrstr);
        !           520:                printf("\n");
        !           521:                ahd_free(ahd);
        !           522:                return;
        !           523:        }
        !           524:        if (intrstr != NULL)
        !           525:                printf(": %s\n", intrstr);
        !           526:
        !           527:        /* Get the size of the cache */
        !           528:        ahd->pci_cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG);
        !           529:        ahd->pci_cachesize *= 4;
        !           530:
        !           531:        ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        !           532:        /* See if we have a SEEPROM and perform auto-term */
        !           533:        error = ahd_check_extport(ahd);
        !           534:        if (error != 0)
        !           535:                return;
        !           536:
        !           537:        /* Core initialization */
        !           538:        error = ahd_init(ahd);
        !           539:        if (error != 0)
        !           540:                return;
        !           541:
        !           542:        ahd_list_lock(&l);
        !           543:        /*
        !           544:         * Link this softc in with all other ahd instances.
        !           545:         */
        !           546:        ahd_softc_insert(ahd);
        !           547:        ahd_list_unlock(&l);
        !           548:
        !           549:        /* complete the attach */
        !           550:        ahd_attach(ahd);
        !           551: }
        !           552:
        !           553: /*
        !           554:  * Perform some simple tests that should catch situations where
        !           555:  * our registers are invalidly mapped.
        !           556:  */
        !           557: int
        !           558: ahd_pci_test_register_access(struct ahd_softc *ahd)
        !           559: {
        !           560:        const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
        !           561:        const pcitag_t tag = ahd->dev_softc->pa_tag;
        !           562:        pcireg_t cmd;
        !           563:        u_int    targpcistat;
        !           564:        pcireg_t pci_status1;
        !           565:        int      error;
        !           566:        uint8_t  hcntrl;
        !           567:
        !           568:        error = EIO;
        !           569:
        !           570:        /*
        !           571:         * Enable PCI error interrupt status, but suppress NMIs
        !           572:         * generated by SERR raised due to target aborts.
        !           573:         */
        !           574:        cmd = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
        !           575:        pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG,
        !           576:            cmd & ~PCI_COMMAND_SERR_ENABLE);
        !           577:
        !           578:        /*
        !           579:         * First a simple test to see if any
        !           580:         * registers can be read.  Reading
        !           581:         * HCNTRL has no side effects and has
        !           582:         * at least one bit that is guaranteed to
        !           583:         * be zero so it is a good register to
        !           584:         * use for this test.
        !           585:         */
        !           586:        hcntrl = ahd_inb(ahd, HCNTRL);
        !           587:        if (hcntrl == 0xFF)
        !           588:                goto fail;
        !           589:
        !           590:        /*
        !           591:         * Next create a situation where write combining
        !           592:         * or read prefetching could be initiated by the
        !           593:         * CPU or host bridge.  Our device does not support
        !           594:         * either, so look for data corruption and/or flaged
        !           595:         * PCI errors.  First pause without causing another
        !           596:         * chip reset.
        !           597:         */
        !           598:        hcntrl &= ~CHIPRST;
        !           599:        ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
        !           600:        while (ahd_is_paused(ahd) == 0)
        !           601:                ;
        !           602:
        !           603:        /* Clear any PCI errors that occurred before our driver attached. */
        !           604:        ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
        !           605:        targpcistat = ahd_inb(ahd, TARGPCISTAT);
        !           606:        ahd_outb(ahd, TARGPCISTAT, targpcistat);
        !           607:        pci_status1 = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
        !           608:        pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, pci_status1);
        !           609:        ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
        !           610:        ahd_outb(ahd, CLRINT, CLRPCIINT);
        !           611:
        !           612:        ahd_outb(ahd, SEQCTL0, PERRORDIS);
        !           613:        ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);
        !           614:        if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)
        !           615:                goto fail;
        !           616:
        !           617:        if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
        !           618:                u_int targpcistat;
        !           619:
        !           620:                ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
        !           621:                targpcistat = ahd_inb(ahd, TARGPCISTAT);
        !           622:                if ((targpcistat & STA) != 0)
        !           623:                        goto fail;
        !           624:        }
        !           625:
        !           626:        error = 0;
        !           627:
        !           628: fail:
        !           629:        if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
        !           630:
        !           631:                ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
        !           632:                targpcistat = ahd_inb(ahd, TARGPCISTAT);
        !           633:
        !           634:                /* Silently clear any latched errors. */
        !           635:                ahd_outb(ahd, TARGPCISTAT, targpcistat);
        !           636:                pci_status1 = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
        !           637:                pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, pci_status1);
        !           638:                ahd_outb(ahd, CLRINT, CLRPCIINT);
        !           639:        }
        !           640:        ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);
        !           641:        pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG, cmd);
        !           642:        return (error);
        !           643: }
        !           644:
        !           645: /*
        !           646:  * Check the external port logic for a serial eeprom
        !           647:  * and termination/cable detection contrls.
        !           648:  */
        !           649: int
        !           650: ahd_check_extport(struct ahd_softc *ahd)
        !           651: {
        !           652:        struct  vpd_config vpd;
        !           653:        struct  seeprom_config *sc;
        !           654:        u_int   adapter_control;
        !           655:        int     have_seeprom;
        !           656:        int     error;
        !           657:
        !           658:        sc = ahd->seep_config;
        !           659:        have_seeprom = ahd_acquire_seeprom(ahd);
        !           660:        if (have_seeprom) {
        !           661:                u_int start_addr;
        !           662:
        !           663:                /*
        !           664:                 * Fetch VPD for this function and parse it.
        !           665:                 */
        !           666:                if (bootverbose)
        !           667:                        printf("%s: Reading VPD from SEEPROM...",
        !           668:                               ahd_name(ahd));
        !           669:
        !           670:                /* Address is always in units of 16bit words */
        !           671:                start_addr = ((2 * sizeof(*sc))
        !           672:                            + (sizeof(vpd) * (ahd->channel - 'A'))) / 2;
        !           673:
        !           674:                error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,
        !           675:                                         start_addr, sizeof(vpd)/2,
        !           676:                                         /*bytestream*/TRUE);
        !           677:                if (error == 0)
        !           678:                        error = ahd_parse_vpddata(ahd, &vpd);
        !           679:                if (bootverbose)
        !           680:                        printf("%s: VPD parsing %s\n",
        !           681:                               ahd_name(ahd),
        !           682:                               error == 0 ? "successful" : "failed");
        !           683:
        !           684:                if (bootverbose)
        !           685:                        printf("%s: Reading SEEPROM...", ahd_name(ahd));
        !           686:
        !           687:                /* Address is always in units of 16bit words */
        !           688:                start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');
        !           689:
        !           690:                error = ahd_read_seeprom(ahd, (uint16_t *)sc,
        !           691:                                         start_addr, sizeof(*sc)/2,
        !           692:                                         /*bytestream*/FALSE);
        !           693:
        !           694:                if (error != 0) {
        !           695:                        printf("Unable to read SEEPROM\n");
        !           696:                        have_seeprom = 0;
        !           697:                } else {
        !           698:                        have_seeprom = ahd_verify_cksum(sc);
        !           699:
        !           700:                        if (bootverbose) {
        !           701:                                if (have_seeprom == 0)
        !           702:                                        printf ("checksum error\n");
        !           703:                                else
        !           704:                                        printf ("done.\n");
        !           705:                        }
        !           706:                }
        !           707:                ahd_release_seeprom(ahd);
        !           708:        }
        !           709:
        !           710:        if (!have_seeprom) {
        !           711:                u_int     nvram_scb;
        !           712:
        !           713:                /*
        !           714:                 * Pull scratch ram settings and treat them as
        !           715:                 * if they are the contents of an seeprom if
        !           716:                 * the 'ADPT', 'BIOS', or 'ASPI' signature is found
        !           717:                 * in SCB 0xFF.  We manually compose the data as 16bit
        !           718:                 * values to avoid endian issues.
        !           719:                 */
        !           720:                ahd_set_scbptr(ahd, 0xFF);
        !           721:                nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);
        !           722:                if (nvram_scb != 0xFF
        !           723:                 && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
        !           724:                   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'
        !           725:                   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
        !           726:                   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')
        !           727:                  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'
        !           728:                   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'
        !           729:                   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'
        !           730:                   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')
        !           731:                  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
        !           732:                   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'
        !           733:                   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
        !           734:                   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {
        !           735:                        uint16_t *sc_data;
        !           736:                        int       i;
        !           737:
        !           738:                        ahd_set_scbptr(ahd, nvram_scb);
        !           739:                        sc_data = (uint16_t *)sc;
        !           740:                        for (i = 0; i < 64; i += 2)
        !           741:                                *sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);
        !           742:                        have_seeprom = ahd_verify_cksum(sc);
        !           743:                        if (have_seeprom)
        !           744:                                ahd->flags |= AHD_SCB_CONFIG_USED;
        !           745:                }
        !           746:        }
        !           747:
        !           748: #ifdef AHD_DEBUG
        !           749:        if (have_seeprom != 0
        !           750:         && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
        !           751:                uint16_t *sc_data;
        !           752:                int       i;
        !           753:
        !           754:                printf("%s: Seeprom Contents:", ahd_name(ahd));
        !           755:                sc_data = (uint16_t *)sc;
        !           756:                for (i = 0; i < (sizeof(*sc)); i += 2)
        !           757:                        printf("\n\t0x%.4x", sc_data[i]);
        !           758:                printf("\n");
        !           759:        }
        !           760: #endif
        !           761:
        !           762:        if (!have_seeprom) {
        !           763:                if (bootverbose)
        !           764:                        printf("%s: No SEEPROM available.\n", ahd_name(ahd));
        !           765:                ahd->flags |= AHD_USEDEFAULTS;
        !           766:                error = ahd_default_config(ahd);
        !           767:                adapter_control = CFAUTOTERM|CFSEAUTOTERM;
        !           768:                free(ahd->seep_config, M_DEVBUF);
        !           769:                ahd->seep_config = NULL;
        !           770:        } else {
        !           771:                error = ahd_parse_cfgdata(ahd, sc);
        !           772:                adapter_control = sc->adapter_control;
        !           773:        }
        !           774:        if (error != 0)
        !           775:                return (error);
        !           776:
        !           777:        ahd_configure_termination(ahd, adapter_control);
        !           778:
        !           779:        return (0);
        !           780: }
        !           781:
        !           782: void
        !           783: ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
        !           784: {
        !           785:        const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
        !           786:        const pcitag_t tag = ahd->dev_softc->pa_tag;
        !           787:        int      error;
        !           788:        u_int    sxfrctl1;
        !           789:        uint8_t  termctl;
        !           790:        pcireg_t devconfig;
        !           791:
        !           792:        devconfig = pci_conf_read(pc, tag, DEVCONFIG);
        !           793:        devconfig &= ~STPWLEVEL;
        !           794:        if ((ahd->flags & AHD_STPWLEVEL_A) != 0)
        !           795:                devconfig |= STPWLEVEL;
        !           796:        if (bootverbose)
        !           797:                printf("%s: STPWLEVEL is %s\n",
        !           798:                       ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");
        !           799:        pci_conf_write(pc, tag, DEVCONFIG, devconfig);
        !           800:
        !           801:        /* Make sure current sensing is off. */
        !           802:        if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {
        !           803:                (void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
        !           804:        }
        !           805:
        !           806:        /*
        !           807:         * Read to sense.  Write to set.
        !           808:         */
        !           809:        error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl);
        !           810:        if ((adapter_control & CFAUTOTERM) == 0) {
        !           811:                if (bootverbose)
        !           812:                        printf("%s: Manual Primary Termination\n",
        !           813:                               ahd_name(ahd));
        !           814:                termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH);
        !           815:                if ((adapter_control & CFSTERM) != 0)
        !           816:                        termctl |= FLX_TERMCTL_ENPRILOW;
        !           817:                if ((adapter_control & CFWSTERM) != 0)
        !           818:                        termctl |= FLX_TERMCTL_ENPRIHIGH;
        !           819:        } else if (error != 0) {
        !           820:                printf("%s: Primary Auto-Term Sensing failed! "
        !           821:                       "Using Defaults.\n", ahd_name(ahd));
        !           822:                termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH;
        !           823:        }
        !           824:
        !           825:        if ((adapter_control & CFSEAUTOTERM) == 0) {
        !           826:                if (bootverbose)
        !           827:                        printf("%s: Manual Secondary Termination\n",
        !           828:                               ahd_name(ahd));
        !           829:                termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH);
        !           830:                if ((adapter_control & CFSELOWTERM) != 0)
        !           831:                        termctl |= FLX_TERMCTL_ENSECLOW;
        !           832:                if ((adapter_control & CFSEHIGHTERM) != 0)
        !           833:                        termctl |= FLX_TERMCTL_ENSECHIGH;
        !           834:        } else if (error != 0) {
        !           835:                printf("%s: Secondary Auto-Term Sensing failed! "
        !           836:                       "Using Defaults.\n", ahd_name(ahd));
        !           837:                termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH;
        !           838:        }
        !           839:
        !           840:        /*
        !           841:         * Now set the termination based on what we found.
        !           842:         */
        !           843:        sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
        !           844:        ahd->flags &= ~AHD_TERM_ENB_A;
        !           845:        if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
        !           846:                ahd->flags |= AHD_TERM_ENB_A;
        !           847:                sxfrctl1 |= STPWEN;
        !           848:        }
        !           849:        /* Must set the latch once in order to be effective. */
        !           850:        ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
        !           851:        ahd_outb(ahd, SXFRCTL1, sxfrctl1);
        !           852:
        !           853:        error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl);
        !           854:        if (error != 0) {
        !           855:                printf("%s: Unable to set termination settings!\n",
        !           856:                       ahd_name(ahd));
        !           857:        } else if (bootverbose) {
        !           858:                printf("%s: Primary High byte termination %sabled\n",
        !           859:                       ahd_name(ahd),
        !           860:                       (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis");
        !           861:
        !           862:                printf("%s: Primary Low byte termination %sabled\n",
        !           863:                       ahd_name(ahd),
        !           864:                       (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis");
        !           865:
        !           866:                printf("%s: Secondary High byte termination %sabled\n",
        !           867:                       ahd_name(ahd),
        !           868:                       (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis");
        !           869:
        !           870:                printf("%s: Secondary Low byte termination %sabled\n",
        !           871:                       ahd_name(ahd),
        !           872:                       (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis");
        !           873:        }
        !           874:        return;
        !           875: }
        !           876:
        !           877: #define        DPE     0x80
        !           878: #define SSE    0x40
        !           879: #define        RMA     0x20
        !           880: #define        RTA     0x10
        !           881: #define STA    0x08
        !           882: #define DPR    0x01
        !           883:
        !           884: static const char *split_status_source[] =
        !           885: {
        !           886:        "DFF0",
        !           887:        "DFF1",
        !           888:        "OVLY",
        !           889:        "CMC",
        !           890: };
        !           891:
        !           892: static const char *pci_status_source[] =
        !           893: {
        !           894:        "DFF0",
        !           895:        "DFF1",
        !           896:        "SG",
        !           897:        "CMC",
        !           898:        "OVLY",
        !           899:        "NONE",
        !           900:        "MSI",
        !           901:        "TARG"
        !           902: };
        !           903:
        !           904: static const char *split_status_strings[] =
        !           905: {
        !           906:        "%s: Received split response in %s.\n",
        !           907:        "%s: Received split completion error message in %s\n",
        !           908:        "%s: Receive overrun in %s\n",
        !           909:        "%s: Count not complete in %s\n",
        !           910:        "%s: Split completion data bucket in %s\n",
        !           911:        "%s: Split completion address error in %s\n",
        !           912:        "%s: Split completion byte count error in %s\n",
        !           913:        "%s: Signaled Target-abort to early terminate a split in %s\n"
        !           914: };
        !           915:
        !           916: static const char *pci_status_strings[] =
        !           917: {
        !           918:        "%s: Data Parity Error has been reported via PERR# in %s\n",
        !           919:        "%s: Target initial wait state error in %s\n",
        !           920:        "%s: Split completion read data parity error in %s\n",
        !           921:        "%s: Split completion address attribute parity error in %s\n",
        !           922:        "%s: Received a Target Abort in %s\n",
        !           923:        "%s: Received a Master Abort in %s\n",
        !           924:        "%s: Signal System Error Detected in %s\n",
        !           925:        "%s: Address or Write Phase Parity Error Detected in %s.\n"
        !           926: };
        !           927:
        !           928: void
        !           929: ahd_pci_intr(struct ahd_softc *ahd)
        !           930: {
        !           931:        const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
        !           932:        const pcitag_t tag = ahd->dev_softc->pa_tag;
        !           933:        uint8_t         pci_status[8];
        !           934:        ahd_mode_state  saved_modes;
        !           935:        pcireg_t        pci_status1;
        !           936:        u_int           intstat;
        !           937:        u_int           i;
        !           938:        u_int           reg;
        !           939:
        !           940:        intstat = ahd_inb(ahd, INTSTAT);
        !           941:
        !           942:        if ((intstat & SPLTINT) != 0)
        !           943:                ahd_pci_split_intr(ahd, intstat);
        !           944:
        !           945:        if ((intstat & PCIINT) == 0)
        !           946:                return;
        !           947:
        !           948:        printf("%s: PCI error Interrupt\n", ahd_name(ahd));
        !           949:        saved_modes = ahd_save_modes(ahd);
        !           950:        ahd_dump_card_state(ahd);
        !           951:        ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
        !           952:        for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {
        !           953:
        !           954:                if (i == 5)
        !           955:                        continue;
        !           956:                pci_status[i] = ahd_inb(ahd, reg);
        !           957:                /* Clear latched errors.  So our interrupt deasserts. */
        !           958:                ahd_outb(ahd, reg, pci_status[i]);
        !           959:        }
        !           960:
        !           961:        for (i = 0; i < 8; i++) {
        !           962:                u_int bit;
        !           963:
        !           964:                if (i == 5)
        !           965:                        continue;
        !           966:
        !           967:                for (bit = 0; bit < 8; bit++) {
        !           968:
        !           969:                        if ((pci_status[i] & (0x1 << bit)) != 0) {
        !           970:                                static const char *s;
        !           971:
        !           972:                                s = pci_status_strings[bit];
        !           973:                                if (i == 7/*TARG*/ && bit == 3)
        !           974:                                        s = "%s: Signaled Target Abort\n";
        !           975:                                printf(s, ahd_name(ahd), pci_status_source[i]);
        !           976:                        }
        !           977:                }
        !           978:        }
        !           979:        pci_status1 = pci_conf_read(pc, tag, PCI_COMMAND_STATUS_REG);
        !           980:        pci_conf_write(pc, tag, PCI_COMMAND_STATUS_REG , pci_status1);
        !           981:
        !           982:        ahd_restore_modes(ahd, saved_modes);
        !           983:        ahd_outb(ahd, CLRINT, CLRPCIINT);
        !           984:        ahd_unpause(ahd);
        !           985:
        !           986:        return;
        !           987: }
        !           988:
        !           989: void
        !           990: ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
        !           991: {
        !           992:        const pci_chipset_tag_t pc = ahd->dev_softc->pa_pc;
        !           993:        const pcitag_t tag = ahd->dev_softc->pa_tag;
        !           994:        uint8_t         split_status[4];
        !           995:        uint8_t         split_status1[4];
        !           996:        uint8_t         sg_split_status[2];
        !           997:        uint8_t         sg_split_status1[2];
        !           998:        ahd_mode_state  saved_modes;
        !           999:        u_int           i;
        !          1000:        pcireg_t        pcix_status;
        !          1001:
        !          1002:        /*
        !          1003:         * Check for splits in all modes.  Modes 0 and 1
        !          1004:         * additionally have SG engine splits to look at.
        !          1005:         */
        !          1006:        pcix_status = pci_conf_read(pc, tag, ahd->pcix_off + 0x04);
        !          1007:        printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",
        !          1008:               ahd_name(ahd), pcix_status);
        !          1009:
        !          1010:        saved_modes = ahd_save_modes(ahd);
        !          1011:        for (i = 0; i < 4; i++) {
        !          1012:                ahd_set_modes(ahd, i, i);
        !          1013:
        !          1014:                split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0);
        !          1015:                split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1);
        !          1016:                /* Clear latched errors.  So our interrupt deasserts. */
        !          1017:                ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]);
        !          1018:                ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]);
        !          1019:                if (i > 1)
        !          1020:                        continue;
        !          1021:                sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0);
        !          1022:                sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1);
        !          1023:                /* Clear latched errors.  So our interrupt deasserts. */
        !          1024:                ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]);
        !          1025:                ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]);
        !          1026:        }
        !          1027:
        !          1028:        for (i = 0; i < 4; i++) {
        !          1029:                u_int bit;
        !          1030:
        !          1031:                for (bit = 0; bit < 8; bit++) {
        !          1032:
        !          1033:                        if ((split_status[i] & (0x1 << bit)) != 0) {
        !          1034:                                static const char *s;
        !          1035:
        !          1036:                                s = split_status_strings[bit];
        !          1037:                                printf(s, ahd_name(ahd),
        !          1038:                                       split_status_source[i]);
        !          1039:                        }
        !          1040:
        !          1041:                        if (i > 1)
        !          1042:                                continue;
        !          1043:
        !          1044:                        if ((sg_split_status[i] & (0x1 << bit)) != 0) {
        !          1045:                                static const char *s;
        !          1046:
        !          1047:                                s = split_status_strings[bit];
        !          1048:                                printf(s, ahd_name(ahd), "SG");
        !          1049:                        }
        !          1050:                }
        !          1051:        }
        !          1052:        /*
        !          1053:         * Clear PCI-X status bits.
        !          1054:         */
        !          1055:        pci_conf_write(pc, tag, ahd->pcix_off + 0x04, pcix_status);
        !          1056:        ahd_outb(ahd, CLRINT, CLRSPLTINT);
        !          1057:        ahd_restore_modes(ahd, saved_modes);
        !          1058: }
        !          1059:
        !          1060: int
        !          1061: ahd_aic7901_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
        !          1062: {
        !          1063:
        !          1064:        ahd->chip = AHD_AIC7901;
        !          1065:        ahd->features = AHD_AIC7901_FE;
        !          1066:        return (ahd_aic790X_setup(ahd, pa));
        !          1067: }
        !          1068:
        !          1069: int
        !          1070: ahd_aic7901A_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
        !          1071: {
        !          1072:
        !          1073:        ahd->chip = AHD_AIC7901A;
        !          1074:        ahd->features = AHD_AIC7901A_FE;
        !          1075:        return (ahd_aic790X_setup(ahd, pa));
        !          1076: }
        !          1077:
        !          1078: int
        !          1079: ahd_aic7902_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
        !          1080: {
        !          1081:        ahd->chip = AHD_AIC7902;
        !          1082:        ahd->features = AHD_AIC7902_FE;
        !          1083:        return (ahd_aic790X_setup(ahd, pa));
        !          1084: }
        !          1085:
        !          1086: int
        !          1087: ahd_aic790X_setup(struct ahd_softc *ahd, struct pci_attach_args *pa)
        !          1088: {
        !          1089:        u_int rev;
        !          1090:
        !          1091:        rev = PCI_REVISION(pa->pa_class);
        !          1092: #ifdef AHD_DEBUG
        !          1093:        printf("\n%s: aic7902 chip revision 0x%x\n", ahd_name(ahd), rev);
        !          1094: #endif
        !          1095:        if (rev < ID_AIC7902_PCI_REV_A4) {
        !          1096:                printf("%s: Unable to attach to unsupported chip revision %d\n",
        !          1097:                       ahd_name(ahd), rev);
        !          1098:                pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 0);
        !          1099:                return (ENXIO);
        !          1100:        }
        !          1101:
        !          1102:        ahd->channel = (pa->pa_function == 1) ? 'B' : 'A';
        !          1103:        if (rev < ID_AIC7902_PCI_REV_B0) {
        !          1104:                /*
        !          1105:                 * Enable A series workarounds.
        !          1106:                 */
        !          1107:                ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG
        !          1108:                          |  AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG
        !          1109:                          |  AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG
        !          1110:                          |  AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG
        !          1111:                          |  AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG
        !          1112:                          |  AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG
        !          1113:                          |  AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG
        !          1114:                          |  AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG
        !          1115:                          |  AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG
        !          1116:                          |  AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG
        !          1117:                          |  AHD_FAINT_LED_BUG;
        !          1118:
        !          1119:                /*
        !          1120:                 * IO Cell parameter setup.
        !          1121:                 */
        !          1122:                AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
        !          1123:
        !          1124:                if ((ahd->flags & AHD_HP_BOARD) == 0)
        !          1125:                        AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);
        !          1126:        } else {
        !          1127:                pcireg_t devconfig1;
        !          1128:
        !          1129:                ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
        !          1130:                              |  AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY;
        !          1131:                ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG
        !          1132:                          |  AHD_BUSFREEREV_BUG;
        !          1133:
        !          1134:                /*
        !          1135:                 * Some issues have been resolved in the 7901B.
        !          1136:                 */
        !          1137:                if ((ahd->features & AHD_MULTI_FUNC) != 0)
        !          1138:                        ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG;
        !          1139:
        !          1140:                /*
        !          1141:                 * IO Cell parameter setup.
        !          1142:                 */
        !          1143:                AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
        !          1144:                AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);
        !          1145:                AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);
        !          1146:
        !          1147:                /*
        !          1148:                 * Set the PREQDIS bit for H2B which disables some workaround
        !          1149:                 * that doesn't work on regular PCI busses.
        !          1150:                 * XXX - Find out exactly what this does from the hardware
        !          1151:                 *       folks!
        !          1152:                 */
        !          1153:                devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG1);
        !          1154:                pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG1, devconfig1|PREQDIS);
        !          1155:                devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG1);
        !          1156:        }
        !          1157:
        !          1158:        return (0);
        !          1159: }

CVSweb