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

Annotation of sys/dev/ic/aic7xxx_seeprom.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: aic7xxx_seeprom.c,v 1.3 2004/10/24 04:28:33 krw Exp $ */
        !             2: /*     $NetBSD: aic7xxx_seeprom.c,v 1.8 2003/05/02 19:12:19 dyoung Exp $       */
        !             3:
        !             4: /*
        !             5:  * Product specific probe and attach routines for:
        !             6:  *      3940, 2940, aic7895, aic7890, aic7880,
        !             7:  *      aic7870, aic7860 and aic7850 SCSI controllers
        !             8:  *
        !             9:  * Copyright (c) 1994-2001 Justin T. Gibbs.
        !            10:  * Copyright (c) 2000-2001 Adaptec Inc.
        !            11:  * All rights reserved.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions, and the following disclaimer,
        !            18:  *    without modification.
        !            19:  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
        !            20:  *    substantially similar to the "NO WARRANTY" disclaimer below
        !            21:  *    ("Disclaimer") and any redistribution must be conditioned upon
        !            22:  *    including a substantially similar Disclaimer requirement for further
        !            23:  *    binary redistribution.
        !            24:  * 3. Neither the names of the above-listed copyright holders nor the names
        !            25:  *    of any contributors may be used to endorse or promote products derived
        !            26:  *    from this software without specific prior written permission.
        !            27:  *
        !            28:  * Alternatively, this software may be distributed under the terms of the
        !            29:  * GNU General Public License ("GPL") version 2 as published by the Free
        !            30:  * Software Foundation.
        !            31:  *
        !            32:  * NO WARRANTY
        !            33:  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
        !            34:  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
        !            35:  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
        !            36:  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
        !            37:  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            38:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            39:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            40:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
        !            41:  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
        !            42:  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            43:  * POSSIBILITY OF SUCH DAMAGES.
        !            44:  *
        !            45:  * This file was originally split off from the PCI code by
        !            46:  * Jason Thorpe <thorpej@netbsd.org>. This version was split off
        !            47:  * from the FreeBSD source file aic7xxx_pci.c by Frank van der Linden
        !            48:  * <fvdl@netbsd.org>
        !            49:  *
        !            50:  * $Id: aic7xxx_seeprom.c,v 1.3 2004/10/24 04:28:33 krw Exp $
        !            51:  *
        !            52:  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_pci.c,v 1.22 2003/01/20 20:44:55 gibbs Exp $
        !            53:  */
        !            54:
        !            55: #include <sys/cdefs.h>
        !            56: /* __KERNEL_RCSID(0, "$NetBSD: aic7xxx_seeprom.c,v 1.8 2003/05/02 19:12:19 dyoung Exp $"); */
        !            57:
        !            58: #include <sys/param.h>
        !            59: #include <sys/systm.h>
        !            60: #include <sys/malloc.h>
        !            61: #include <sys/kernel.h>
        !            62: #include <sys/queue.h>
        !            63: #include <sys/device.h>
        !            64: #include <sys/reboot.h>                /* for AB_* needed by bootverbose */
        !            65:
        !            66: #include <machine/bus.h>
        !            67: #include <machine/intr.h>
        !            68:
        !            69: #include <scsi/scsi_all.h>
        !            70: #include <scsi/scsiconf.h>
        !            71:
        !            72: #include <dev/ic/aic7xxx_openbsd.h>
        !            73: #include <dev/ic/aic7xxx_inline.h>
        !            74:
        !            75: #include <dev/ic/smc93cx6var.h>
        !            76:
        !            77: #define DEVCONFIG      0x40
        !            78: #define STPWLEVEL      0x00000002
        !            79:
        !            80: static void configure_termination(struct ahc_softc *,
        !            81:                                  struct seeprom_descriptor *, u_int, u_int *);
        !            82: static int verify_seeprom_cksum(struct seeprom_config *sc);
        !            83:
        !            84: static void ahc_new_term_detect(struct ahc_softc *, int *, int *, int *,
        !            85:                                   int *, int *);
        !            86: static void aic787X_cable_detect(struct ahc_softc *, int *, int *, int *,
        !            87:                                 int *);
        !            88: static void aic785X_cable_detect(struct ahc_softc *, int *, int *, int *);
        !            89: static void write_brdctl(struct ahc_softc *, u_int8_t);
        !            90: static u_int8_t read_brdctl(struct ahc_softc *);
        !            91: static void ahc_parse_pci_eeprom(struct ahc_softc *, struct seeprom_config *);
        !            92:
        !            93: /*
        !            94:  * Check the external port logic for a serial eeprom
        !            95:  * and termination/cable detection contrls.
        !            96:  */
        !            97: void
        !            98: ahc_check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
        !            99: {
        !           100:        struct  seeprom_descriptor sd;
        !           101:        struct  seeprom_config *sc;
        !           102:        int     have_seeprom;
        !           103:        int     have_autoterm;
        !           104:
        !           105:        sd.sd_tag = ahc->tag;
        !           106:        sd.sd_bsh = ahc->bsh;
        !           107:        sd.sd_regsize = 1;
        !           108:        sd.sd_control_offset = SEECTL;
        !           109:        sd.sd_status_offset = SEECTL;
        !           110:        sd.sd_dataout_offset = SEECTL;
        !           111:        sc = ahc->seep_config;
        !           112:
        !           113:        /*
        !           114:         * For some multi-channel devices, the c46 is simply too
        !           115:         * small to work.  For the other controller types, we can
        !           116:         * get our information from either SEEPROM type.  Set the
        !           117:         * type to start our probe with accordingly.
        !           118:         */
        !           119:        if (ahc->flags & AHC_LARGE_SEEPROM)
        !           120:                sd.sd_chip = C56_66;
        !           121:        else
        !           122:                sd.sd_chip = C46;
        !           123:
        !           124:        sd.sd_MS = SEEMS;
        !           125:        sd.sd_RDY = SEERDY;
        !           126:        sd.sd_CS = SEECS;
        !           127:        sd.sd_CK = SEECK;
        !           128:        sd.sd_DO = SEEDO;
        !           129:        sd.sd_DI = SEEDI;
        !           130:
        !           131:        have_seeprom = ahc_acquire_seeprom(ahc, &sd);
        !           132:        if (have_seeprom) {
        !           133:
        !           134:                if (bootverbose)
        !           135:                        printf("%s: Reading SEEPROM...", ahc_name(ahc));
        !           136:
        !           137:                for (;;) {
        !           138:                        u_int start_addr;
        !           139:
        !           140:                        start_addr = 32 * (ahc->channel - 'A');
        !           141:                        have_seeprom = read_seeprom(&sd, (uint16_t *)sc,
        !           142:                                                        start_addr,
        !           143:                                                        sizeof(*sc)/2);
        !           144:
        !           145:                        if (have_seeprom)
        !           146:                                have_seeprom = verify_seeprom_cksum(sc);
        !           147:
        !           148:                        if (have_seeprom != 0 || sd.sd_chip == C56_66) {
        !           149:                                if (bootverbose) {
        !           150:                                        if (have_seeprom == 0)
        !           151:                                                printf ("checksum error\n");
        !           152:                                        else
        !           153:                                                printf ("done.\n");
        !           154:                                }
        !           155:                                break;
        !           156:                        }
        !           157:                        sd.sd_chip = C56_66;
        !           158:                }
        !           159:                ahc_release_seeprom(&sd);
        !           160:        }
        !           161:
        !           162:        if (!have_seeprom) {
        !           163:                /*
        !           164:                 * Pull scratch ram settings and treat them as
        !           165:                 * if they are the contents of an seeprom if
        !           166:                 * the 'ADPT' signature is found in SCB2.
        !           167:                 * We manually compose the data as 16bit values
        !           168:                 * to avoid endian issues.
        !           169:                 */
        !           170:                ahc_outb(ahc, SCBPTR, 2);
        !           171:                if (ahc_inb(ahc, SCB_BASE) == 'A'
        !           172:                 && ahc_inb(ahc, SCB_BASE + 1) == 'D'
        !           173:                 && ahc_inb(ahc, SCB_BASE + 2) == 'P'
        !           174:                 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
        !           175:                        uint16_t *sc_data;
        !           176:                        int       i;
        !           177:
        !           178:                        sc_data = (uint16_t *)sc;
        !           179:                        for (i = 0; i < 32; i++, sc_data++) {
        !           180:                                int     j;
        !           181:
        !           182:                                j = i * 2;
        !           183:                                *sc_data = ahc_inb(ahc, SRAM_BASE + j)
        !           184:                                         | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
        !           185:                        }
        !           186:                        have_seeprom = verify_seeprom_cksum(sc);
        !           187:                        if (have_seeprom)
        !           188:                                ahc->flags |= AHC_SCB_CONFIG_USED;
        !           189:                }
        !           190:                /*
        !           191:                 * Clear any SCB parity errors in case this data and
        !           192:                 * its associated parity was not initialized by the BIOS
        !           193:                 */
        !           194:                ahc_outb(ahc, CLRINT, CLRPARERR);
        !           195:                ahc_outb(ahc, CLRINT, CLRBRKADRINT);
        !           196:        }
        !           197:
        !           198:        if (!have_seeprom) {
        !           199:                if (bootverbose)
        !           200:                        printf("%s: No SEEPROM available.\n", ahc_name(ahc));
        !           201:                ahc->flags |= AHC_USEDEFAULTS | AHC_NO_BIOS_INIT;
        !           202:                free(ahc->seep_config, M_DEVBUF);
        !           203:                ahc->seep_config = NULL;
        !           204:                sc = NULL;
        !           205:        } else {
        !           206:                ahc_parse_pci_eeprom(ahc, sc);
        !           207:        }
        !           208:
        !           209:        /*
        !           210:         * Cards that have the external logic necessary to talk to
        !           211:         * a SEEPROM, are almost certain to have the remaining logic
        !           212:         * necessary for auto-termination control.  This assumption
        !           213:         * hasn't failed yet...
        !           214:         */
        !           215:        have_autoterm = have_seeprom;
        !           216:
        !           217:        /*
        !           218:         * Some low-cost chips have SEEPROM and auto-term control built
        !           219:         * in, instead of using a GAL.  They can tell us directly
        !           220:         * if the termination logic is enabled.
        !           221:         */
        !           222:        if ((ahc->features & AHC_SPIOCAP) != 0) {
        !           223:                if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)
        !           224:                        have_autoterm = FALSE;
        !           225:        }
        !           226:
        !           227:        if (have_autoterm) {
        !           228:                ahc_acquire_seeprom(ahc, &sd);
        !           229:                configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
        !           230:                ahc_release_seeprom(&sd);
        !           231:        } else if (have_seeprom) {
        !           232:                *sxfrctl1 &= ~STPWEN;
        !           233:                if ((sc->adapter_control & CFSTERM) != 0)
        !           234:                        *sxfrctl1 |= STPWEN;
        !           235:                if (bootverbose)
        !           236:                        printf("%s: Low byte termination %sabled\n",
        !           237:                               ahc_name(ahc),
        !           238:                               (*sxfrctl1 & STPWEN) ? "en" : "dis");
        !           239:        }
        !           240: }
        !           241:
        !           242: static void
        !           243: ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
        !           244: {
        !           245:        /*
        !           246:         * Put the data we've collected down into SRAM
        !           247:         * where ahc_init will find it.
        !           248:         */
        !           249:        int      i;
        !           250:        int      max_targ = sc->max_targets & CFMAXTARG;
        !           251:        u_int    scsi_conf;
        !           252:        uint16_t discenable;
        !           253:        uint16_t ultraenb;
        !           254:
        !           255:        discenable = 0;
        !           256:        ultraenb = 0;
        !           257:        if ((sc->adapter_control & CFULTRAEN) != 0) {
        !           258:                /*
        !           259:                 * Determine if this adapter has a "newstyle"
        !           260:                 * SEEPROM format.
        !           261:                 */
        !           262:                for (i = 0; i < max_targ; i++) {
        !           263:                        if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
        !           264:                                ahc->flags |= AHC_NEWEEPROM_FMT;
        !           265:                                break;
        !           266:                        }
        !           267:                }
        !           268:        }
        !           269:
        !           270:        for (i = 0; i < max_targ; i++) {
        !           271:                u_int     scsirate;
        !           272:                uint16_t target_mask;
        !           273:
        !           274:                target_mask = 0x01 << i;
        !           275:                if (sc->device_flags[i] & CFDISC)
        !           276:                        discenable |= target_mask;
        !           277:                if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
        !           278:                        if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0)
        !           279:                                ultraenb |= target_mask;
        !           280:                } else if ((sc->adapter_control & CFULTRAEN) != 0) {
        !           281:                        ultraenb |= target_mask;
        !           282:                }
        !           283:                if ((sc->device_flags[i] & CFXFER) == 0x04
        !           284:                    && (ultraenb & target_mask) != 0) {
        !           285:                        /* Treat 10MHz as a non-ultra speed */
        !           286:                        sc->device_flags[i] &= ~CFXFER;
        !           287:                        ultraenb &= ~target_mask;
        !           288:                }
        !           289:                if ((ahc->features & AHC_ULTRA2) != 0) {
        !           290:                        u_int offset;
        !           291:
        !           292:                        if (sc->device_flags[i] & CFSYNCH)
        !           293:                                offset = MAX_OFFSET_ULTRA2;
        !           294:                        else
        !           295:                                offset = 0;
        !           296:                        ahc_outb(ahc, TARG_OFFSET + i, offset);
        !           297:
        !           298:                        /*
        !           299:                         * The ultra enable bits contain the
        !           300:                         * high bit of the ultra2 sync rate
        !           301:                         * field.
        !           302:                         */
        !           303:                        scsirate = (sc->device_flags[i] & CFXFER)
        !           304:                                 | ((ultraenb & target_mask) ? 0x8 : 0x0);
        !           305:                        if (sc->device_flags[i] & CFWIDEB)
        !           306:                                scsirate |= WIDEXFER;
        !           307:                } else {
        !           308:                        scsirate = (sc->device_flags[i] & CFXFER) << 4;
        !           309:                        if (sc->device_flags[i] & CFSYNCH)
        !           310:                                scsirate |= SOFS;
        !           311:                        if (sc->device_flags[i] & CFWIDEB)
        !           312:                                scsirate |= WIDEXFER;
        !           313:                }
        !           314:                ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
        !           315:        }
        !           316:        ahc->our_id = sc->brtime_id & CFSCSIID;
        !           317:
        !           318:        scsi_conf = (ahc->our_id & 0x7);
        !           319:        if (sc->adapter_control & CFSPARITY)
        !           320:                scsi_conf |= ENSPCHK;
        !           321:        if (sc->adapter_control & CFRESETB)
        !           322:                scsi_conf |= RESET_SCSI;
        !           323:
        !           324:        ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
        !           325:
        !           326:        if (sc->bios_control & CFEXTEND)
        !           327:                ahc->flags |= AHC_EXTENDED_TRANS_A;
        !           328:
        !           329:        if (sc->bios_control & CFBIOSEN)
        !           330:                ahc->flags |= AHC_BIOS_ENABLED;
        !           331:        if (ahc->features & AHC_ULTRA
        !           332:            && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
        !           333:                /* Should we enable Ultra mode? */
        !           334:                if (!(sc->adapter_control & CFULTRAEN))
        !           335:                        /* Treat us as a non-ultra card */
        !           336:                        ultraenb = 0;
        !           337:        }
        !           338:
        !           339:        if (sc->signature == CFSIGNATURE
        !           340:            || sc->signature == CFSIGNATURE2) {
        !           341:                uint32_t devconfig;
        !           342:
        !           343:                /* Honor the STPWLEVEL settings */
        !           344:                devconfig = pci_conf_read(ahc->bd->pc, ahc->bd->tag, DEVCONFIG);
        !           345:                devconfig &= ~STPWLEVEL;
        !           346:                if ((sc->bios_control & CFSTPWLEVEL) != 0)
        !           347:                        devconfig |= STPWLEVEL;
        !           348:                pci_conf_write(ahc->bd->pc, ahc->bd->tag, DEVCONFIG,  devconfig);
        !           349:        }
        !           350:        /* Set SCSICONF info */
        !           351:        ahc_outb(ahc, SCSICONF, scsi_conf);
        !           352:        ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
        !           353:        ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
        !           354:        ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
        !           355:        ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
        !           356: }
        !           357:
        !           358: static void
        !           359: configure_termination(struct ahc_softc *ahc,
        !           360:                      struct seeprom_descriptor *sd,
        !           361:                      u_int adapter_control,
        !           362:                      u_int *sxfrctl1)
        !           363: {
        !           364:        uint8_t brddat;
        !           365:
        !           366:        brddat = 0;
        !           367:
        !           368:        /*
        !           369:         * Update the settings in sxfrctl1 to match the
        !           370:         * termination settings
        !           371:         */
        !           372:        *sxfrctl1 = 0;
        !           373:
        !           374:        /*
        !           375:         * SEECS must be on for the GALS to latch
        !           376:         * the data properly.  Be sure to leave MS
        !           377:         * on or we will release the seeprom.
        !           378:         */
        !           379:        SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
        !           380:        if ((adapter_control & CFAUTOTERM) != 0
        !           381:         || (ahc->features & AHC_NEW_TERMCTL) != 0) {
        !           382:                int internal50_present;
        !           383:                int internal68_present;
        !           384:                int externalcable_present;
        !           385:                int eeprom_present;
        !           386:                int enableSEC_low;
        !           387:                int enableSEC_high;
        !           388:                int enablePRI_low;
        !           389:                int enablePRI_high;
        !           390:                int sum;
        !           391:
        !           392:                enableSEC_low = 0;
        !           393:                enableSEC_high = 0;
        !           394:                enablePRI_low = 0;
        !           395:                enablePRI_high = 0;
        !           396:                if ((ahc->features & AHC_NEW_TERMCTL) != 0) {
        !           397:                        ahc_new_term_detect(ahc, &enableSEC_low,
        !           398:                                            &enableSEC_high,
        !           399:                                            &enablePRI_low,
        !           400:                                            &enablePRI_high,
        !           401:                                            &eeprom_present);
        !           402:                        if ((adapter_control & CFSEAUTOTERM) == 0) {
        !           403:                                if (bootverbose)
        !           404:                                        printf("%s: Manual SE Termination\n",
        !           405:                                               ahc_name(ahc));
        !           406:                                enableSEC_low = (adapter_control & CFSELOWTERM);
        !           407:                                enableSEC_high =
        !           408:                                    (adapter_control & CFSEHIGHTERM);
        !           409:                        }
        !           410:                        if ((adapter_control & CFAUTOTERM) == 0) {
        !           411:                                if (bootverbose)
        !           412:                                        printf("%s: Manual LVD Termination\n",
        !           413:                                               ahc_name(ahc));
        !           414:                                enablePRI_low = (adapter_control & CFSTERM);
        !           415:                                enablePRI_high = (adapter_control & CFWSTERM);
        !           416:                        }
        !           417:                        /* Make the table calculations below happy */
        !           418:                        internal50_present = 0;
        !           419:                        internal68_present = 1;
        !           420:                        externalcable_present = 1;
        !           421:                } else if ((ahc->features & AHC_SPIOCAP) != 0) {
        !           422:                        aic785X_cable_detect(ahc, &internal50_present,
        !           423:                                             &externalcable_present,
        !           424:                                             &eeprom_present);
        !           425:                        /* Can never support a wide connector. */
        !           426:                        internal68_present = 0;
        !           427:                } else {
        !           428:                        aic787X_cable_detect(ahc, &internal50_present,
        !           429:                                             &internal68_present,
        !           430:                                             &externalcable_present,
        !           431:                                             &eeprom_present);
        !           432:                }
        !           433:
        !           434:                if ((ahc->features & AHC_WIDE) == 0)
        !           435:                        internal68_present = 0;
        !           436:
        !           437:                if (bootverbose
        !           438:                 && (ahc->features & AHC_ULTRA2) == 0) {
        !           439:                        printf("%s: internal 50 cable %s present",
        !           440:                               ahc_name(ahc),
        !           441:                               internal50_present ? "is":"not");
        !           442:
        !           443:                        if ((ahc->features & AHC_WIDE) != 0)
        !           444:                                printf(", internal 68 cable %s present",
        !           445:                                       internal68_present ? "is":"not");
        !           446:                        printf("\n%s: external cable %s present\n",
        !           447:                               ahc_name(ahc),
        !           448:                               externalcable_present ? "is":"not");
        !           449:                }
        !           450:                if (bootverbose)
        !           451:                        printf("%s: BIOS eeprom %s present\n",
        !           452:                               ahc_name(ahc), eeprom_present ? "is" : "not");
        !           453:
        !           454:                if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
        !           455:                        /*
        !           456:                         * The 50 pin connector is a separate bus,
        !           457:                         * so force it to always be terminated.
        !           458:                         * In the future, perform current sensing
        !           459:                         * to determine if we are in the middle of
        !           460:                         * a properly terminated bus.
        !           461:                         */
        !           462:                        internal50_present = 0;
        !           463:                }
        !           464:
        !           465:                /*
        !           466:                 * Now set the termination based on what
        !           467:                 * we found.
        !           468:                 * Flash Enable = BRDDAT7
        !           469:                 * Secondary High Term Enable = BRDDAT6
        !           470:                 * Secondary Low Term Enable = BRDDAT5 (7890)
        !           471:                 * Primary High Term Enable = BRDDAT4 (7890)
        !           472:                 */
        !           473:                if ((ahc->features & AHC_ULTRA2) == 0
        !           474:                 && (internal50_present != 0)
        !           475:                 && (internal68_present != 0)
        !           476:                 && (externalcable_present != 0)) {
        !           477:                        printf("%s: Illegal cable configuration!!. "
        !           478:                               "Only two connectors on the "
        !           479:                               "adapter may be used at a "
        !           480:                               "time!\n", ahc_name(ahc));
        !           481:
        !           482:                        /*
        !           483:                         * Pretend there are no cables in the hope
        !           484:                         * that having all of the termination on
        !           485:                         * gives us a more stable bus.
        !           486:                         */
        !           487:                        internal50_present = 0;
        !           488:                        internal68_present = 0;
        !           489:                        externalcable_present = 0;
        !           490:                }
        !           491:
        !           492:                if ((ahc->features & AHC_WIDE) != 0
        !           493:                 && ((externalcable_present == 0)
        !           494:                  || (internal68_present == 0)
        !           495:                  || (enableSEC_high != 0))) {
        !           496:                        brddat |= BRDDAT6;
        !           497:                        if (bootverbose) {
        !           498:                                if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
        !           499:                                        printf("%s: 68 pin termination "
        !           500:                                               "Enabled\n", ahc_name(ahc));
        !           501:                                else
        !           502:                                        printf("%s: %sHigh byte termination "
        !           503:                                               "Enabled\n", ahc_name(ahc),
        !           504:                                               enableSEC_high ? "Secondary "
        !           505:                                                              : "");
        !           506:                        }
        !           507:                }
        !           508:
        !           509:                sum = internal50_present + internal68_present
        !           510:                    + externalcable_present;
        !           511:                if (sum < 2 || (enableSEC_low != 0)) {
        !           512:                        if ((ahc->features & AHC_ULTRA2) != 0)
        !           513:                                brddat |= BRDDAT5;
        !           514:                        else
        !           515:                                *sxfrctl1 |= STPWEN;
        !           516:                        if (bootverbose) {
        !           517:                                if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
        !           518:                                        printf("%s: 50 pin termination "
        !           519:                                               "Enabled\n", ahc_name(ahc));
        !           520:                                else
        !           521:                                        printf("%s: %sLow byte termination "
        !           522:                                               "Enabled\n", ahc_name(ahc),
        !           523:                                               enableSEC_low ? "Secondary "
        !           524:                                                             : "");
        !           525:                        }
        !           526:                }
        !           527:
        !           528:                if (enablePRI_low != 0) {
        !           529:                        *sxfrctl1 |= STPWEN;
        !           530:                        if (bootverbose)
        !           531:                                printf("%s: Primary Low Byte termination "
        !           532:                                       "Enabled\n", ahc_name(ahc));
        !           533:                }
        !           534:
        !           535:                /*
        !           536:                 * Setup STPWEN before setting up the rest of
        !           537:                 * the termination per the tech note on the U160 cards.
        !           538:                 */
        !           539:                ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
        !           540:
        !           541:                if (enablePRI_high != 0) {
        !           542:                        brddat |= BRDDAT4;
        !           543:                        if (bootverbose)
        !           544:                                printf("%s: Primary High Byte "
        !           545:                                       "termination Enabled\n",
        !           546:                                       ahc_name(ahc));
        !           547:                }
        !           548:
        !           549:                write_brdctl(ahc, brddat);
        !           550:
        !           551:        } else {
        !           552:                if ((adapter_control & CFSTERM) != 0) {
        !           553:                        *sxfrctl1 |= STPWEN;
        !           554:
        !           555:                        if (bootverbose)
        !           556:                                printf("%s: %sLow byte termination Enabled\n",
        !           557:                                       ahc_name(ahc),
        !           558:                                       (ahc->features & AHC_ULTRA2) ? "Primary "
        !           559:                                                                    : "");
        !           560:                }
        !           561:
        !           562:                if ((adapter_control & CFWSTERM) != 0
        !           563:                 && (ahc->features & AHC_WIDE) != 0) {
        !           564:                        brddat |= BRDDAT6;
        !           565:                        if (bootverbose)
        !           566:                                printf("%s: %sHigh byte termination Enabled\n",
        !           567:                                       ahc_name(ahc),
        !           568:                                       (ahc->features & AHC_ULTRA2)
        !           569:                                     ? "Secondary " : "");
        !           570:                }
        !           571:
        !           572:                /*
        !           573:                 * Setup STPWEN before setting up the rest of
        !           574:                 * the termination per the tech note on the U160 cards.
        !           575:                 */
        !           576:                ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
        !           577:
        !           578:                if ((ahc->features & AHC_WIDE) != 0)
        !           579:                        write_brdctl(ahc, brddat);
        !           580:        }
        !           581:        SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */
        !           582: }
        !           583:
        !           584: static void
        !           585: ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low,
        !           586:                    int *enableSEC_high, int *enablePRI_low,
        !           587:                    int *enablePRI_high, int *eeprom_present)
        !           588: {
        !           589:        uint8_t brdctl;
        !           590:
        !           591:        /*
        !           592:         * BRDDAT7 = Eeprom
        !           593:         * BRDDAT6 = Enable Secondary High Byte termination
        !           594:         * BRDDAT5 = Enable Secondary Low Byte termination
        !           595:         * BRDDAT4 = Enable Primary high byte termination
        !           596:         * BRDDAT3 = Enable Primary low byte termination
        !           597:         */
        !           598:        brdctl = read_brdctl(ahc);
        !           599:        *eeprom_present = brdctl & BRDDAT7;
        !           600:        *enableSEC_high = (brdctl & BRDDAT6);
        !           601:        *enableSEC_low = (brdctl & BRDDAT5);
        !           602:        *enablePRI_high = (brdctl & BRDDAT4);
        !           603:        *enablePRI_low = (brdctl & BRDDAT3);
        !           604: }
        !           605:
        !           606: static void
        !           607: aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
        !           608:                     int *internal68_present, int *externalcable_present,
        !           609:                     int *eeprom_present)
        !           610: {
        !           611:        uint8_t brdctl;
        !           612:
        !           613:        /*
        !           614:         * First read the status of our cables.
        !           615:         * Set the rom bank to 0 since the
        !           616:         * bank setting serves as a multiplexor
        !           617:         * for the cable detection logic.
        !           618:         * BRDDAT5 controls the bank switch.
        !           619:         */
        !           620:        write_brdctl(ahc, 0);
        !           621:
        !           622:        /*
        !           623:         * Now read the state of the internal
        !           624:         * connectors.  BRDDAT6 is INT50 and
        !           625:         * BRDDAT7 is INT68.
        !           626:         */
        !           627:        brdctl = read_brdctl(ahc);
        !           628:        *internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
        !           629:        *internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
        !           630:
        !           631:        /*
        !           632:         * Set the rom bank to 1 and determine
        !           633:         * the other signals.
        !           634:         */
        !           635:        write_brdctl(ahc, BRDDAT5);
        !           636:
        !           637:        /*
        !           638:         * Now read the state of the external
        !           639:         * connectors.  BRDDAT6 is EXT68 and
        !           640:         * BRDDAT7 is EPROMPS.
        !           641:         */
        !           642:        brdctl = read_brdctl(ahc);
        !           643:        *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
        !           644:        *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
        !           645: }
        !           646:
        !           647: static void
        !           648: aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
        !           649:                     int *externalcable_present, int *eeprom_present)
        !           650: {
        !           651:        uint8_t brdctl;
        !           652:        uint8_t spiocap;
        !           653:
        !           654:        spiocap = ahc_inb(ahc, SPIOCAP);
        !           655:        spiocap &= ~SOFTCMDEN;
        !           656:        spiocap |= EXT_BRDCTL;
        !           657:        ahc_outb(ahc, SPIOCAP, spiocap);
        !           658:        ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
        !           659:        ahc_outb(ahc, BRDCTL, 0);
        !           660:        brdctl = ahc_inb(ahc, BRDCTL);
        !           661:        *internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
        !           662:        *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
        !           663:
        !           664:        *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
        !           665: }
        !           666:
        !           667: int
        !           668: ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
        !           669: {
        !           670:        int wait;
        !           671:
        !           672:        if ((ahc->features & AHC_SPIOCAP) != 0
        !           673:            && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
        !           674:                return (0);
        !           675:
        !           676:        /*
        !           677:         * Request access of the memory port.  When access is
        !           678:         * granted, SEERDY will go high.  We use a 1 second
        !           679:         * timeout which should be near 1 second more than
        !           680:         * is needed.  Reason: after the chip reset, there
        !           681:         * should be no contention.
        !           682:         */
        !           683:        SEEPROM_OUTB(sd, sd->sd_MS);
        !           684:        wait = 1000;  /* 1 second timeout in msec */
        !           685:        while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
        !           686:                aic_delay(1000);  /* delay 1 msec */
        !           687:        }
        !           688:        if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
        !           689:                SEEPROM_OUTB(sd, 0);
        !           690:                return (0);
        !           691:        }
        !           692:        return(1);
        !           693: }
        !           694:
        !           695: void
        !           696: ahc_release_seeprom(struct seeprom_descriptor *sd)
        !           697: {
        !           698:        /* Release access to the memory port and the serial EEPROM. */
        !           699:        SEEPROM_OUTB(sd, 0);
        !           700: }
        !           701:
        !           702: static void
        !           703: write_brdctl(struct ahc_softc *ahc, uint8_t value)
        !           704: {
        !           705:        uint8_t brdctl;
        !           706:
        !           707:        if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
        !           708:                brdctl = BRDSTB;
        !           709:                if (ahc->channel == 'B')
        !           710:                        brdctl |= BRDCS;
        !           711:        } else if ((ahc->features & AHC_ULTRA2) != 0) {
        !           712:                brdctl = 0;
        !           713:        } else {
        !           714:                brdctl = BRDSTB|BRDCS;
        !           715:        }
        !           716:        ahc_outb(ahc, BRDCTL, brdctl);
        !           717:        ahc_flush_device_writes(ahc);
        !           718:        brdctl |= value;
        !           719:        ahc_outb(ahc, BRDCTL, brdctl);
        !           720:        ahc_flush_device_writes(ahc);
        !           721:        if ((ahc->features & AHC_ULTRA2) != 0)
        !           722:                brdctl |= BRDSTB_ULTRA2;
        !           723:        else
        !           724:                brdctl &= ~BRDSTB;
        !           725:        ahc_outb(ahc, BRDCTL, brdctl);
        !           726:        ahc_flush_device_writes(ahc);
        !           727:        if ((ahc->features & AHC_ULTRA2) != 0)
        !           728:                brdctl = 0;
        !           729:        else
        !           730:                brdctl &= ~BRDCS;
        !           731:        ahc_outb(ahc, BRDCTL, brdctl);
        !           732: }
        !           733:
        !           734: static uint8_t
        !           735: read_brdctl(ahc)
        !           736:        struct  ahc_softc *ahc;
        !           737: {
        !           738:        uint8_t brdctl;
        !           739:        uint8_t value;
        !           740:
        !           741:        if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
        !           742:                brdctl = BRDRW;
        !           743:                if (ahc->channel == 'B')
        !           744:                        brdctl |= BRDCS;
        !           745:        } else if ((ahc->features & AHC_ULTRA2) != 0) {
        !           746:                brdctl = BRDRW_ULTRA2;
        !           747:        } else {
        !           748:                brdctl = BRDRW|BRDCS;
        !           749:        }
        !           750:        ahc_outb(ahc, BRDCTL, brdctl);
        !           751:        ahc_flush_device_writes(ahc);
        !           752:        value = ahc_inb(ahc, BRDCTL);
        !           753:        ahc_outb(ahc, BRDCTL, 0);
        !           754:        return (value);
        !           755: }
        !           756:
        !           757: static int
        !           758: verify_seeprom_cksum(struct seeprom_config *sc)
        !           759: {
        !           760:        int i;
        !           761:        int maxaddr;
        !           762:        uint32_t checksum;
        !           763:        uint16_t *scarray;
        !           764:
        !           765:        maxaddr = (sizeof(*sc)/2) - 1;
        !           766:        checksum = 0;
        !           767:        scarray = (uint16_t *)sc;
        !           768:
        !           769:        for (i = 0; i < maxaddr; i++)
        !           770:                checksum = checksum + scarray[i];
        !           771:        if (checksum == 0
        !           772:         || (checksum & 0xFFFF) != sc->checksum) {
        !           773:                return (0);
        !           774:        } else {
        !           775:                return(1);
        !           776:        }
        !           777: }

CVSweb