[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

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