The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/aic7xxx_seeprom.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: aic7xxx_seeprom.c,v 1.11 2005/12/11 12:21:25 christos Exp $    */
    2 
    3 /*
    4  * Product specific probe and attach routines for:
    5  *      3940, 2940, aic7895, aic7890, aic7880,
    6  *      aic7870, aic7860 and aic7850 SCSI controllers
    7  *
    8  * Copyright (c) 1994-2001 Justin T. Gibbs.
    9  * Copyright (c) 2000-2001 Adaptec Inc.
   10  * All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions, and the following disclaimer,
   17  *    without modification.
   18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   19  *    substantially similar to the "NO WARRANTY" disclaimer below
   20  *    ("Disclaimer") and any redistribution must be conditioned upon
   21  *    including a substantially similar Disclaimer requirement for further
   22  *    binary redistribution.
   23  * 3. Neither the names of the above-listed copyright holders nor the names
   24  *    of any contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * Alternatively, this software may be distributed under the terms of the
   28  * GNU General Public License ("GPL") version 2 as published by the Free
   29  * Software Foundation.
   30  *
   31  * NO WARRANTY
   32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
   35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
   36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
   41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   42  * POSSIBILITY OF SUCH DAMAGES.
   43  *
   44  * This file was originally split off from the PCI code by
   45  * Jason Thorpe <thorpej@NetBSD.org>. This version was split off
   46  * from the FreeBSD source file aic7xxx_pci.c by Frank van der Linden
   47  * <fvdl@NetBSD.org>
   48  *
   49  * $Id: aic7xxx_seeprom.c,v 1.11 2005/12/11 12:21:25 christos Exp $
   50  *
   51  * $FreeBSD: src/sys/dev/aic7xxx/aic7xxx_pci.c,v 1.22 2003/01/20 20:44:55 gibbs Exp $
   52  */
   53 
   54 #include <sys/cdefs.h>
   55 __KERNEL_RCSID(0, "$NetBSD: aic7xxx_seeprom.c,v 1.11 2005/12/11 12:21:25 christos Exp $");
   56 
   57 #include <sys/param.h>
   58 #include <sys/systm.h>
   59 #include <sys/malloc.h>
   60 #include <sys/kernel.h>
   61 #include <sys/queue.h>
   62 #include <sys/device.h>
   63 #include <sys/reboot.h>         /* for AB_* needed by bootverbose */
   64 
   65 #include <machine/bus.h>
   66 #include <machine/intr.h>
   67 
   68 #include <dev/scsipi/scsi_all.h>
   69 #include <dev/scsipi/scsipi_all.h>
   70 #include <dev/scsipi/scsiconf.h>
   71 
   72 #include <dev/ic/aic7xxx_osm.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;
  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                 ahc_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 }

Cache object: 3da31ed40fa9bc90c1f90c067dc08898


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.