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/isa/nca_isa.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: nca_isa.c,v 1.12 2002/10/02 03:10:49 thorpej Exp $     */
    2 
    3 /*-
    4  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by John M. Ruschmeyer.
    9  *
   10  * Redistribution and use in source and binary forms, with or without
   11  * modification, are permitted provided that the following conditions
   12  * are met:
   13  * 1. Redistributions of source code must retain the above copyright
   14  *    notice, this list of conditions and the following disclaimer.
   15  * 2. Redistributions in binary form must reproduce the above copyright
   16  *    notice, this list of conditions and the following disclaimer in the
   17  *    documentation and/or other materials provided with the distribution.
   18  * 3. All advertising materials mentioning features or use of this software
   19  *    must display the following acknowledgement:
   20  *        This product includes software developed by the NetBSD
   21  *        Foundation, Inc. and its contributors.
   22  * 4. Neither the name of The NetBSD Foundation nor the names of its
   23  *    contributors may be used to endorse or promote products derived
   24  *    from this software without specific prior written permission.
   25  *
   26  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   27  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   28  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   29  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   30  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   36  * POSSIBILITY OF SUCH DAMAGE.
   37  */
   38 
   39 /*
   40  * FreeBSD generic NCR-5380/NCR-53C400 SCSI driver
   41  *
   42  * Copyright (C) 1994 Serge Vakulenko (vak@cronyx.ru)
   43  *
   44  * Redistribution and use in source and binary forms, with or without
   45  * modification, are permitted provided that the following conditions
   46  * are met:
   47  * 1. Redistributions of source code must retain the above copyright
   48  *    notice, this list of conditions and the following disclaimer.
   49  * 2. Redistributions in binary form must reproduce the above copyright
   50  *    notice, this list of conditions and the following disclaimer in the
   51  *    documentation and/or other materials provided with the distribution.
   52  *
   53  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND
   54  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPERS BE LIABLE
   57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   63  * SUCH DAMAGE.
   64  */
   65 
   66 #include <sys/cdefs.h>
   67 __KERNEL_RCSID(0, "$NetBSD: nca_isa.c,v 1.12 2002/10/02 03:10:49 thorpej Exp $");
   68 
   69 #include <sys/param.h>
   70 #include <sys/systm.h>
   71 #include <sys/device.h>
   72 #include <sys/buf.h>
   73 
   74 #include <machine/bus.h>
   75 #include <machine/intr.h>
   76 
   77 #include <dev/scsipi/scsi_all.h>
   78 #include <dev/scsipi/scsipi_all.h>
   79 #include <dev/scsipi/scsiconf.h>
   80 
   81 #include <dev/isa/isavar.h>
   82 #include <dev/isa/isadmavar.h>
   83 
   84 #include <dev/ic/ncr5380reg.h>
   85 #include <dev/ic/ncr5380var.h>
   86 #include <dev/ic/ncr53c400reg.h>
   87 
   88 struct nca_isa_softc {
   89         struct ncr5380_softc    sc_ncr5380;     /* glue to MI code */
   90 
   91         void *sc_ih;
   92         int sc_irq;
   93         int sc_options;
   94 };
   95 
   96 struct nca_isa_probe_data {
   97         struct device sc_dev;
   98         int sc_reg_offset;
   99         int sc_host_type;
  100 };
  101 
  102 int     nca_isa_find __P((bus_space_tag_t, bus_space_handle_t, bus_size_t,
  103             struct nca_isa_probe_data *));
  104 int     nca_isa_match __P((struct device *, struct cfdata *, void *)); 
  105 void    nca_isa_attach __P((struct device *, struct device *, void *));  
  106 int     nca_isa_test __P((bus_space_tag_t, bus_space_handle_t, bus_size_t));
  107 
  108 CFATTACH_DECL(nca_isa, sizeof(struct nca_isa_softc),
  109     nca_isa_match, nca_isa_attach, NULL, NULL);
  110 
  111 
  112 /* Supported controller types */
  113 #define MAX_NCA_CONTROLLER      3
  114 #define CTLR_NCR_5380   1
  115 #define CTLR_NCR_53C400 2
  116 #define CTLR_PAS16      3
  117 
  118 #define NCA_ISA_IOSIZE 16
  119 #define MIN_DMA_LEN 128
  120 
  121 /* Options for disconnect/reselect, DMA, and interrupts. */
  122 #define NCA_NO_DISCONNECT    0xff
  123 #define NCA_NO_PARITY_CHK  0xff00
  124 #define NCA_FORCE_POLLING 0x10000
  125 
  126 
  127 /*
  128  * Initialization and test function used by nca_isa_find()
  129  */
  130 int
  131 nca_isa_test(iot, ioh, reg_offset)
  132         bus_space_tag_t iot;
  133         bus_space_handle_t ioh;
  134         bus_size_t reg_offset;
  135 {
  136         /* Reset the SCSI bus. */
  137         bus_space_write_1(iot, ioh, reg_offset + C80_ICR, SCI_ICMD_RST);
  138         bus_space_write_1(iot, ioh, reg_offset + C80_ODR, 0);
  139         /* Hold reset for at least 25 microseconds. */
  140         delay(500);
  141         /* Check that status cleared. */
  142         if (bus_space_read_1(iot, ioh, reg_offset + C80_CSBR) != SCI_BUS_RST) {
  143 #ifdef DEBUG
  144                 printf("nca_isa_find: reset status not cleared [0x%x]\n",
  145                     bus_space_read_1(iot, ioh, reg_offset+C80_CSBR));
  146 #endif
  147                 bus_space_write_1(iot, ioh, reg_offset+C80_ICR, 0);
  148                 return 0;
  149         }
  150         /* Clear reset. */
  151         bus_space_write_1(iot, ioh, reg_offset + C80_ICR, 0);
  152         /* Wait a Bus Clear Delay (800 ns + bus free delay 800 ns). */
  153         delay(16000);
  154 
  155         /* Read RPI port, resetting parity/interrupt state. */
  156         bus_space_read_1(iot, ioh, reg_offset + C80_RPIR);
  157 
  158         /* Test BSR: parity error, interrupt request and busy loss state
  159          * should be cleared. */
  160         if (bus_space_read_1(iot, ioh, reg_offset + C80_BSR) & (SCI_CSR_PERR |
  161             SCI_CSR_INT | SCI_CSR_DISC)) {
  162 #ifdef DEBUG
  163                 printf("nca_isa_find: Parity/Interrupt/Busy not cleared [0x%x]\n",
  164                     bus_space_read_1(iot, ioh, reg_offset+C80_BSR));
  165 #endif
  166                 return 0;
  167         }
  168 
  169         /* We must have found one */
  170         return 1;
  171 }
  172 
  173 
  174 /*
  175  * Look for the board
  176  */
  177 int
  178 nca_isa_find(iot, ioh, max_offset, epd)
  179         bus_space_tag_t iot;
  180         bus_space_handle_t ioh;
  181         bus_size_t max_offset;
  182         struct nca_isa_probe_data *epd;
  183 {
  184         /*
  185          * We check for the existence of a board by trying to initialize it,
  186          * Then sending the commands to reset the SCSI bus.
  187          * (Unfortunately, this duplicates code which is already in the MI
  188          * driver. Unavoidable as that code is not suited to this task.)
  189          * This is largely stolen from FreeBSD.
  190          */
  191 
  192         int             cont_type;
  193         bus_size_t      base_offset, reg_offset = 0;
  194 
  195         /*
  196          * Some notes:
  197          * In the case of a port-mapped board, we should be pointing
  198          * right at the chip registers (if they are there at all).
  199          * For a memory-mapped card, we loop through the 16K paragraph,
  200          * 8 bytes at a time, until we either find it or run out
  201          * of region. This means we will probably be doing things like
  202          * trying to write to ROMS, etc. Hopefully, this is not a problem.
  203          */
  204 
  205         for (base_offset = 0; base_offset < max_offset; base_offset += 0x08) {
  206 #ifdef DEBUG
  207                 printf("nca_isa_find: testing offset 0x%x\n", (int)base_offset);
  208 #endif
  209 
  210                 /* See if anything is there */
  211                 if (bus_space_read_1(iot, ioh, base_offset) == 0xff)
  212                         continue;
  213 
  214                 /* Loop around for each board type */
  215                 for (cont_type = 1; cont_type <= MAX_NCA_CONTROLLER; cont_type++) {
  216                         /* Per-controller initialization */
  217                         switch (cont_type) {
  218                         case CTLR_NCR_5380:
  219                                 /* No special inits */
  220                                 reg_offset = 0;
  221                                 break;
  222                         case CTLR_NCR_53C400:
  223                                 /* Reset into 5380-compat. mode */
  224                                 bus_space_write_1(iot, ioh,
  225                                     base_offset + C400_CSR,
  226                                     C400_CSR_5380_ENABLE);
  227                                 reg_offset = C400_5380_REG_OFFSET;
  228                                 break;
  229                         case CTLR_PAS16:
  230                                 /* Not currently supported */
  231                                 reg_offset = 0;
  232                                 cont_type = 0;
  233                                 continue;
  234                         }
  235 
  236                         /* Initialize controller and bus */
  237                         if (nca_isa_test(iot, ioh, base_offset+reg_offset)) {
  238                                 epd->sc_reg_offset = base_offset;
  239                                 epd->sc_host_type = cont_type;
  240                                 return cont_type;       /* This must be it */
  241                         }
  242                 }
  243         }
  244 
  245         /* If we got here, we didn't find one */
  246         return 0;
  247 }
  248 
  249 
  250 /*
  251  * See if there is anything at the config'd address.
  252  * If so, call the real probe to see what it is.
  253  */
  254 int
  255 nca_isa_match(parent, match, aux)
  256         struct device *parent;
  257         struct cfdata *match;
  258         void *aux;
  259 {
  260         struct isa_attach_args *ia = aux;
  261         bus_space_tag_t iot = ia->ia_iot;
  262         bus_space_tag_t memt = ia->ia_memt;
  263         bus_space_handle_t ioh;
  264         struct nca_isa_probe_data epd;
  265         int rv = 0;
  266 
  267         if (ISA_DIRECT_CONFIG(ia))
  268                 return (0);
  269 
  270         /* See if we are looking for a port- or memory-mapped adapter */
  271         if (ia->ia_nio > 0 || ia->ia_io[0].ir_addr != ISACF_PORT_DEFAULT) {
  272                 /* Port-mapped card */
  273                 if (bus_space_map(iot, ia->ia_io[0].ir_addr, NCA_ISA_IOSIZE,
  274                     0, &ioh))
  275                         return 0;
  276 
  277                 /* See if a 53C80/53C400 is there */
  278                 rv = nca_isa_find(iot, ioh, 0x07, &epd);
  279 
  280                 bus_space_unmap(iot, ioh, NCA_ISA_IOSIZE);
  281 
  282                 if (rv) {
  283                         ia->ia_nio = 1;
  284                         ia->ia_io[0].ir_size = NCA_ISA_IOSIZE;
  285 
  286                         ia->ia_niomem = 0;
  287                         ia->ia_ndrq = 0;
  288                 }
  289         } else if (ia->ia_niomem > 0) {
  290                 /* Memory-mapped card */
  291                 if (bus_space_map(memt, ia->ia_iomem[0].ir_addr, 0x4000,
  292                     0, &ioh))
  293                         return 0;
  294 
  295                 /* See if a 53C80/53C400 is somewhere in this para. */
  296                 rv = nca_isa_find(memt, ioh, 0x03ff0, &epd);
  297 
  298                 bus_space_unmap(memt, ioh, 0x04000);
  299 
  300                 if (rv) {
  301                         ia->ia_niomem = 1;
  302                         ia->ia_iomem[0].ir_addr += epd.sc_reg_offset;
  303                         ia->ia_iomem[0].ir_size = NCA_ISA_IOSIZE;
  304 
  305                         ia->ia_nio = 0;
  306                         ia->ia_ndrq = 0;
  307                 }
  308         }
  309 
  310         return rv;
  311 }
  312 
  313 /*
  314  * Attach this instance, and then all the sub-devices
  315  */
  316 void
  317 nca_isa_attach(parent, self, aux)
  318         struct device *parent, *self;
  319         void *aux;
  320 {
  321         struct isa_attach_args *ia = aux;
  322         struct nca_isa_softc *esc = (void *)self;
  323         struct ncr5380_softc *sc = &esc->sc_ncr5380;
  324         bus_space_tag_t iot = ia->ia_iot;
  325         bus_space_handle_t ioh;
  326         struct nca_isa_probe_data epd;
  327         isa_chipset_tag_t ic = ia->ia_ic;
  328 
  329         printf("\n");
  330 
  331         if (ia->ia_nio > 0) {
  332                 iot = ia->ia_iot;
  333                 if (bus_space_map(iot, ia->ia_io[0].ir_addr, NCA_ISA_IOSIZE,
  334                     0, &ioh)) {
  335                         printf("%s: can't map i/o space\n",
  336                             sc->sc_dev.dv_xname);
  337                         return;
  338                 }
  339         } else {
  340                 KASSERT(ia->ia_niomem > 0);
  341                 iot = ia->ia_memt;
  342                 if (bus_space_map(iot, ia->ia_iomem[0].ir_addr, NCA_ISA_IOSIZE,
  343                     0, &ioh)) {
  344                         printf("%s: can't map mem space\n",
  345                             sc->sc_dev.dv_xname);
  346                         return;
  347                 }
  348         }
  349 
  350         switch (nca_isa_find(iot, ioh, NCA_ISA_IOSIZE, &epd)) {
  351         case 0:
  352                 /* Not found- must have gone away */
  353                 printf("%s: nca_isa_find failed\n", sc->sc_dev.dv_xname);
  354                 return;
  355         case CTLR_NCR_5380:
  356                 printf("%s: NCR 53C80 detected\n", sc->sc_dev.dv_xname);
  357                 sc->sci_r0 = 0;
  358                 sc->sci_r1 = 1;
  359                 sc->sci_r2 = 2;
  360                 sc->sci_r3 = 3;
  361                 sc->sci_r4 = 4;
  362                 sc->sci_r5 = 5;
  363                 sc->sci_r6 = 6;
  364                 sc->sci_r7 = 7;
  365                 sc->sc_rev = NCR_VARIANT_NCR5380;
  366                 break;
  367         case CTLR_NCR_53C400:
  368                 printf("%s: NCR 53C400 detected\n", sc->sc_dev.dv_xname);
  369                 sc->sci_r0 = C400_5380_REG_OFFSET + 0;
  370                 sc->sci_r1 = C400_5380_REG_OFFSET + 1;
  371                 sc->sci_r2 = C400_5380_REG_OFFSET + 2;
  372                 sc->sci_r3 = C400_5380_REG_OFFSET + 3;
  373                 sc->sci_r4 = C400_5380_REG_OFFSET + 4;
  374                 sc->sci_r5 = C400_5380_REG_OFFSET + 5;
  375                 sc->sci_r6 = C400_5380_REG_OFFSET + 6;
  376                 sc->sci_r7 = C400_5380_REG_OFFSET + 7;
  377                 sc->sc_rev = NCR_VARIANT_NCR53C400;
  378                 break;
  379         case CTLR_PAS16:
  380                 printf("%s: ProAudio Spectrum 16 detected\n",
  381                     sc->sc_dev.dv_xname);
  382                 sc->sc_rev = NCR_VARIANT_PAS16;
  383                 break;
  384         }
  385 
  386         /*
  387          * MD function pointers used by the MI code.
  388          */
  389         sc->sc_pio_out = ncr5380_pio_out;
  390         sc->sc_pio_in =  ncr5380_pio_in;
  391         sc->sc_dma_alloc = NULL;
  392         sc->sc_dma_free  = NULL;
  393         sc->sc_dma_setup = NULL;
  394         sc->sc_dma_start = NULL;
  395         sc->sc_dma_poll  = NULL;
  396         sc->sc_dma_eop   = NULL;
  397         sc->sc_dma_stop  = NULL;
  398         sc->sc_intr_on   = NULL;
  399         sc->sc_intr_off  = NULL;
  400 
  401         if (ia->ia_nirq > 0 && ia->ia_irq[0].ir_irq != ISACF_IRQ_DEFAULT) {
  402                 esc->sc_ih = isa_intr_establish(ic, ia->ia_irq[0].ir_irq,
  403                     IST_EDGE, IPL_BIO, ncr5380_intr, esc);
  404                 if (esc->sc_ih == NULL) {
  405                         printf("%s: couldn't establish interrupt\n",
  406                             sc->sc_dev.dv_xname);
  407                         return;
  408                 }
  409         } else 
  410                 sc->sc_flags |= NCR5380_FORCE_POLLING;
  411 
  412 
  413         /*
  414          * Support the "options" (config file flags).
  415          * Disconnect/reselect is a per-target mask.
  416          * Interrupts and DMA are per-controller.
  417          */
  418 #if 0
  419         esc->sc_options = 0x00000;      /* no options */
  420 #else
  421         esc->sc_options = 0x0ffff;      /* all options except force poll */
  422 #endif
  423 
  424         sc->sc_no_disconnect =
  425                 (esc->sc_options & NCA_NO_DISCONNECT);
  426         sc->sc_parity_disable = 
  427                 (esc->sc_options & NCA_NO_PARITY_CHK) >> 8;
  428         if (esc->sc_options & NCA_FORCE_POLLING)
  429                 sc->sc_flags |= NCR5380_FORCE_POLLING;
  430         sc->sc_min_dma_len = MIN_DMA_LEN;
  431 
  432 
  433         /*
  434          * Initialize fields used by the MI code
  435          */
  436         sc->sc_regt = iot;
  437         sc->sc_regh = ioh;
  438 
  439         /*
  440          * Fill in our portion of the scsipi_adapter.
  441          */
  442         sc->sc_adapter.adapt_request = ncr5380_scsipi_request;
  443         sc->sc_adapter.adapt_minphys = minphys;
  444 
  445         /*
  446          * Fill in our portion of the scsipi_channel.
  447          */
  448 
  449         sc->sc_channel.chan_id = 7;
  450 
  451         /*
  452          *  Initialize nca board itself.
  453          */
  454         ncr5380_attach(sc);
  455 }

Cache object: 575eb1f14bef318081bfa34bf8981c46


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