LCOV - code coverage report
Current view: top level - dev/ic - aic7xxx_seeprom.c (source / functions) Hit Total Coverage
Test: 6.4 Lines: 0 302 0.0 %
Date: 2018-10-19 03:25:38 Functions: 0 11 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13