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/mca/esp_mca.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: esp_mca.c,v 1.7 2003/07/14 15:47:18 lukem Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 2001 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jaromir Dolecek <jdolecek@NetBSD.org>.
    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  * Driver for NCR 53c90, MCA version, with 86c01 DMA controller chip.
   41  * 
   42  * Some of the information used to write this driver was taken
   43  * from Tymm Twillman <tymm@computer.org>'s Linux MCA NC53c90 driver,
   44  * in drivers/scsi/mca_53c9x.c
   45  */
   46 
   47 #include <sys/cdefs.h>
   48 __KERNEL_RCSID(0, "$NetBSD: esp_mca.c,v 1.7 2003/07/14 15:47:18 lukem Exp $");
   49 
   50 #include <sys/types.h>
   51 #include <sys/param.h>
   52 #include <sys/systm.h>
   53 #include <sys/kernel.h>
   54 #include <sys/errno.h>
   55 #include <sys/ioctl.h>
   56 #include <sys/device.h>
   57 #include <sys/buf.h>
   58 #include <sys/proc.h>
   59 #include <sys/user.h>
   60 #include <sys/queue.h>
   61 
   62 #include <dev/scsipi/scsi_all.h>
   63 #include <dev/scsipi/scsipi_all.h>
   64 #include <dev/scsipi/scsiconf.h>
   65 #include <dev/scsipi/scsi_message.h>
   66 
   67 #include <machine/bus.h>
   68 #include <machine/cpu.h>
   69 
   70 #include <dev/ic/ncr53c9xreg.h>
   71 #include <dev/ic/ncr53c9xvar.h>
   72 
   73 #include <dev/mca/espvar.h>
   74 #include <dev/mca/espreg.h>
   75 
   76 #include <dev/mca/mcavar.h>
   77 #include <dev/mca/mcareg.h>
   78 #include <dev/mca/mcadevs.h>
   79 
   80 #if 0
   81 #if defined(DEBUG) && !defined(NCR53C9X_DEBUG)
   82 #define NCR53C9X_DEBUG
   83 #endif
   84 #endif
   85 
   86 #ifdef NCR53C9X_DEBUG
   87 static int esp_mca_debug = 0;
   88 #define DPRINTF(x) if (esp_mca_debug) printf x;
   89 #else
   90 #define DPRINTF(x)
   91 #endif
   92 
   93 #define ESP_MCA_IOSIZE  0x20
   94 #define ESP_REG_OFFSET  0x10
   95 
   96 static void     esp_mca_attach  __P((struct device *, struct device *, void *));
   97 static int      esp_mca_match   __P((struct device *, struct cfdata *, void *));
   98 
   99 CFATTACH_DECL(esp_mca, sizeof(struct esp_softc),
  100     esp_mca_match, esp_mca_attach, NULL, NULL);
  101 
  102 /*
  103  * Functions and the switch for the MI code.
  104  */
  105 static u_char   esp_read_reg __P((struct ncr53c9x_softc *, int));
  106 static void     esp_write_reg __P((struct ncr53c9x_softc *, int, u_char));
  107 static int      esp_dma_isintr __P((struct ncr53c9x_softc *));
  108 static void     esp_dma_reset __P((struct ncr53c9x_softc *));
  109 static int      esp_dma_intr __P((struct ncr53c9x_softc *));
  110 static int      esp_dma_setup __P((struct ncr53c9x_softc *, caddr_t *,
  111             size_t *, int, size_t *));
  112 static void     esp_dma_go __P((struct ncr53c9x_softc *));
  113 static void     esp_dma_stop __P((struct ncr53c9x_softc *));
  114 static int      esp_dma_isactive __P((struct ncr53c9x_softc *));
  115 
  116 static struct ncr53c9x_glue esp_glue = {
  117         esp_read_reg,
  118         esp_write_reg,
  119         esp_dma_isintr,
  120         esp_dma_reset,
  121         esp_dma_intr,
  122         esp_dma_setup,
  123         esp_dma_go,
  124         esp_dma_stop,
  125         esp_dma_isactive,
  126         NULL,                   /* gl_clear_latched_intr */
  127 };
  128 
  129 static int
  130 esp_mca_match(parent, cf, aux)
  131         struct device *parent;
  132         struct cfdata *cf;
  133         void *aux;
  134 {
  135         struct mca_attach_args *ma = aux;
  136 
  137         switch (ma->ma_id) {
  138         case MCA_PRODUCT_NCR53C90:
  139                 return 1;
  140         }
  141 
  142         return 0;
  143 }
  144 
  145 static void
  146 esp_mca_attach(parent, self, aux)
  147         struct device *parent, *self;
  148         void *aux;
  149 {
  150         struct mca_attach_args *ma = aux;
  151         struct esp_softc *esc = (void *)self;
  152         struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
  153         u_int16_t iobase;
  154         int scsi_id, irq, drq, error;
  155         bus_space_handle_t ioh;
  156         int pos2, pos3, pos5;
  157 
  158         static const u_int16_t ncrmca_iobase[] = {
  159                 0, 0x240, 0x340, 0x400, 0x420, 0x3240, 0x8240, 0xa240
  160         };
  161 
  162         /*
  163          * NCR SCSI Adapter (ADF 7f4f)
  164          *
  165          * POS register 2: (adf pos0)
  166          * 
  167          * 7 6 5 4 3 2 1 0
  168          *     \_/ \___/ \__ enable: 0=adapter disabled, 1=adapter enabled
  169          *      |      \____ I/O base (32B): 001=0x240 010=0x340 011=0x400
  170          *      |              100=0x420 101=0x3240 110=0x8240 111=0xa240
  171          *       \__________ IRQ: 00=3 01=5 10=7 11=9
  172          *
  173          * POS register 3: (adf pos1)
  174          * 
  175          * 7 6 5 4 3 2 1 0
  176          * 1 1 1 | \_____/
  177          *       |       \__ DMA level
  178          *        \_________ Fairness: 1=enabled 0=disabled
  179          *
  180          * POS register 5: (adf pos3)
  181          * 
  182          * 7 6 5 4 3 2 1 0
  183          * 1   |     \___/
  184          *     |         \__ Static Ram: 0xC8000-0xC87FF + XX*0x4000
  185          *      \___________ Host Adapter ID: 1=7 0=6
  186          */
  187 
  188         pos2 = mca_conf_read(ma->ma_mc, ma->ma_slot, 2);
  189         pos3 = mca_conf_read(ma->ma_mc, ma->ma_slot, 3);
  190         pos5 = mca_conf_read(ma->ma_mc, ma->ma_slot, 5);
  191 
  192         iobase = ncrmca_iobase[(pos2 & 0x0e) >> 1];
  193         irq = 3 + 2*((pos2 & 0x30) >> 4);
  194         drq = (pos3 & 0x0f);
  195         scsi_id = 6 + ((pos5 & 0x20) ? 1 : 0);
  196 
  197         printf(" slot %d irq %d drq %d: NCR SCSI Adapter\n",
  198                 ma->ma_slot + 1, irq, drq);
  199 
  200         /* Map the 86C01 registers */
  201         if (bus_space_map(ma->ma_iot, iobase, ESP_MCA_IOSIZE, 0, &ioh)) {
  202                 printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname);
  203                 return;
  204         }
  205 
  206         esc->sc_iot = ma->ma_iot;
  207         esc->sc_ioh = ioh;
  208 
  209         /* Submap the 'esp' registers */
  210         if (bus_space_subregion(ma->ma_iot, ioh, ESP_REG_OFFSET,
  211             ESP_MCA_IOSIZE-ESP_REG_OFFSET, &esc->sc_esp_ioh)) {
  212                 printf("%s: can't subregion i/o space\n", sc->sc_dev.dv_xname);
  213                 return;
  214         }
  215 
  216         /* Setup DMA map */
  217         esc->sc_dmat = ma->ma_dmat;
  218         if ((error = mca_dmamap_create(esc->sc_dmat, MAXPHYS,
  219             BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW | MCABUS_DMA_IOPORT,
  220             &esc->sc_xfer, drq)) != 0){
  221                 printf("%s: couldn't create DMA map - error %d\n",
  222                         sc->sc_dev.dv_xname, error);
  223                 return;
  224         }
  225 
  226         /* MI code glue */
  227         sc->sc_id = scsi_id;
  228         sc->sc_freq = 25;               /* Mhz */
  229 
  230         sc->sc_glue = &esp_glue;
  231 
  232         sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB; //| NCRCFG1_SLOW;
  233         /* No point setting sc_cfg[2345], they won't be used */
  234 
  235         sc->sc_rev = NCR_VARIANT_NCR53C90_86C01;
  236         sc->sc_minsync = 0;
  237 
  238         /* max 64KB DMA */
  239         sc->sc_maxxfer = 64 * 1024;
  240 
  241         /* Establish interrupt */
  242         esc->sc_ih = mca_intr_establish(ma->ma_mc, irq, IPL_BIO, ncr53c9x_intr,
  243                         esc);
  244         if (esc->sc_ih == NULL) {
  245                 printf("%s: couldn't establish interrupt\n",
  246                     sc->sc_dev.dv_xname);
  247                 return;
  248         }
  249 
  250         /*
  251          * Massage the 86C01 chip - setup MCA DMA controller for DMA via
  252          * the 86C01 register, and enable 86C01 interrupts.
  253          */
  254         mca_dma_set_ioport(drq, iobase + N86C01_PIO);
  255 
  256         bus_space_write_1(esc->sc_iot, esc->sc_ioh, N86C01_MODE_ENABLE,
  257                 bus_space_read_1(esc->sc_iot, esc->sc_ioh, N86C01_MODE_ENABLE)
  258                 | N86C01_INTR_ENABLE);
  259 
  260         /*
  261          * Now try to attach all the sub-devices
  262          */
  263         sc->sc_adapter.adapt_minphys = minphys;
  264         sc->sc_adapter.adapt_request = ncr53c9x_scsipi_request;
  265 
  266         /* Do the common parts of attachment. */
  267         printf("%s", sc->sc_dev.dv_xname);
  268         ncr53c9x_attach(sc);
  269 }
  270 
  271 /*
  272  * Glue functions.
  273  */
  274 
  275 static u_char
  276 esp_read_reg(sc, reg)
  277         struct ncr53c9x_softc *sc;
  278         int reg;
  279 {
  280         struct esp_softc *esc = (struct esp_softc *)sc;
  281 
  282         return (bus_space_read_1(esc->sc_iot, esc->sc_esp_ioh, reg));
  283 }
  284 
  285 static void
  286 esp_write_reg(sc, reg, val)
  287         struct ncr53c9x_softc *sc;
  288         int reg;
  289         u_char val;
  290 {
  291         struct esp_softc *esc = (struct esp_softc *)sc;
  292 
  293         bus_space_write_1(esc->sc_iot, esc->sc_esp_ioh, reg, val);
  294 }
  295 
  296 static int
  297 esp_dma_isintr(sc)
  298         struct ncr53c9x_softc *sc;
  299 {
  300         struct esp_softc *esc = (struct esp_softc *)sc;
  301 
  302         DPRINTF(("[esp_dma_isintr] "));
  303         return (bus_space_read_1(esc->sc_iot, esc->sc_ioh,
  304                 N86C01_STATUS) & N86C01_IRQ_PEND);
  305 }
  306 
  307 static void
  308 esp_dma_reset(sc)
  309         struct ncr53c9x_softc *sc;
  310 {
  311         struct esp_softc *esc = (struct esp_softc *)sc;
  312 
  313         DPRINTF(("[esp_dma_reset] "));
  314 
  315         if (esc->sc_flags & ESP_XFER_LOADED) {
  316                 bus_dmamap_unload(esc->sc_dmat, esc->sc_xfer);
  317                 esc->sc_flags &= ~ESP_XFER_LOADED;
  318         }
  319 
  320         if (esc->sc_flags & ESP_XFER_ACTIVE) {
  321                 esc->sc_flags &= ~ESP_XFER_ACTIVE;
  322                 mca_disk_unbusy();
  323         }
  324 }
  325 
  326 static int
  327 esp_dma_intr(sc)
  328         struct ncr53c9x_softc *sc;
  329 {
  330         struct esp_softc *esc = (struct esp_softc *) sc;
  331         DPRINTF(("[esp_dma_intr] "));
  332 
  333         if ((esc->sc_flags & ESP_XFER_ACTIVE) == 0) {
  334                 printf("%s: dma_intr--inactive DMA\n", sc->sc_dev.dv_xname);
  335                 return (-1);
  336         }
  337 
  338         if ((sc->sc_espintr & NCRINTR_BS) == 0) {
  339                 esc->sc_flags &= ~ESP_XFER_ACTIVE;
  340                 mca_disk_unbusy();
  341                 return (0);
  342         }
  343 
  344         sc->sc_espstat |= NCRSTAT_TC;   /* XXX */
  345 
  346         if ((sc->sc_espstat & NCRSTAT_TC) == 0) {
  347                 printf("%s: DMA not complete?\n", sc->sc_dev.dv_xname);
  348                 return (1);
  349         }
  350 
  351         bus_dmamap_sync(esc->sc_dmat, esc->sc_xfer, 0,
  352                 *esc->sc_xfer_len,
  353                 (esc->sc_flags & ESP_XFER_READ)
  354                         ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE);
  355         
  356         bus_dmamap_unload(esc->sc_dmat, esc->sc_xfer);
  357         esc->sc_flags &= ~ESP_XFER_LOADED;
  358 
  359         *esc->sc_xfer_addr +=  *esc->sc_xfer_len;
  360         *esc->sc_xfer_len = 0;
  361 
  362         esc->sc_flags &= ~ESP_XFER_ACTIVE;
  363         mca_disk_unbusy();
  364 
  365         return (0);
  366 }
  367 
  368 /*
  369  * Setup DMA transfer.
  370  */
  371 static int
  372 esp_dma_setup(sc, addr, len, datain, dmasize)
  373         struct ncr53c9x_softc *sc;
  374         caddr_t *addr;
  375         size_t *len;
  376         int datain;
  377         size_t *dmasize;
  378 {
  379         struct esp_softc *esc = (struct esp_softc *) sc;
  380         int error;
  381         int fl;
  382 
  383         DPRINTF(("[esp_dma_setup] "));
  384 
  385         if (esc->sc_flags & ESP_XFER_LOADED) {
  386                 printf("%s: esp_dma_setup: unloading leaked xfer\n",
  387                         sc->sc_dev.dv_xname);
  388                 bus_dmamap_unload(esc->sc_dmat, esc->sc_xfer);
  389                 esc->sc_flags &= ~ESP_XFER_LOADED;
  390         }
  391 
  392         /* Load the buffer for DMA transfer. */
  393         fl = (datain) ? BUS_DMA_READ : BUS_DMA_WRITE;
  394 
  395         if ((error = bus_dmamap_load(esc->sc_dmat, esc->sc_xfer, *addr,
  396             *len, NULL, BUS_DMA_STREAMING|fl))) {
  397                 printf("%s: esp_dma_setup: unable to load DMA buffer - error %d\n",
  398                         sc->sc_dev.dv_xname, error);
  399                 return (error);
  400         }
  401 
  402         bus_dmamap_sync(esc->sc_dmat, esc->sc_xfer, 0,
  403                 *len, (datain) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
  404         
  405         esc->sc_flags |= ESP_XFER_LOADED | (datain ? ESP_XFER_READ : 0);
  406         esc->sc_xfer_addr = addr;
  407         esc->sc_xfer_len  = len;
  408 
  409         return (0);
  410 }
  411 
  412 static void
  413 esp_dma_go(sc)
  414         struct ncr53c9x_softc *sc;
  415 {
  416         struct esp_softc *esc = (struct esp_softc *) sc;
  417         DPRINTF(("[esp_dma_go] "));
  418 
  419         esc->sc_flags |= ESP_XFER_ACTIVE;
  420         mca_disk_busy();
  421 }
  422 
  423 static void
  424 esp_dma_stop(sc)
  425         struct ncr53c9x_softc *sc;
  426 {
  427         DPRINTF(("[esp_dma_stop] "));
  428 
  429         panic("%s: stop not yet implemented", sc->sc_dev.dv_xname);
  430 }
  431 
  432 static int
  433 esp_dma_isactive(sc)
  434         struct ncr53c9x_softc *sc;
  435 {
  436         struct esp_softc *esc = (struct esp_softc *) sc;
  437         DPRINTF(("[esp_dma_isactive] "));
  438 
  439         return (esc->sc_flags & ESP_XFER_ACTIVE);
  440 }

Cache object: a672bb4c66c7967348b6c2349ef7cef8


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