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/pci/aic7870.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 /*
    2  * Product specific probe and attach routines for:
    3  *      3940, 2940, aic7880, aic7870, aic7860 and aic7850 SCSI controllers
    4  *
    5  * Copyright (c) 1995, 1996, 1997 Justin T. Gibbs.
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice immediately at the beginning of the file, without modification,
   13  *    this list of conditions, and the following disclaimer.
   14  * 2. Redistributions in binary form must reproduce the above copyright
   15  *    notice, this list of conditions and the following disclaimer in the
   16  *    documentation and/or other materials provided with the distribution.
   17  * 3. The name of the author may not be used to endorse or promote products
   18  *    derived from this software without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   24  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   30  * SUCH DAMAGE.
   31  *
   32  * $FreeBSD: src/sys/pci/aic7870.c,v 1.41.2.11 1999/09/05 08:20:55 peter Exp $
   33  */
   34 
   35 #if defined(__FreeBSD__)
   36 #include <pci.h>
   37 #endif
   38 #if NPCI > 0 || defined(__NetBSD__)
   39 #include <sys/param.h>
   40 #include <sys/systm.h>
   41 #include <sys/malloc.h>
   42 #include <sys/kernel.h>
   43 #include <sys/queue.h>
   44 #if defined(__NetBSD__)
   45 #include <sys/device.h>
   46 #include <machine/bus.h>
   47 #include <machine/intr.h>
   48 #endif /* defined(__NetBSD__) */
   49 
   50 #include <scsi/scsi_all.h>
   51 #include <scsi/scsiconf.h>
   52 
   53 #if defined(__FreeBSD__)
   54 
   55 #include <pci/pcireg.h>
   56 #include <pci/pcivar.h>
   57 
   58 #include <machine/clock.h>
   59 
   60 #include <i386/scsi/aic7xxx.h>
   61 #include <i386/scsi/93cx6.h>
   62 
   63 #include <aic7xxx_reg.h>
   64 
   65 #define PCI_BASEADR0    PCI_MAP_REG_START       /* I/O Address */
   66 #define PCI_BASEADR1    PCI_MAP_REG_START + 4   /* Mem I/O Address */
   67 
   68 #elif defined(__NetBSD__)
   69 
   70 #include <dev/pci/pcireg.h>
   71 #include <dev/pci/pcivar.h>
   72 
   73 #include <dev/ic/aic7xxxreg.h>
   74 #include <dev/ic/aic7xxxvar.h>
   75 #include <dev/ic/smc93cx6var.h>
   76 
   77 #define bootverbose     1
   78 #define PCI_BASEADR0    PCI_MAPREG_START        /* I/O Address */
   79 #define PCI_BASEADR1    PCI_MAPREG_START + 4    /* Mem I/O Address */
   80 
   81 #endif /* defined(__NetBSD__) */
   82 
   83 #define PCI_DEVICE_ID_ADAPTEC_398XU     0x83789004ul
   84 #define PCI_DEVICE_ID_ADAPTEC_3940U     0x82789004ul
   85 #define PCI_DEVICE_ID_ADAPTEC_2944U     0x84789004ul
   86 #define PCI_DEVICE_ID_ADAPTEC_2940U     0x81789004ul
   87 #define PCI_DEVICE_ID_ADAPTEC_2940AU    0x61789004ul
   88 #define PCI_DEVICE_ID_ADAPTEC_398X      0x73789004ul
   89 #define PCI_DEVICE_ID_ADAPTEC_3940      0x72789004ul
   90 #define PCI_DEVICE_ID_ADAPTEC_2944      0x74789004ul
   91 #define PCI_DEVICE_ID_ADAPTEC_2940      0x71789004ul
   92 #define PCI_DEVICE_ID_ADAPTEC_AIC7880   0x80789004ul
   93 #define PCI_DEVICE_ID_ADAPTEC_AIC7870   0x70789004ul
   94 #define PCI_DEVICE_ID_ADAPTEC_AIC7860   0x60789004ul
   95 #define PCI_DEVICE_ID_ADAPTEC_AIC7855   0x55789004ul
   96 #define PCI_DEVICE_ID_ADAPTEC_AIC7850   0x50789004ul
   97 #define PCI_DEVICE_ID_ADAPTEC_AIC7810   0x10789004ul
   98 
   99 #define DEVCONFIG               0x40
  100 #define         MPORTMODE       0x00000400ul    /* aic7870 only */
  101 #define         RAMPSM          0x00000200ul    /* aic7870 only */
  102 #define         VOLSENSE        0x00000100ul
  103 #define         SCBRAMSEL       0x00000080ul
  104 #define         MRDCEN          0x00000040ul
  105 #define         EXTSCBTIME      0x00000020ul    /* aic7870 only */
  106 #define         EXTSCBPEN       0x00000010ul    /* aic7870 only */
  107 #define         BERREN          0x00000008ul
  108 #define         DACEN           0x00000004ul
  109 #define         STPWLEVEL       0x00000002ul
  110 #define         DIFACTNEGEN     0x00000001ul    /* aic7870 only */
  111 
  112 #define CSIZE_LATTIME           0x0c
  113 #define         CACHESIZE       0x0000003ful    /* only 5 bits */
  114 #define         LATTIME         0x0000ff00ul
  115 
  116 /*
  117  * Define the format of the aic78X0 SEEPROM registers (16 bits).
  118  */
  119 
  120 struct seeprom_config {
  121 
  122 /*
  123  * SCSI ID Configuration Flags
  124  */
  125 #define CFXFER          0x0007          /* synchronous transfer rate */
  126 #define CFSYNCH         0x0008          /* enable synchronous transfer */
  127 #define CFDISC          0x0010          /* enable disconnection */
  128 #define CFWIDEB         0x0020          /* wide bus device */
  129 /* UNUSED               0x00C0 */
  130 #define CFSTART         0x0100          /* send start unit SCSI command */
  131 #define CFINCBIOS       0x0200          /* include in BIOS scan */
  132 #define CFRNFOUND       0x0400          /* report even if not found */
  133 /* UNUSED               0xf800 */
  134   u_int16_t device_flags[16];   /* words 0-15 */
  135 
  136 /*
  137  * BIOS Control Bits
  138  */
  139 #define CFSUPREM        0x0001          /* support all removeable drives */
  140 #define CFSUPREMB       0x0002          /* support removeable drives for boot only */
  141 #define CFBIOSEN        0x0004          /* BIOS enabled */
  142 /* UNUSED               0x0008 */
  143 #define CFSM2DRV        0x0010          /* support more than two drives */
  144 /* UNUSED               0x0060 */
  145 #define CFEXTEND        0x0080          /* extended translation enabled */
  146 /* UNUSED               0xff00 */
  147   u_int16_t bios_control;               /* word 16 */
  148 
  149 /*
  150  * Host Adapter Control Bits
  151  */
  152 #define CFAUTOTERM      0x0001          /* Perform Auto termination */
  153 #define CFULTRAEN       0x0002          /* Ultra SCSI speed enable */
  154 #define CFSTERM         0x0004          /* SCSI low byte termination */
  155 #define CFWSTERM        0x0008          /* SCSI high byte termination */
  156 #define CFSPARITY       0x0010          /* SCSI parity */
  157 /* UNUSED               0x0020 */
  158 #define CFRESETB        0x0040          /* reset SCSI bus at boot */
  159 /* UNUSED               0xff80 */
  160   u_int16_t adapter_control;    /* word 17 */
  161 
  162 /*
  163  * Bus Release, Host Adapter ID
  164  */
  165 #define CFSCSIID        0x000f          /* host adapter SCSI ID */
  166 /* UNUSED               0x00f0 */
  167 #define CFBRTIME        0xff00          /* bus release time */
  168  u_int16_t brtime_id;           /* word 18 */
  169 
  170 /*
  171  * Maximum targets
  172  */
  173 #define CFMAXTARG       0x00ff  /* maximum targets */
  174 /* UNUSED               0xff00 */
  175   u_int16_t max_targets;                /* word 19 */
  176 
  177   u_int16_t res_1[11];          /* words 20-30 */
  178   u_int16_t checksum;           /* word 31 */
  179 };
  180 
  181 static void load_seeprom __P((struct ahc_softc *ahc, u_int8_t *sxfrctl1));
  182 static int acquire_seeprom __P((struct seeprom_descriptor *sd));
  183 static void release_seeprom __P((struct seeprom_descriptor *sd));
  184 static void write_brdctl __P((struct ahc_softc *ahc, u_int8_t value));
  185 static u_int8_t read_brdctl __P((struct ahc_softc *ahc));
  186 
  187 static int aic3940_count;
  188 static int aic398X_count;
  189 static struct ahc_softc *first_398X;
  190 
  191 #if defined(__FreeBSD__)
  192 
  193 static char* aic7870_probe __P((pcici_t tag, pcidi_t type));
  194 static void aic7870_attach __P((pcici_t config_id, int unit));
  195 
  196 static struct  pci_device ahc_pci_driver = {
  197         "ahc",
  198         aic7870_probe,
  199         aic7870_attach,
  200         &ahc_unit,
  201         NULL
  202 };
  203 
  204 DATA_SET (pcidevice_set, ahc_pci_driver);
  205 
  206 static  char*
  207 aic7870_probe (pcici_t tag, pcidi_t type)
  208 {
  209         switch (type) {
  210         case PCI_DEVICE_ID_ADAPTEC_398XU:
  211                 return ("Adaptec 398X Ultra SCSI RAID adapter");
  212                 break;
  213         case PCI_DEVICE_ID_ADAPTEC_3940U:
  214                 return ("Adaptec 3940 Ultra SCSI host adapter");
  215                 break;
  216         case PCI_DEVICE_ID_ADAPTEC_398X:
  217                 return ("Adaptec 398X SCSI RAID adapter");
  218                 break;
  219         case PCI_DEVICE_ID_ADAPTEC_3940:
  220                 return ("Adaptec 3940 SCSI host adapter");
  221                 break;
  222         case PCI_DEVICE_ID_ADAPTEC_2944U:
  223                 return ("Adaptec 2944 Ultra SCSI host adapter");
  224                 break;
  225         case PCI_DEVICE_ID_ADAPTEC_2940U:
  226                 return ("Adaptec 2940 Ultra SCSI host adapter");
  227                 break;
  228         case PCI_DEVICE_ID_ADAPTEC_2944:
  229                 return ("Adaptec 2944 SCSI host adapter");
  230                 break;
  231         case PCI_DEVICE_ID_ADAPTEC_2940:
  232                 return ("Adaptec 2940 SCSI host adapter");
  233                 break;
  234         case PCI_DEVICE_ID_ADAPTEC_2940AU:
  235                 return ("Adaptec 2940A Ultra SCSI host adapter");
  236                 break;
  237         case PCI_DEVICE_ID_ADAPTEC_AIC7880:
  238                 return ("Adaptec aic7880 Ultra SCSI host adapter");
  239                 break;
  240         case PCI_DEVICE_ID_ADAPTEC_AIC7870:
  241                 return ("Adaptec aic7870 SCSI host adapter");
  242                 break;
  243         case PCI_DEVICE_ID_ADAPTEC_AIC7860:
  244                 return ("Adaptec aic7860 SCSI host adapter");
  245                 break;
  246         case PCI_DEVICE_ID_ADAPTEC_AIC7855:
  247                 return ("Adaptec aic7855 SCSI host adapter");
  248                 break;
  249         case PCI_DEVICE_ID_ADAPTEC_AIC7850:
  250                 return ("Adaptec aic7850 SCSI host adapter");
  251                 break;
  252         case PCI_DEVICE_ID_ADAPTEC_AIC7810:
  253                 return ("Adaptec aic7810 RAID memory controller");
  254                 break;
  255         default:
  256                 break;
  257         }
  258         return (0);
  259 
  260 }
  261 
  262 #elif defined(__NetBSD__)
  263 
  264 int ahc_pci_probe __P((struct device *, void *, void *));
  265 void ahc_pci_attach __P((struct device *, struct device *, void *));
  266 
  267 struct cfattach ahc_pci_ca = {
  268         sizeof(struct ahc_softc), ahc_pci_probe, ahc_pci_attach
  269 };
  270 
  271 int
  272 ahc_pci_probe(parent, match, aux)
  273         struct device *parent;
  274         void *match, *aux; 
  275 {       
  276         struct pci_attach_args *pa = aux;
  277 
  278         switch (pa->pa_id) {
  279         case PCI_DEVICE_ID_ADAPTEC_398XU:
  280         case PCI_DEVICE_ID_ADAPTEC_3940U:
  281         case PCI_DEVICE_ID_ADAPTEC_2944U:
  282         case PCI_DEVICE_ID_ADAPTEC_2940U:
  283         case PCI_DEVICE_ID_ADAPTEC_2940AU:
  284         case PCI_DEVICE_ID_ADAPTEC_398X:
  285         case PCI_DEVICE_ID_ADAPTEC_3940:
  286         case PCI_DEVICE_ID_ADAPTEC_2944:
  287         case PCI_DEVICE_ID_ADAPTEC_2940:
  288         case PCI_DEVICE_ID_ADAPTEC_AIC7880:
  289         case PCI_DEVICE_ID_ADAPTEC_AIC7870:
  290         case PCI_DEVICE_ID_ADAPTEC_AIC7860:
  291         case PCI_DEVICE_ID_ADAPTEC_AIC7855:
  292         case PCI_DEVICE_ID_ADAPTEC_AIC7850:
  293         case PCI_DEVICE_ID_ADAPTEC_AIC7810:
  294                 return 1;
  295         }
  296         return 0;
  297 }
  298 #endif /* defined(__NetBSD__) */
  299 
  300 #if defined(__FreeBSD__)
  301 static void
  302 aic7870_attach(config_id, unit)
  303         pcici_t config_id;
  304         int     unit;
  305 #elif defined(__NetBSD__)
  306 void    
  307 ahc_pci_attach(parent, self, aux)
  308         struct device *parent, *self;
  309         void *aux;
  310 #endif
  311 {
  312 #if defined(__FreeBSD__)
  313         u_int16_t io_port;
  314         struct    ahc_softc *ahc;
  315 #elif defined(__NetBSD__)
  316         struct pci_attach_args *pa = aux;
  317         struct ahc_softc *ahc = (void *)self;
  318         int unit = ahc->sc_dev.dv_unit;
  319         bus_io_addr_t iobase;
  320         bus_io_size_t iosize;
  321         bus_io_handle_t ioh;
  322         pci_intr_handle_t ih;
  323         const char *intrstr;
  324 #endif
  325         u_int32_t id;
  326         u_int32_t command;
  327         struct scb_data *shared_scb_data;
  328         int opri;
  329         ahc_type    ahc_t = AHC_NONE;
  330         ahc_flag    ahc_f = AHC_FNONE;
  331         vm_offset_t vaddr;
  332         vm_offset_t paddr;
  333         u_int8_t    ultra_enb = 0;
  334         u_int8_t    our_id = 0;
  335         u_int8_t    sxfrctl1;
  336 
  337         shared_scb_data = NULL;
  338         vaddr = NULL;
  339         paddr = NULL;
  340 #if defined(__FreeBSD__)
  341         io_port = 0;
  342         command = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG);
  343 #ifdef AHC_ALLOW_MEMIO
  344         if ((command & PCI_COMMAND_MEM_ENABLE) == 0
  345          || (pci_map_mem(config_id, PCI_BASEADR1, &vaddr, &paddr)) == 0)
  346 #endif
  347                 if ((command & PCI_COMMAND_IO_ENABLE) == 0
  348                  || (pci_map_port(config_id, PCI_BASEADR0, &io_port)) == 0)
  349                         return;
  350 #elif defined(__NetBSD__)
  351         /* XXX Memory mapped I/O?? */
  352         if (bus_io_map(pa->pa_bc, iobase, iosize, &ioh))
  353                 if (pci_io_find(pa->pa_pc, pa->pa_tag, PCI_BASEADR0, &iobase,
  354                                 &iosize))
  355                         return;
  356 #endif
  357 
  358 #if defined(__FreeBSD__)
  359         switch ((id = pci_conf_read(config_id, PCI_ID_REG))) {
  360 #elif defined(__NetBSD__)
  361         switch (id = pa->pa_id) {
  362 #endif
  363                 case PCI_DEVICE_ID_ADAPTEC_398XU:
  364                 case PCI_DEVICE_ID_ADAPTEC_398X:
  365                         if (id == PCI_DEVICE_ID_ADAPTEC_398XU)
  366                                 ahc_t = AHC_398U;
  367                         else
  368                                 ahc_t = AHC_398;
  369                         switch (aic398X_count) {
  370                         case 0:
  371                                 break;
  372                         case 1:
  373                                 ahc_f |= AHC_CHNLB;
  374                                 break;
  375                         case 2:
  376                                 ahc_f |= AHC_CHNLC;
  377                                 break;
  378                         default:
  379                                 break;
  380                         }
  381                         aic398X_count++; 
  382                         if (first_398X != NULL)
  383 #ifdef AHC_SHARE_SCBS
  384                                 shared_scb_data = first_398X->scb_data;
  385 #endif
  386                         if (aic398X_count == 3) {
  387                                 /*
  388                                  * This is the last device on this RAID
  389                                  * controller, so reset our counts.
  390                                  * XXX This won't work for the multiple 3980
  391                                  * controllers since they have only 2 channels,
  392                                  * but I'm not even sure if Adaptec actually
  393                                  * went through with their plans to produce
  394                                  * this controller.
  395                                  */
  396                                 aic398X_count = 0;
  397                                 first_398X = NULL;
  398                         }
  399                         break;
  400         case PCI_DEVICE_ID_ADAPTEC_3940U:
  401         case PCI_DEVICE_ID_ADAPTEC_3940:
  402                 if (id == PCI_DEVICE_ID_ADAPTEC_3940U)
  403                         ahc_t = AHC_394U;
  404                 else
  405                         ahc_t = AHC_394;
  406                 if ((aic3940_count & 0x01) != 0)
  407                         /* Odd count implies second channel */
  408                         ahc_f |= AHC_CHNLB;
  409                 aic3940_count++;
  410                 break;
  411         case PCI_DEVICE_ID_ADAPTEC_2944U:
  412         case PCI_DEVICE_ID_ADAPTEC_2940U:
  413                 ahc_t = AHC_294U;
  414                 break;
  415         case PCI_DEVICE_ID_ADAPTEC_2944:
  416         case PCI_DEVICE_ID_ADAPTEC_2940:
  417                 ahc_t = AHC_294;
  418                 break;
  419         case PCI_DEVICE_ID_ADAPTEC_2940AU:
  420                 ahc_t = AHC_294AU;
  421                 break;
  422         case PCI_DEVICE_ID_ADAPTEC_AIC7880:
  423                 ahc_t = AHC_AIC7880;
  424                 break;
  425         case PCI_DEVICE_ID_ADAPTEC_AIC7870:
  426                 ahc_t = AHC_AIC7870;
  427                 break;
  428         case PCI_DEVICE_ID_ADAPTEC_AIC7860:
  429                 ahc_t = AHC_AIC7860;
  430                 break;
  431         case PCI_DEVICE_ID_ADAPTEC_AIC7855:
  432         case PCI_DEVICE_ID_ADAPTEC_AIC7850:
  433                 ahc_t = AHC_AIC7850;
  434                 break;
  435         case PCI_DEVICE_ID_ADAPTEC_AIC7810:
  436                 printf("RAID functionality unsupported\n");
  437                 return;
  438         default:
  439                 break;
  440         }
  441 
  442         /* On all PCI adapters, we allow SCB paging */
  443         ahc_f |= AHC_PAGESCBS;
  444 #if defined(__FreeBSD__)
  445         if ((ahc = ahc_alloc(unit, io_port, vaddr, ahc_t, ahc_f,
  446              shared_scb_data)) == NULL)
  447                 return;  /* XXX PCI code should take return status */
  448 #else
  449         ahc_construct(ahc, pa->pa_bc, ioh, ahc_t, ahc_f);
  450 #endif
  451 
  452         /* Remeber how the card was setup in case there is no SEEPROM */
  453         our_id = ahc_inb(ahc, SCSIID) & OID;
  454         if (ahc_t & AHC_ULTRA)
  455                 ultra_enb = ahc_inb(ahc, SXFRCTL0) & FAST20;
  456         sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN;
  457 
  458 #if defined(__NetBSD__)
  459         printf("\n");
  460 #endif
  461         ahc_reset(ahc);
  462 
  463 #ifdef AHC_SHARE_SCBS
  464         if (ahc_t & AHC_AIC7870) {
  465 #if defined(__FreeBSD__)
  466                 u_int32_t devconfig = pci_conf_read(config_id, DEVCONFIG);
  467 #elif defined(__NetBSD__)
  468                 u_int32_t devconfig =
  469                         pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
  470 #endif
  471                 if (devconfig & (RAMPSM)) {
  472                         /* XXX Assume 9bit SRAM and enable parity checking */
  473                         devconfig |= EXTSCBPEN;
  474 
  475                         /* XXX Assume fast SRAM and only enable 2 cycle
  476                          * access if we are sharing the SRAM across mutiple
  477                          * adapters (398X adapter).
  478                          */
  479                         if ((devconfig & MPORTMODE) == 0)
  480                                 /* Multi-user mode */
  481                                 devconfig |= EXTSCBTIME;
  482 
  483                         devconfig &= ~SCBRAMSEL;
  484 #if defined(__FreeBSD__)
  485                         pci_conf_write(config_id, DEVCONFIG, devconfig);
  486 #elif defined(__NetBSD__)
  487                         pci_conf_write(pa->pa_pc, pa->pa_tag,
  488                                        DEVCONFIG, devconfig);
  489 #endif
  490                 }
  491         }
  492 #endif
  493 
  494 #if defined(__FreeBSD__)
  495         if (!(pci_map_int(config_id, ahc_intr, (void *)ahc, &bio_imask))) {
  496                 ahc_free(ahc);
  497                 return;
  498         }
  499 #elif defined(__NetBSD__)
  500 
  501         if (pci_intr_map(pa->pa_pc, pa->pa_intrtag, pa->pa_intrpin,
  502                          pa->pa_intrline, &ih)) {
  503                 printf("%s: couldn't map interrupt\n", ahc->sc_dev.dv_xname);
  504                 ahc_free(ahc);
  505                 return;
  506         }
  507         intrstr = pci_intr_string(pa->pa_pc, ih);
  508 #ifdef __OpenBSD__
  509         ahc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahc_intr, ahc,
  510                                         ahc->sc_dev.dv_xname);
  511 #else
  512         ahc->sc_ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO, ahc_intr, ahc);
  513 #endif
  514         if (ahc->sc_ih == NULL) {
  515                 printf("%s: couldn't establish interrupt",
  516                        ahc->sc_dev.dv_xname);
  517                 if (intrstr != NULL)
  518                         printf(" at %s", intrstr);
  519                 printf("\n");
  520                 ahc_free(ahc);
  521                 return;
  522         }
  523         if (intrstr != NULL)
  524                 printf("%s: interrupting at %s\n", ahc->sc_dev.dv_xname,
  525                        intrstr);
  526 #endif
  527         /*
  528          * Protect ourself from spurrious interrupts during
  529          * intialization.
  530          */
  531         opri = splbio();
  532 
  533         /*
  534          * Do aic7880/aic7870/aic7860/aic7850 specific initialization
  535          */
  536         {
  537                 u_int8_t sblkctl;
  538                 char     *id_string;
  539 
  540                 switch(ahc->type) {
  541                 case AHC_398U:
  542                 case AHC_394U:
  543                 case AHC_294U:
  544                 case AHC_AIC7880:
  545                         id_string = "aic7880 ";
  546                         load_seeprom(ahc, &sxfrctl1);
  547                         break;
  548                 case AHC_398:
  549                 case AHC_394:
  550                 case AHC_294:
  551                 case AHC_AIC7870:
  552                         id_string = "aic7870 ";
  553                         load_seeprom(ahc, &sxfrctl1);
  554                         break;
  555                 case AHC_294AU:
  556                 case AHC_AIC7860:
  557                         id_string = "aic7860 ";
  558                         load_seeprom(ahc, &sxfrctl1);
  559                         break;
  560                 case AHC_AIC7850:
  561                         id_string = "aic7850 ";
  562                         /*
  563                          * Use defaults, if the chip wasn't initialized by
  564                          * a BIOS.
  565                          */
  566                         ahc->flags |= AHC_USEDEFAULTS;
  567                         break;
  568                 default:
  569                         printf("ahc: Unknown controller type.  Ignoring.\n");
  570                         ahc_free(ahc);
  571                         splx(opri);
  572                         return;
  573                 }
  574 
  575                 /*
  576                  * Take the LED out of diagnostic mode
  577                  */
  578                 sblkctl = ahc_inb(ahc, SBLKCTL);
  579                 ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
  580 
  581                 /*
  582                  * I don't know where this is set in the SEEPROM or by the
  583                  * BIOS, so we default to 100%.
  584                  */
  585                 ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);
  586 
  587                 if (ahc->flags & AHC_USEDEFAULTS) {
  588                         /*
  589                          * PCI Adapter default setup
  590                          * Should only be used if the adapter does not have
  591                          * an SEEPROM.
  592                          */
  593                         /* See if someone else set us up already */
  594                         u_int32_t i;
  595                         for (i = TARG_SCRATCH; i < 0x60; i++) {
  596                                 if (ahc_inb(ahc, i) != 0x00)
  597                                         break;
  598                         }
  599                         if (i == TARG_SCRATCH) {
  600                                 /*
  601                                  * Try looking for all ones.  You can get
  602                                  * either.
  603                                  */
  604                                 for (i = TARG_SCRATCH; i < 0x60; i++) {
  605                                         if (ahc_inb(ahc, i) != 0xff)
  606                                                 break;
  607                                 }
  608                         }
  609                         if ((i != 0x60) && (our_id != 0)) {
  610                                 printf("%s: Using left over BIOS settings\n",
  611                                         ahc_name(ahc));
  612                                 ahc->flags &= ~AHC_USEDEFAULTS;
  613                         } else {
  614                                 /*
  615                                  * Assume only one connector and always turn
  616                                  * on termination.
  617                                  */
  618                                 our_id = 0x07;
  619                                 sxfrctl1 = STPWEN;
  620                         }
  621                         ahc_outb(ahc, SCSICONF,
  622                                  (our_id & 0x07)|ENSPCHK|RESET_SCSI);
  623                         /* In case we are a wide card */
  624                         ahc_outb(ahc, SCSICONF + 1, our_id);
  625 
  626                         if (ultra_enb == 0
  627                          && (ahc->flags & AHC_USEDEFAULTS) == 0) {
  628                                 /*
  629                                  * If there wasn't a BIOS or the board
  630                                  * wasn't in this mode to begin with, 
  631                                  * turn off ultra.
  632                                  */
  633                                 ahc->type &= ~AHC_ULTRA;
  634                         }
  635                 }
  636 
  637                 printf("%s: %s", ahc_name(ahc), id_string);
  638         }
  639 
  640         /*
  641          * Put our termination setting into sxfrctl1 now so that the
  642          * generic initialization can see it.
  643          */
  644         sxfrctl1 |= ahc_inb(ahc, SXFRCTL1);
  645         ahc_outb(ahc, SXFRCTL1, sxfrctl1);
  646 
  647         if (ahc_init(ahc)){
  648                 ahc_free(ahc);
  649                 splx(opri);
  650                 return; /* XXX PCI code should take return status */
  651         }
  652 
  653         if ((ahc->type & AHC_398) == AHC_398) {
  654                 /* Only set this once we've successfully probed */
  655                 if (shared_scb_data == NULL)
  656                         first_398X = ahc;
  657         }
  658         splx(opri);
  659 
  660         ahc_attach(ahc);
  661 }
  662 
  663 /*
  664  * Read the SEEPROM.  Return 0 on failure
  665  */
  666 void
  667 load_seeprom(ahc, sxfrctl1)
  668         struct   ahc_softc *ahc;
  669         u_int8_t *sxfrctl1;
  670 {
  671         struct    seeprom_descriptor sd;
  672         struct    seeprom_config sc;
  673         u_int16_t *scarray = (u_int16_t *)&sc;
  674         u_int8_t  scsi_conf;
  675         u_int8_t  host_id;
  676         int       have_seeprom;
  677                  
  678 #if defined(__FreeBSD__)
  679         sd.sd_maddr = ahc->maddr;
  680         if (sd.sd_maddr != NULL)
  681                 sd.sd_maddr += SEECTL;
  682         sd.sd_iobase = ahc->baseport;
  683         if (sd.sd_iobase != 0)
  684                 sd.sd_iobase += SEECTL;
  685 #elif defined(__NetBSD__)
  686         sd.sd_bc = ahc->sc_bc;
  687         sd.sd_ioh = ahc->sc_ioh;
  688         sd.sd_offset = SEECTL;
  689 #endif
  690         /*
  691          * For some multi-channel devices, the c46 is simply too
  692          * small to work.  For the other controller types, we can
  693          * get our information from either SEEPROM type.  Set the
  694          * type to start our probe with accordingly.
  695          */
  696         if ((ahc->type & AHC_398) == AHC_398)
  697                 sd.sd_chip = C56_66;
  698         else
  699                 sd.sd_chip = C46;
  700         sd.sd_MS = SEEMS;
  701         sd.sd_RDY = SEERDY;
  702         sd.sd_CS = SEECS;
  703         sd.sd_CK = SEECK;
  704         sd.sd_DO = SEEDO;
  705         sd.sd_DI = SEEDI;
  706 
  707         have_seeprom = acquire_seeprom(&sd);
  708         if (have_seeprom) {
  709                 if (bootverbose) 
  710                         printf("%s: Reading SEEPROM...", ahc_name(ahc));
  711 
  712                 for (;;) {
  713                         u_int start_addr;
  714 
  715                         start_addr = ahc->flags & (AHC_CHNLB|AHC_CHNLC);
  716 
  717                         have_seeprom = read_seeprom(&sd, (u_int16_t *)&sc,
  718                                                     start_addr, sizeof(sc)/2);
  719 
  720                         if (have_seeprom) {
  721                                 /* Check checksum */
  722                                 int i;
  723                                 int maxaddr;
  724                                 u_int16_t *scarray;
  725                                 u_int16_t checksum;
  726 
  727                                 maxaddr = (sizeof(sc)/2) - 1;
  728                                 checksum = 0;
  729                                 scarray = (u_int16_t *)&sc;
  730 
  731                                 for (i = 0; i < maxaddr; i++)
  732                                         checksum = checksum + scarray[i];
  733                                 if (checksum == 0 || checksum != sc.checksum) {
  734                                         if (bootverbose && sd.sd_chip == C56_66)
  735                                                 printf ("checksum error\n");
  736                                         have_seeprom = 0;
  737                                 } else {
  738                                         if (bootverbose)
  739                                                 printf("done.\n");
  740                                         break;
  741                                 }
  742                         }
  743 
  744                         if (sd.sd_chip == C56_66)
  745                                 break;
  746                         sd.sd_chip = C56_66;
  747                 }
  748         }
  749         release_seeprom(&sd);
  750         if (!have_seeprom) {
  751                 if (bootverbose)
  752                         printf("\n%s: No SEEPROM available\n", ahc_name(ahc));
  753                 ahc->flags |= AHC_USEDEFAULTS;
  754         } else {
  755                 /*
  756                  * Put the data we've collected down into SRAM
  757                  * where ahc_init will find it.
  758                  */
  759                 int i;
  760                 int max_targ = sc.max_targets & CFMAXTARG;
  761 
  762                 for (i = 0; i < max_targ; i++){
  763                         u_char target_settings;
  764                         target_settings = (sc.device_flags[i] & CFXFER) << 4;
  765                         if (sc.device_flags[i] & CFSYNCH)
  766                                 target_settings |= SOFS;
  767                         if (sc.device_flags[i] & CFWIDEB)
  768                                 target_settings |= WIDEXFER;
  769                         if (sc.device_flags[i] & CFDISC)
  770                                 ahc->discenable |= (0x01 << i);
  771                         ahc_outb(ahc, TARG_SCRATCH+i, target_settings);
  772                 }
  773                 ahc_outb(ahc, DISC_DSB, ~(ahc->discenable & 0xff));
  774                 ahc_outb(ahc, DISC_DSB + 1, ~((ahc->discenable >> 8) & 0xff));
  775 
  776                 host_id = sc.brtime_id & CFSCSIID;
  777 
  778                 scsi_conf = (host_id & 0x7);
  779                 if (sc.adapter_control & CFSPARITY)
  780                         scsi_conf |= ENSPCHK;
  781                 if (sc.adapter_control & CFRESETB)
  782                         scsi_conf |= RESET_SCSI;
  783 
  784                 /*
  785                  * Update the settings in sxfrctl1 to match the
  786                  *termination settings
  787                  */
  788                 *sxfrctl1 = 0;
  789                 if (sc.adapter_control & CFAUTOTERM) {
  790                         /* Play around with the memory port */
  791                         have_seeprom = acquire_seeprom(&sd);
  792                         if (have_seeprom) {
  793                                 u_int8_t brdctl;
  794                                 u_int8_t seectl;
  795                                 int      internal50_present;
  796                                 int      internal68_present;
  797                                 int      external68_present;
  798                                 int      eprom_present;
  799                                 int      high_on;
  800                                 int      low_on;
  801 
  802                                 seectl = sd.sd_CS|sd.sd_MS;
  803                                 SEEPROM_OUTB(&sd, seectl);
  804                                 /*
  805                                  * First read the status of our cables.
  806                                  * Set the rom bank to 0 since the
  807                                  * bank setting serves as a multiplexor
  808                                  * for the cable detection logic.
  809                                  * BRDDAT5 controls the bank switch.
  810                                  */
  811                                 write_brdctl(ahc, 0);
  812 
  813                                 /*
  814                                  * Now read the state of the internal
  815                                  * connectors.  BRDDAT6 is INT50 and
  816                                  * BRDDAT7 is INT68.
  817                                  */
  818                                 brdctl = read_brdctl(ahc);
  819                                 internal50_present = !(brdctl & BRDDAT6);
  820                                 internal68_present = !(brdctl & BRDDAT7)
  821                                                    && (max_targ > 8);
  822                                 if (bootverbose) {
  823                                         printf("internal50 cable %s present\n"
  824                                                "internal68 cable %s present\n"
  825                                                "brdctl == 0x%x\n",
  826                                                internal50_present ? "is":"not",
  827                                                internal68_present ? "is":"not",
  828                                                brdctl);
  829                                 }
  830 
  831                                 /*
  832                                  * Set the rom bank to 1 and determine
  833                                  * the other signals.
  834                                  */
  835                                 write_brdctl(ahc, BRDDAT5);
  836 
  837                                 /*
  838                                  * Now read the state of the external
  839                                  * connectors.  BRDDAT6 is EXT68 and
  840                                  * BRDDAT7 is EPROMPS.
  841                                  */
  842                                 brdctl = read_brdctl(ahc);
  843                                 external68_present = !(brdctl & BRDDAT6);
  844                                 eprom_present = brdctl & BRDDAT7;
  845                                 if (bootverbose) {
  846                                         printf("external cable %s present\n"
  847                                                "eprom %s present\n"
  848                                                "brdctl == 0x%x\n",
  849                                                external68_present ? "is":"not",
  850                                                eprom_present ? "is" : "not",
  851                                                brdctl);
  852                                 }
  853 
  854                                 /*
  855                                  * Now set the termination based on what
  856                                  * we found.  BRDDAT6 controls wide
  857                                  * termination enable.
  858                                  */
  859                                 high_on = FALSE;
  860                                 low_on = FALSE;
  861                                 if ((max_targ > 8)
  862                                  && ((external68_present == 0)
  863                                   || (internal68_present == 0)))
  864                                         high_on = TRUE;
  865 
  866                                 if (((internal50_present ? 1 : 0)
  867                                    + (internal68_present ? 1 : 0)
  868                                    + (external68_present ? 1 : 0)) <= 1)
  869                                         low_on = TRUE;
  870                                         
  871                                 if ((internal50_present != 0)
  872                                  && (internal68_present != 0)
  873                                  && (external68_present != 0)) {
  874                                         printf("Illegal cable configuration!!. "
  875                                                "Only two connectors on the "
  876                                                "adapter may be used at a "
  877                                                "time!");
  878                                 }
  879 
  880                                 if (high_on == TRUE)
  881                                         write_brdctl(ahc, BRDDAT6);
  882                                 else
  883                                         write_brdctl(ahc, 0);
  884 
  885                                 if (low_on == TRUE)
  886                                         *sxfrctl1 |= STPWEN;
  887 
  888                                 if (bootverbose) {
  889                                         printf("low byte termination %s, "
  890                                                "high byte termination %s\n",
  891                                                low_on ? "enabled":"disabled",
  892                                                high_on ? "enabled":"disabled");
  893                                 }
  894                         }
  895                         release_seeprom(&sd);
  896                 } else {
  897                         if (sc.adapter_control & CFSTERM)
  898                                 *sxfrctl1 |= STPWEN;
  899                         have_seeprom = acquire_seeprom(&sd);
  900                         if (have_seeprom) {
  901                                 SEEPROM_OUTB(&sd, sd.sd_CS|sd.sd_MS);
  902                                 if (sc.adapter_control & CFWSTERM)
  903                                         write_brdctl(ahc, BRDDAT6);
  904                                 else
  905                                         write_brdctl(ahc, 0);
  906                                 release_seeprom(&sd);
  907                         } else
  908                                 printf("Unabled to configure high byte "
  909                                        "termination!\n");
  910                                 
  911                         if (bootverbose) {
  912                                 printf("low byte termination %s, "
  913                                        "high byte termination %s\n",
  914                                        sc.adapter_control & CFSTERM ?
  915                                                         "enabled":"disabled",
  916                                        sc.adapter_control & CFWSTERM ?
  917                                                         "enabled":"disabled");
  918                         }
  919                 }
  920 
  921                 if (ahc->type & AHC_ULTRA) {
  922                         /* Should we enable Ultra mode? */
  923                         if (!(sc.adapter_control & CFULTRAEN))
  924                                 /* Treat us as a non-ultra card */
  925                                 ahc->type &= ~AHC_ULTRA;
  926                 }
  927                 /* Set the host ID */
  928                 ahc_outb(ahc, SCSICONF, scsi_conf);
  929                 /* In case we are a wide card */
  930                 ahc_outb(ahc, SCSICONF + 1, host_id);
  931         }
  932 }
  933 
  934 static int
  935 acquire_seeprom(sd)
  936         struct seeprom_descriptor *sd;
  937 {
  938         int wait;
  939 
  940         /*
  941          * Request access of the memory port.  When access is
  942          * granted, SEERDY will go high.  We use a 1 second
  943          * timeout which should be near 1 second more than
  944          * is needed.  Reason: after the chip reset, there
  945          * should be no contention.
  946          */
  947         SEEPROM_OUTB(sd, sd->sd_MS);
  948         wait = 1000;  /* 1 second timeout in msec */
  949         while (--wait && ((SEEPROM_INB(sd) & sd->sd_RDY) == 0)) {
  950                 DELAY (1000);  /* delay 1 msec */
  951         }
  952         if ((SEEPROM_INB(sd) & sd->sd_RDY) == 0) {
  953                 SEEPROM_OUTB(sd, 0); 
  954                 return (0);
  955         }         
  956         return(1);
  957 }
  958 
  959 static void
  960 release_seeprom(sd)
  961         struct seeprom_descriptor *sd;
  962 {
  963         /* Release access to the memory port and the serial EEPROM. */
  964         SEEPROM_OUTB(sd, 0);
  965 }
  966 
  967 static void
  968 write_brdctl(ahc, value)
  969         struct  ahc_softc *ahc;
  970         u_int8_t value;
  971 {
  972         u_int8_t brdctl;
  973 
  974         brdctl = BRDCS|BRDSTB;
  975         ahc_outb(ahc, BRDCTL, brdctl);
  976         brdctl |= value;
  977         ahc_outb(ahc, BRDCTL, brdctl);
  978         brdctl &= ~BRDSTB;
  979         ahc_outb(ahc, BRDCTL, brdctl);
  980         brdctl &= ~BRDCS;
  981         ahc_outb(ahc, BRDCTL, brdctl);
  982 }
  983 
  984 static u_int8_t
  985 read_brdctl(ahc)
  986         struct  ahc_softc *ahc;
  987 {
  988         ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
  989         return ahc_inb(ahc, BRDCTL);
  990 }
  991 
  992 #endif /* NPCI > 0 */

Cache object: 9baf0feb84adb84ab0fa0e17c93661c4


[ 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.