root/dev/eisa/ahc_eisa.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ahc_eisa_irq
  2. ahc_eisa_match
  3. ahc_eisa_attach

    1 /*      $OpenBSD: ahc_eisa.c,v 1.18 2007/04/10 17:47:55 miod Exp $      */
    2 /*      $NetBSD: ahc_eisa.c,v 1.10 1996/10/21 22:30:58 thorpej Exp $    */
    3 
    4 /*
    5  * Product specific probe and attach routines for:
    6  *      27/284X and aic7770 motherboard SCSI controllers
    7  *
    8  * Copyright (c) 1994, 1995, 1996 Justin T. Gibbs.
    9  * All rights reserved.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice immediately at the beginning of the file, without modification,
   16  *    this list of conditions, and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  * 3. The name of the author may not be used to endorse or promote products
   21  *    derived from this software without specific prior written permission.
   22  *
   23  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   26  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
   27  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   33  * SUCH DAMAGE.
   34  *
   35  *      $Id: ahc_eisa.c,v 1.18 2007/04/10 17:47:55 miod Exp $
   36  */
   37 
   38 #include "eisa.h"
   39 #if NEISA > 0
   40 
   41 #include <sys/param.h>
   42 #include <sys/systm.h>
   43 #include <sys/kernel.h>
   44 #include <sys/device.h>
   45 #include <machine/bus.h>
   46 #include <machine/intr.h>
   47 
   48 #include <scsi/scsi_all.h>
   49 #include <scsi/scsiconf.h>
   50 
   51 #include <dev/eisa/eisareg.h>
   52 #include <dev/eisa/eisavar.h>
   53 #include <dev/eisa/eisadevs.h>
   54 #include <dev/ic/aic7xxx_openbsd.h>
   55 #include <dev/ic/aic7xxx_inline.h>
   56 
   57 #define AHC_EISA_SLOT_OFFSET    0xc00
   58 #define AHC_EISA_IOSIZE         0x100
   59 
   60 int   ahc_eisa_irq(bus_space_tag_t, bus_space_handle_t);
   61 int   ahc_eisa_match(struct device *, void *, void *);
   62 void  ahc_eisa_attach(struct device *, struct device *, void *);
   63 
   64 
   65 struct cfattach ahc_eisa_ca = {
   66         sizeof(struct ahc_softc), ahc_eisa_match, ahc_eisa_attach
   67 };
   68 
   69 /*
   70  * Return irq setting of the board, otherwise -1.
   71  */
   72 int
   73 ahc_eisa_irq(iot, ioh)
   74 bus_space_tag_t iot;
   75 bus_space_handle_t ioh;
   76 {
   77         int irq;
   78         u_char intdef;
   79         u_char hcntrl;
   80         
   81         /* Pause the card preserving the IRQ type */
   82         hcntrl = bus_space_read_1(iot, ioh, HCNTRL) & IRQMS;
   83         bus_space_write_1(iot, ioh, HCNTRL, hcntrl | PAUSE);
   84         
   85         intdef = bus_space_read_1(iot, ioh, INTDEF);
   86         switch (irq = (intdef & VECTOR)) {
   87         case 9:
   88         case 10:
   89         case 11:
   90         case 12:
   91         case 14:
   92         case 15:
   93                 break;
   94         default:
   95                 printf("ahc_eisa_irq: illegal irq setting %d\n", intdef);
   96                 return -1;
   97         }
   98 
   99         /* Note that we are going and return (to probe) */
  100         return irq;
  101 }
  102 
  103 /*
  104  * Check the slots looking for a board we recognise
  105  * If we find one, note its address (slot) and call
  106  * the actual probe routine to check it out.
  107  */
  108 int
  109 ahc_eisa_match(parent, match, aux)
  110 struct device *parent;
  111 void *match, *aux;
  112 {
  113         struct eisa_attach_args *ea = aux;
  114         bus_space_tag_t iot = ea->ea_iot;
  115         bus_space_handle_t ioh;
  116         int irq;
  117 
  118         /* must match one of our known ID strings */
  119         if (strcmp(ea->ea_idstring, "ADP7770") &&
  120                  strcmp(ea->ea_idstring, "ADP7771")
  121 #if 0
  122                  && strcmp(ea->ea_idstring, "ADP7756")  /* not EISA, but VL */
  123                  && strcmp(ea->ea_idstring, "ADP7757")  /* not EISA, but VL */
  124 #endif
  125                 )
  126                 return (0);
  127 
  128         if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
  129                           AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh))
  130                 return (0);
  131 
  132         irq = ahc_eisa_irq(iot, ioh);
  133 
  134         bus_space_unmap(iot, ioh, AHC_EISA_IOSIZE);
  135 
  136         return (irq >= 0);
  137 }
  138 
  139 void
  140 ahc_eisa_attach(parent, self, aux)
  141 struct device *parent, *self;
  142 void *aux;
  143 {
  144         struct ahc_softc *ahc = (void *)self;
  145         struct eisa_attach_args *ea = aux;
  146         bus_space_tag_t iot = ea->ea_iot;
  147         bus_space_handle_t ioh;
  148         int irq;
  149         eisa_chipset_tag_t ec = ea->ea_ec;
  150         eisa_intr_handle_t ih;
  151         const char *model, *intrstr;
  152         u_int biosctrl;
  153         u_int scsiconf;
  154         u_int scsiconf1;
  155         u_int intdef;
  156         
  157         ahc_set_name(ahc, ahc->sc_dev.dv_xname);
  158         ahc_set_unit(ahc, ahc->sc_dev.dv_unit);
  159         
  160         /* set dma tags */
  161         ahc->parent_dmat = ea->ea_dmat;
  162 
  163         if (bus_space_map(iot, EISA_SLOT_ADDR(ea->ea_slot) +
  164                           AHC_EISA_SLOT_OFFSET, AHC_EISA_IOSIZE, 0, &ioh))
  165                 panic("ahc_eisa_attach: could not map I/O addresses");
  166         if ((irq = ahc_eisa_irq(iot, ioh)) < 0)
  167                 panic("ahc_eisa_attach: ahc_eisa_irq failed!");
  168 
  169         if (strcmp(ea->ea_idstring, "ADP7770") == 0) {
  170                 model = EISA_PRODUCT_ADP7770;
  171         } else if (strcmp(ea->ea_idstring, "ADP7771") == 0) {
  172                 model = EISA_PRODUCT_ADP7771;
  173         } else {
  174                 panic("ahc_eisa_attach: Unknown device type %s",
  175                                 ea->ea_idstring);
  176         }
  177         printf(": %s\n", model);
  178         
  179         ahc->channel = 'A';
  180         ahc->chip = AHC_AIC7770|AHC_EISA;
  181         ahc->features = AHC_AIC7770_FE;
  182         ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
  183         ahc->flags |= AHC_PAGESCBS;
  184         
  185         if (ahc_reset(ahc, /*reinit*/FALSE) != 0)
  186                 return;
  187         
  188         /* See if we are edge triggered */
  189         intdef = ahc_inb(ahc, INTDEF);
  190         if ((intdef & EDGE_TRIG) != 0)
  191                 ahc->flags |= AHC_EDGE_INTERRUPT;
  192         
  193         if (eisa_intr_map(ec, irq, &ih)) {
  194                 printf("%s: couldn't map interrupt (%d)\n",
  195                        ahc->sc_dev.dv_xname, irq);
  196                 return;
  197         }
  198 
  199         /*
  200          * Tell the user what type of interrupts we're using.
  201          * useful for debugging irq problems
  202          */
  203         if (bootverbose) {
  204                 printf("%s: Using %s Interrupts\n",
  205                        ahc_name(ahc),
  206                        ahc->pause & IRQMS ?
  207                        "Level Sensitive" : "Edge Triggered");
  208         }
  209 
  210         /*
  211          * Now that we know we own the resources we need, do the 
  212          * card initialization.
  213          *
  214          * First, the aic7770 card specific setup.
  215          */
  216         biosctrl = ahc_inb(ahc, HA_274_BIOSCTRL);
  217         scsiconf = ahc_inb(ahc, SCSICONF);
  218         scsiconf1 = ahc_inb(ahc, SCSICONF + 1);
  219         
  220         /* Get the primary channel information */
  221         if ((biosctrl & CHANNEL_B_PRIMARY) != 0)
  222                 ahc->flags |= AHC_PRIMARY_CHANNEL;
  223 
  224         if ((biosctrl & BIOSMODE) == BIOSDISABLED) {
  225                 ahc->flags |= AHC_USEDEFAULTS;
  226         } else if ((ahc->features & AHC_WIDE) != 0) {
  227                 ahc->our_id = scsiconf1 & HWSCSIID;
  228                 if (scsiconf & TERM_ENB)
  229                         ahc->flags |= AHC_TERM_ENB_A;
  230         } else {
  231                 ahc->our_id = scsiconf & HSCSIID;
  232                 ahc->our_id_b = scsiconf1 & HSCSIID;
  233                 if (scsiconf & TERM_ENB)
  234                         ahc->flags |= AHC_TERM_ENB_A;
  235                 if (scsiconf1 & TERM_ENB)
  236                         ahc->flags |= AHC_TERM_ENB_B;
  237         }
  238         /*
  239          * We have no way to tell, so assume extended
  240          * translation is enabled.
  241          */
  242         
  243         ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B;
  244         
  245         /*      
  246          * See if we have a Rev E or higher aic7770. Anything below a
  247          * Rev E will have a R/O autoflush disable configuration bit.
  248          * It's still not clear exactly what is different about the Rev E.
  249          * We think it allows 8 bit entries in the QOUTFIFO to support
  250          * "paging" SCBs so you can have more than 4 commands active at
  251          * once.
  252          */
  253         {
  254                 char *id_string;
  255                 u_char sblkctl;
  256                 u_char sblkctl_orig;
  257 
  258                 sblkctl_orig = ahc_inb(ahc, SBLKCTL);
  259                 sblkctl = sblkctl_orig ^ AUTOFLUSHDIS;
  260                 ahc_outb(ahc, SBLKCTL, sblkctl);
  261                 sblkctl = ahc_inb(ahc, SBLKCTL);
  262                 if (sblkctl != sblkctl_orig) {
  263                         id_string = "aic7770 >= Rev E, ";
  264                         /*
  265                          * Ensure autoflush is enabled
  266                          */
  267                         sblkctl &= ~AUTOFLUSHDIS;
  268                         ahc_outb(ahc, SBLKCTL, sblkctl);
  269 
  270                         /* Allow paging on this adapter */
  271                         ahc->flags |= AHC_PAGESCBS;
  272                 } else
  273                         id_string = "aic7770 <= Rev C, ";
  274 
  275                 printf("%s: %s", ahc_name(ahc), id_string);
  276         }
  277 
  278         /* Setup the FIFO threshold and the bus off time */
  279         {
  280                 u_char hostconf = ahc_inb(ahc, HOSTCONF);
  281                 ahc_outb(ahc, BUSSPD, hostconf & DFTHRSH);
  282                 ahc_outb(ahc, BUSTIME, (hostconf << 2) & BOFF);
  283         }
  284 
  285         /*
  286          * Generic aic7xxx initialization.
  287          */
  288         if (ahc_init(ahc)) {
  289                 ahc_free(ahc);
  290                 return;
  291         }
  292  
  293         /*
  294          * Link this softc in with all other ahc instances.
  295          */
  296         ahc_softc_insert(ahc);
  297         
  298         /*
  299          * Enable the board's BUS drivers
  300          */
  301         ahc_outb(ahc, BCTL, ENABLE);
  302 
  303         intrstr = eisa_intr_string(ec, ih);
  304         /*
  305          * The IRQMS bit enables level sensitive interrupts only allow
  306          * IRQ sharing if its set.
  307          */
  308         ahc->ih = eisa_intr_establish(ec, ih,
  309             ahc->pause & IRQMS ? IST_LEVEL : IST_EDGE, IPL_BIO,
  310             ahc_platform_intr, ahc, ahc->sc_dev.dv_xname);
  311         if (ahc->ih == NULL) {
  312                 printf("%s: couldn't establish interrupt",
  313                        ahc->sc_dev.dv_xname);
  314                 if (intrstr != NULL)
  315                         printf(" at %s", intrstr);
  316                 printf("\n");
  317                 ahc_free(ahc);
  318                 return;
  319         }
  320         if (intrstr != NULL)
  321                 printf("%s: interrupting at %s\n", ahc->sc_dev.dv_xname,
  322                        intrstr);
  323         
  324         ahc_intr_enable(ahc, TRUE);
  325 
  326         /* Attach sub-devices - always succeeds */
  327         ahc_attach(ahc);
  328 
  329 }
  330 #endif /* NEISA > 0 */

/* [<][>][^][v][top][bottom][index][help] */