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/esp/esp_sbus.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  * Copyright (c) 2004 Scott Long
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  *
   26  */
   27 
   28 /*      $NetBSD: esp_sbus.c,v 1.31 2005/02/27 00:27:48 perry Exp $      */
   29 
   30 /*-
   31  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
   32  * All rights reserved.
   33  *
   34  * This code is derived from software contributed to The NetBSD Foundation
   35  * by Charles M. Hannum; Jason R. Thorpe of the Numerical Aerospace
   36  * Simulation Facility, NASA Ames Research Center; Paul Kranenburg.
   37  *
   38  * Redistribution and use in source and binary forms, with or without
   39  * modification, are permitted provided that the following conditions
   40  * are met:
   41  * 1. Redistributions of source code must retain the above copyright
   42  *    notice, this list of conditions and the following disclaimer.
   43  * 2. Redistributions in binary form must reproduce the above copyright
   44  *    notice, this list of conditions and the following disclaimer in the
   45  *    documentation and/or other materials provided with the distribution.
   46  * 3. All advertising materials mentioning features or use of this software
   47  *    must display the following acknowledgement:
   48  *      This product includes software developed by the NetBSD
   49  *      Foundation, Inc. and its contributors.
   50  * 4. Neither the name of The NetBSD Foundation nor the names of its
   51  *    contributors may be used to endorse or promote products derived
   52  *    from this software without specific prior written permission.
   53  *
   54  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   55  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   56  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   57  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   58  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   59  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   60  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   61  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   62  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   63  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   64  * POSSIBILITY OF SUCH DAMAGE.
   65  */
   66 
   67 #include <sys/cdefs.h>
   68 __FBSDID("$FreeBSD$");
   69 
   70 #include <sys/param.h>
   71 #include <sys/systm.h>
   72 #include <sys/bus.h>
   73 #include <sys/kernel.h>
   74 #include <sys/module.h>
   75 #include <sys/resource.h>
   76 
   77 #include <dev/ofw/ofw_bus.h>
   78 #include <dev/ofw/openfirm.h>
   79 #include <machine/bus.h>
   80 #include <machine/resource.h>
   81 #include <sys/rman.h>
   82 
   83 #include <cam/cam.h>
   84 #include <cam/cam_ccb.h>
   85 #include <cam/scsi/scsi_all.h>
   86 
   87 #include <sparc64/sbus/lsi64854reg.h>
   88 #include <sparc64/sbus/lsi64854var.h>
   89 #include <sparc64/sbus/sbusvar.h>
   90 
   91 #include <dev/esp/ncr53c9xreg.h>
   92 #include <dev/esp/ncr53c9xvar.h>
   93 
   94 /* #define ESP_SBUS_DEBUG */
   95 
   96 struct esp_softc {
   97         struct ncr53c9x_softc   sc_ncr53c9x;    /* glue to MI code */
   98         struct device           *sc_dev;
   99 
  100         int                     sc_rid;
  101         struct resource         *sc_res;
  102         bus_space_handle_t      sc_regh;
  103         bus_space_tag_t         sc_regt;
  104 
  105         int                     sc_irqrid;
  106         struct resource         *sc_irqres;
  107         void                    *sc_irq;
  108 
  109         struct lsi64854_softc   *sc_dma;        /* pointer to my DMA */
  110 };
  111 
  112 static devclass_t       esp_devclass;
  113 
  114 static int      esp_probe(device_t);
  115 static int      esp_dma_attach(device_t);
  116 static int      esp_dma_detach(device_t);
  117 static int      esp_sbus_attach(device_t);
  118 static int      esp_sbus_detach(device_t);
  119 static int      esp_suspend(device_t);
  120 static int      esp_resume(device_t);
  121 
  122 static device_method_t esp_dma_methods[] = {
  123         DEVMETHOD(device_probe,         esp_probe),
  124         DEVMETHOD(device_attach,        esp_dma_attach),
  125         DEVMETHOD(device_detach,        esp_dma_detach),
  126         DEVMETHOD(device_suspend,       esp_suspend),
  127         DEVMETHOD(device_resume,        esp_resume),
  128         {0, 0}
  129 };
  130 
  131 static driver_t esp_dma_driver = {
  132         "esp",
  133         esp_dma_methods,
  134         sizeof(struct esp_softc)
  135 };
  136 
  137 DRIVER_MODULE(esp, dma, esp_dma_driver, esp_devclass, 0, 0);
  138 MODULE_DEPEND(esp, dma, 1, 1, 1);
  139 
  140 static device_method_t esp_sbus_methods[] = {
  141         DEVMETHOD(device_probe,         esp_probe),
  142         DEVMETHOD(device_attach,        esp_sbus_attach),
  143         DEVMETHOD(device_detach,        esp_sbus_detach),
  144         DEVMETHOD(device_suspend,       esp_suspend),
  145         DEVMETHOD(device_resume,        esp_resume),
  146         {0, 0}
  147 };
  148 
  149 static driver_t esp_sbus_driver = {
  150         "esp",
  151         esp_sbus_methods,
  152         sizeof(struct esp_softc)
  153 };
  154 
  155 DRIVER_MODULE(esp, sbus, esp_sbus_driver, esp_devclass, 0, 0);
  156 MODULE_DEPEND(esp, sbus, 1, 1, 1);
  157 
  158 MODULE_DEPEND(esp, cam, 1, 1, 1);
  159 
  160 /*
  161  * Functions and the switch for the MI code
  162  */
  163 static u_char   esp_read_reg(struct ncr53c9x_softc *sc, int reg);
  164 static void     esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v);
  165 static int      esp_dma_isintr(struct ncr53c9x_softc *sc);
  166 static void     esp_dma_reset(struct ncr53c9x_softc *sc);
  167 static int      esp_dma_intr(struct ncr53c9x_softc *sc);
  168 static int      esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr,
  169                     size_t *len, int datain, size_t *dmasize);
  170 static void     esp_dma_go(struct ncr53c9x_softc *sc);
  171 static void     esp_dma_stop(struct ncr53c9x_softc *sc);
  172 static int      esp_dma_isactive(struct ncr53c9x_softc *sc);
  173 static int      espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep);
  174 
  175 static struct ncr53c9x_glue esp_sbus_glue = {
  176         esp_read_reg,
  177         esp_write_reg,
  178         esp_dma_isintr,
  179         esp_dma_reset,
  180         esp_dma_intr,
  181         esp_dma_setup,
  182         esp_dma_go,
  183         esp_dma_stop,
  184         esp_dma_isactive,
  185         NULL,                   /* gl_clear_latched_intr */
  186 };
  187 
  188 static int
  189 esp_probe(device_t dev)
  190 {
  191         const char *name;
  192 
  193         name = ofw_bus_get_name(dev);
  194         if (strcmp("SUNW,fas", name) == 0) {
  195                 device_set_desc(dev, "Sun FAS366 Fast-Wide SCSI");
  196                 return (BUS_PROBE_DEFAULT);
  197         } else if (strcmp("esp", name) == 0) {
  198                 device_set_desc(dev, "Sun ESP SCSI/Sun FAS Fast-SCSI");
  199                 return (BUS_PROBE_DEFAULT);
  200         }
  201 
  202         return (ENXIO);
  203 }
  204 
  205 static int
  206 esp_sbus_attach(device_t dev)
  207 {
  208         struct esp_softc *esc;
  209         struct ncr53c9x_softc *sc;
  210         struct lsi64854_softc *lsc;
  211         device_t *children;
  212         const char *name;
  213         phandle_t node;
  214         int burst, error, i, nchildren, slot;
  215 
  216         esc = device_get_softc(dev);
  217         bzero(esc, sizeof(struct esp_softc));
  218         sc = &esc->sc_ncr53c9x;
  219 
  220         lsc = NULL;
  221         esc->sc_dev = dev;
  222         name = ofw_bus_get_name(dev);
  223         node = ofw_bus_get_node(dev);
  224         if (OF_getprop(node, "initiator-id", &sc->sc_id,
  225             sizeof(sc->sc_id)) == -1)
  226                 sc->sc_id = 7;
  227         sc->sc_freq = sbus_get_clockfreq(dev);
  228 
  229 #ifdef ESP_SBUS_DEBUG
  230         device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
  231             sc->sc_freq);
  232 #endif
  233 
  234         if (strcmp(name, "SUNW,fas") == 0) {
  235                 /*
  236                  * Allocate space for DMA, in SUNW,fas there are no
  237                  * separate DMA devices.
  238                  */
  239                 lsc = malloc(sizeof (struct lsi64854_softc), M_DEVBUF,
  240                     M_NOWAIT | M_ZERO);
  241                 if (lsc == NULL) {
  242                         device_printf(dev, "out of memory (lsi64854_softc)\n");
  243                         return (ENOMEM);
  244                 }
  245                 esc->sc_dma = lsc;
  246 
  247                 /*
  248                  * SUNW,fas have 2 register spaces: DMA (lsi64854) and
  249                  * SCSI core (ncr53c9x).
  250                  */
  251 
  252                 /* Allocate DMA registers. */
  253                 lsc->sc_rid = 0;
  254                 if ((lsc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  255                     &lsc->sc_rid, RF_ACTIVE)) == NULL) {
  256                         device_printf(dev, "cannot allocate DMA registers\n");
  257                         error = ENXIO;
  258                         goto fail_sbus_lsc;
  259                 }
  260                 lsc->sc_regt = rman_get_bustag(lsc->sc_res);
  261                 lsc->sc_regh = rman_get_bushandle(lsc->sc_res);
  262 
  263                 /* Create a parent DMA tag based on this bus. */
  264                 error = bus_dma_tag_create(
  265                     NULL,                       /* parent */
  266                     PAGE_SIZE, 0,               /* alignment, boundary */
  267                     BUS_SPACE_MAXADDR,          /* lowaddr */
  268                     BUS_SPACE_MAXADDR,          /* highaddr */
  269                     NULL, NULL,                 /* filter, filterarg */
  270                     BUS_SPACE_MAXSIZE_32BIT,    /* maxsize */
  271                     0,                          /* nsegments */
  272                     BUS_SPACE_MAXSIZE_32BIT,    /* maxsegsize */
  273                     0,                          /* flags */
  274                     NULL, NULL,                 /* no locking */
  275                     &lsc->sc_parent_dmat);
  276                 if (error != 0) {
  277                         device_printf(dev, "cannot allocate parent DMA tag\n");
  278                         goto fail_sbus_lres;
  279                 }
  280                 burst = sbus_get_burstsz(dev);
  281 
  282 #ifdef ESP_SBUS_DEBUG
  283                 printf("%s: burst 0x%x\n", __func__, burst);
  284 #endif
  285 
  286                 lsc->sc_burst = (burst & SBUS_BURST_32) ? 32 :
  287                     (burst & SBUS_BURST_16) ? 16 : 0;
  288 
  289                 lsc->sc_channel = L64854_CHANNEL_SCSI;
  290                 lsc->sc_client = sc;
  291                 lsc->sc_dev = dev;
  292 
  293                 error = lsi64854_attach(lsc);
  294                 if (error != 0) {
  295                         device_printf(dev, "lsi64854_attach failed\n");
  296                         goto fail_sbus_lpdma;
  297                 }
  298 
  299                 /*
  300                  * Allocate SCSI core registers.
  301                  */
  302                 esc->sc_rid = 1;
  303                 if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  304                     &esc->sc_rid, RF_ACTIVE)) == NULL) {
  305                         device_printf(dev,
  306                             "cannot allocate SCSI core registers\n");
  307                         error = ENXIO;
  308                         goto fail_sbus_lsi;
  309                 }
  310                 esc->sc_regt = rman_get_bustag(esc->sc_res);
  311                 esc->sc_regh = rman_get_bushandle(esc->sc_res);
  312         } else {
  313                 /*
  314                  * Search accompanying DMA engine.  It should have been
  315                  * already attached otherwise there isn't much we can do.
  316                  */
  317                 if (device_get_children(device_get_parent(dev), &children,
  318                     &nchildren) != 0) {
  319                         device_printf(dev, "cannot determine siblings\n");
  320                         return (ENXIO);
  321                 }
  322                 slot = sbus_get_slot(dev);
  323                 for (i = 0; i < nchildren; i++) {
  324                         if (device_is_attached(children[i]) &&
  325                             sbus_get_slot(children[i]) == slot &&
  326                             strcmp(ofw_bus_get_name(children[i]), "dma") == 0) {
  327                                 /* XXX hackery */
  328                                 esc->sc_dma = (struct lsi64854_softc *)
  329                                     device_get_softc(children[i]);
  330                                 break;
  331                         }
  332                 }
  333                 free(children, M_TEMP);
  334                 if (esc->sc_dma == NULL) {
  335                         device_printf(dev, "cannot find DMA engine\n");
  336                         return (ENXIO);
  337                 }
  338                 esc->sc_dma->sc_client = sc;
  339 
  340                 /*
  341                  * Allocate SCSI core registers.
  342                  */
  343                 esc->sc_rid = 0;
  344                 if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  345                     &esc->sc_rid, RF_ACTIVE)) == NULL) {
  346                         device_printf(dev,
  347                             "cannot allocate SCSI core registers\n");
  348                         return (ENXIO);
  349                 }
  350                 esc->sc_regt = rman_get_bustag(esc->sc_res);
  351                 esc->sc_regh = rman_get_bushandle(esc->sc_res);
  352         }
  353 
  354         error = espattach(esc, &esp_sbus_glue);
  355         if (error != 0) {
  356                 device_printf(dev, "espattach failed\n");
  357                 goto fail_sbus_eres;
  358         }
  359 
  360         return (0);
  361 
  362  fail_sbus_eres:
  363         bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
  364         if (strcmp(name, "SUNW,fas") != 0)
  365                 return (error);
  366  fail_sbus_lsi:
  367         lsi64854_detach(lsc);
  368  fail_sbus_lpdma:
  369         bus_dma_tag_destroy(lsc->sc_parent_dmat);
  370  fail_sbus_lres:
  371         bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
  372  fail_sbus_lsc:
  373         free(lsc, M_DEVBUF);
  374         return (error);
  375 }
  376 
  377 static int
  378 esp_sbus_detach(device_t dev)
  379 {
  380         struct esp_softc *esc;
  381         struct ncr53c9x_softc *sc;
  382         struct lsi64854_softc *lsc;
  383         int error;
  384 
  385         esc = device_get_softc(dev);
  386         sc = &esc->sc_ncr53c9x;
  387         lsc = esc->sc_dma;
  388 
  389         bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
  390         error = ncr53c9x_detach(sc);
  391         if (error != 0)
  392                 return (error);
  393         bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
  394             esc->sc_irqres);
  395         bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
  396         if (strcmp(ofw_bus_get_name(dev), "SUNW,fas") != 0)
  397                 return (0);
  398         error = lsi64854_detach(lsc);
  399         if (error != 0)
  400                 return (error);
  401         bus_dma_tag_destroy(lsc->sc_parent_dmat);
  402         bus_release_resource(dev, SYS_RES_MEMORY, lsc->sc_rid, lsc->sc_res);
  403         free(lsc, M_DEVBUF);
  404 
  405         return (0);
  406 }
  407 
  408 static int
  409 esp_dma_attach(device_t dev)
  410 {
  411         struct esp_softc *esc;
  412         struct ncr53c9x_softc *sc;
  413         phandle_t node;
  414         int error;
  415 
  416         esc = device_get_softc(dev);
  417         bzero(esc, sizeof(struct esp_softc));
  418         sc = &esc->sc_ncr53c9x;
  419 
  420         esc->sc_dev = dev;
  421         node = ofw_bus_get_node(dev);
  422         if (OF_getprop(node, "initiator-id", &sc->sc_id,
  423             sizeof(sc->sc_id)) == -1)
  424                 sc->sc_id = 7;
  425         if (OF_getprop(node, "clock-frequency", &sc->sc_freq,
  426             sizeof(sc->sc_freq)) == -1) {
  427                 printf("failed to query OFW for clock-frequency\n");
  428                 return (ENXIO);
  429         }
  430 
  431 #ifdef ESP_SBUS_DEBUG
  432         device_printf(dev, "%s: sc_id %d, freq %d\n", __func__, sc->sc_id,
  433             sc->sc_freq);
  434 #endif
  435 
  436         /* XXX hackery */
  437         esc->sc_dma = (struct lsi64854_softc *)
  438             device_get_softc(device_get_parent(dev));
  439         esc->sc_dma->sc_client = sc;
  440 
  441         /*
  442          * Allocate SCSI core registers.
  443          */
  444         esc->sc_rid = 0;
  445         if ((esc->sc_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  446             &esc->sc_rid, RF_ACTIVE)) == NULL) {
  447                 device_printf(dev, "cannot allocate SCSI core registers\n");
  448                 return (ENXIO);
  449         }
  450         esc->sc_regt = rman_get_bustag(esc->sc_res);
  451         esc->sc_regh = rman_get_bushandle(esc->sc_res);
  452 
  453         error = espattach(esc, &esp_sbus_glue);
  454         if (error != 0) {
  455                 device_printf(dev, "espattach failed\n");
  456                 goto fail_dma_eres;
  457         }
  458 
  459         return (0);
  460 
  461  fail_dma_eres:
  462         bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
  463         return (error);
  464 }
  465 
  466 static int
  467 esp_dma_detach(device_t dev)
  468 {
  469         struct esp_softc *esc;
  470         struct ncr53c9x_softc *sc;
  471         int error;
  472 
  473         esc = device_get_softc(dev);
  474         sc = &esc->sc_ncr53c9x;
  475 
  476         bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
  477         error = ncr53c9x_detach(sc);
  478         if (error != 0)
  479                 return (error);
  480         bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
  481             esc->sc_irqres);
  482         bus_release_resource(dev, SYS_RES_MEMORY, esc->sc_rid, esc->sc_res);
  483 
  484         return (0);
  485 }
  486 
  487 static int
  488 esp_suspend(device_t dev)
  489 {
  490 
  491         return (ENXIO);
  492 }
  493 
  494 static int
  495 esp_resume(device_t dev)
  496 {
  497 
  498         return (ENXIO);
  499 }
  500 
  501 static int
  502 espattach(struct esp_softc *esc, struct ncr53c9x_glue *gluep)
  503 {
  504         struct ncr53c9x_softc *sc = &esc->sc_ncr53c9x;
  505         unsigned int uid = 0;
  506         int error;
  507 
  508         /*
  509          * The `ESC' DMA chip must be reset before we can access
  510          * the ESP registers.
  511          */
  512         if (esc->sc_dma->sc_rev == DMAREV_ESC)
  513                 DMA_RESET(esc->sc_dma);
  514 
  515         /*
  516          * Set up glue for MI code early; we use some of it here.
  517          */
  518         sc->sc_glue = gluep;
  519 
  520         /* gimme MHz */
  521         sc->sc_freq /= 1000000;
  522 
  523         /*
  524          * XXX More of this should be in ncr53c9x_attach(), but
  525          * XXX should we really poke around the chip that much in
  526          * XXX the MI code?  Think about this more...
  527          */
  528 
  529         /*
  530          * Read the part-unique ID code of the SCSI chip.  The contained
  531          * value is only valid if all of the following conditions are met:
  532          * - After power-up or chip reset.
  533          * - Before any value is written to this register.
  534          * - The NCRCFG2_FE bit is set.
  535          * - A (NCRCMD_NOP | NCRCMD_DMA) command has been issued.
  536          */
  537         NCRCMD(sc, NCRCMD_RSTCHIP);
  538         NCRCMD(sc, NCRCMD_NOP);
  539         sc->sc_cfg2 = NCRCFG2_FE;
  540         NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
  541         NCRCMD(sc, NCRCMD_NOP | NCRCMD_DMA);
  542         uid = NCR_READ_REG(sc, NCR_UID);
  543 
  544         /*
  545          * It is necessary to try to load the 2nd config register here,
  546          * to find out what rev the esp chip is, else the ncr53c9x_reset
  547          * will not set up the defaults correctly.
  548          */
  549         sc->sc_cfg1 = sc->sc_id | NCRCFG1_PARENB;
  550         NCR_WRITE_REG(sc, NCR_CFG1, sc->sc_cfg1);
  551         sc->sc_cfg2 = 0;
  552         NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
  553         sc->sc_cfg2 = NCRCFG2_SCSI2 | NCRCFG2_RPE;
  554         NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
  555 
  556         if ((NCR_READ_REG(sc, NCR_CFG2) & ~NCRCFG2_RSVD) !=
  557             (NCRCFG2_SCSI2 | NCRCFG2_RPE)) {
  558                 sc->sc_rev = NCR_VARIANT_ESP100;
  559         } else {
  560                 sc->sc_cfg2 = NCRCFG2_SCSI2;
  561                 NCR_WRITE_REG(sc, NCR_CFG2, sc->sc_cfg2);
  562                 sc->sc_cfg3 = 0;
  563                 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
  564                 sc->sc_cfg3 = (NCRCFG3_CDB | NCRCFG3_FCLK);
  565                 NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
  566                 if (NCR_READ_REG(sc, NCR_CFG3) !=
  567                     (NCRCFG3_CDB | NCRCFG3_FCLK)) {
  568                         sc->sc_rev = NCR_VARIANT_ESP100A;
  569                 } else {
  570                         /* NCRCFG2_FE enables > 64K transfers. */
  571                         sc->sc_cfg2 |= NCRCFG2_FE;
  572                         sc->sc_cfg3 = 0;
  573                         NCR_WRITE_REG(sc, NCR_CFG3, sc->sc_cfg3);
  574                         if (sc->sc_freq <= 25)
  575                                 sc->sc_rev = NCR_VARIANT_ESP200;
  576                         else {
  577                                 switch ((uid & 0xf8) >> 3) {
  578                                 case 0x00:
  579                                         sc->sc_rev = NCR_VARIANT_FAS100A;
  580                                         break;
  581 
  582                                 case 0x02:
  583                                         if ((uid & 0x07) == 0x02)
  584                                                 sc->sc_rev = NCR_VARIANT_FAS216;
  585                                         else
  586                                                 sc->sc_rev = NCR_VARIANT_FAS236;
  587                                         break;
  588 
  589                                 case 0x0a:
  590                                         sc->sc_rev = NCR_VARIANT_FAS366;
  591                                         break;
  592 
  593                                 default:
  594                                         /*
  595                                          * We could just treat unknown chips
  596                                          * as ESP200 but then we would most
  597                                          * likely drive them out of specs.
  598                                          */
  599                                         device_printf(esc->sc_dev,
  600                                             "Unknown chip\n");
  601                                         return (ENXIO);
  602                                 }
  603                         }
  604                 }
  605         }
  606 
  607 #ifdef ESP_SBUS_DEBUG
  608         printf("%s: revision %d, uid 0x%x\n", __func__, sc->sc_rev, uid);
  609 #endif
  610 
  611         /*
  612          * XXX minsync and maxxfer _should_ be set up in MI code,
  613          * XXX but it appears to have some dependency on what sort
  614          * XXX of DMA we're hooked up to, etc.
  615          */
  616 
  617         /*
  618          * This is the value used to start sync negotiations
  619          * Note that the NCR register "SYNCTP" is programmed
  620          * in "clocks per byte", and has a minimum value of 4.
  621          * The SCSI period used in negotiation is one-fourth
  622          * of the time (in nanoseconds) needed to transfer one byte.
  623          * Since the chip's clock is given in MHz, we have the following
  624          * formula: 4 * period = (1000 / freq) * 4
  625          */
  626         sc->sc_minsync = 1000 / sc->sc_freq;
  627 
  628         sc->sc_maxoffset = 15;
  629         sc->sc_extended_geom = 1;
  630 
  631         /*
  632          * Alas, we must now modify the value a bit, because it's
  633          * only valid when can switch on FASTCLK and FASTSCSI bits
  634          * in config register 3...
  635          */
  636         switch (sc->sc_rev) {
  637         case NCR_VARIANT_ESP100:
  638                 sc->sc_maxwidth = 0;
  639                 sc->sc_maxxfer = 64 * 1024;
  640                 sc->sc_minsync = 0;     /* No synch on old chip? */
  641                 break;
  642 
  643         case NCR_VARIANT_ESP100A:
  644                 sc->sc_maxwidth = 0;
  645                 sc->sc_maxxfer = 64 * 1024;
  646                 /* Min clocks/byte is 5 */
  647                 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
  648                 break;
  649 
  650         case NCR_VARIANT_ESP200:
  651                 sc->sc_maxwidth = 0;
  652                 sc->sc_maxxfer = 16 * 1024 * 1024;
  653                 /* Min clocks/byte is 5 */
  654                 sc->sc_minsync = ncr53c9x_cpb2stp(sc, 5);
  655                 break;
  656 
  657         case NCR_VARIANT_FAS100A:
  658         case NCR_VARIANT_FAS216:
  659         case NCR_VARIANT_FAS236:
  660                 /*
  661                  * The onboard SCSI chips in Sun Ultra 1 are actually
  662                  * documented to be NCR53C9X which use NCRCFG3_FCLK and
  663                  * NCRCFG3_FSCSI.  BSD/OS however probes these chips as
  664                  * FAS100A and uses NCRF9XCFG3_FCLK and NCRF9XCFG3_FSCSI
  665                  * instead which seems to be correct as otherwise sync
  666                  * negotiation just doesn't work.  Using NCRF9XCFG3_FCLK
  667                  * and NCRF9XCFG3_FSCSI with these chips in fact also
  668                  * yields Fast-SCSI speed.
  669                  */
  670                 sc->sc_features = NCR_F_FASTSCSI;
  671                 sc->sc_cfg3 = NCRF9XCFG3_FCLK;
  672                 sc->sc_cfg3_fscsi = NCRF9XCFG3_FSCSI;
  673                 sc->sc_maxwidth = 0;
  674                 sc->sc_maxxfer = 16 * 1024 * 1024;
  675                 break;
  676 
  677         case NCR_VARIANT_FAS366:
  678                 sc->sc_maxwidth = 1;
  679                 sc->sc_maxxfer = 16 * 1024 * 1024;
  680                 break;
  681         }
  682 
  683         /* Limit minsync due to unsolved performance issues. */
  684         sc->sc_maxsync = sc->sc_minsync;
  685 
  686         /* Establish interrupt channel. */
  687         esc->sc_irqrid = 0;
  688         if ((esc->sc_irqres = bus_alloc_resource_any(esc->sc_dev, SYS_RES_IRQ,
  689             &esc->sc_irqrid, RF_SHAREABLE|RF_ACTIVE)) == NULL) {
  690                 device_printf(esc->sc_dev, "cannot allocate interrupt\n");
  691                 return (ENXIO);
  692         }
  693         if (bus_setup_intr(esc->sc_dev, esc->sc_irqres,
  694             INTR_TYPE_BIO|INTR_MPSAFE, ncr53c9x_intr, sc, &esc->sc_irq)) {
  695                 device_printf(esc->sc_dev, "cannot set up interrupt\n");
  696                 error = ENXIO;
  697                 goto fail_ires;
  698         }
  699 
  700         /* Turn on target selection using the `DMA' method. */
  701         if (sc->sc_rev != NCR_VARIANT_FAS366)
  702                 sc->sc_features |= NCR_F_DMASELECT;
  703 
  704         /* Do the common parts of attachment. */
  705         sc->sc_dev = esc->sc_dev;
  706         error = ncr53c9x_attach(sc);
  707         if (error != 0) {
  708                 device_printf(esc->sc_dev, "ncr53c9x_attach failed\n");
  709                 goto fail_intr;
  710         }
  711 
  712         return (0);
  713 
  714  fail_intr:
  715         bus_teardown_intr(esc->sc_dev, esc->sc_irqres, esc->sc_irq);
  716  fail_ires:
  717         bus_release_resource(esc->sc_dev, SYS_RES_IRQ, esc->sc_irqrid,
  718             esc->sc_irqres);
  719         return (error);
  720 }
  721 
  722 /*
  723  * Glue functions
  724  */
  725 
  726 #ifdef ESP_SBUS_DEBUG
  727 int esp_sbus_debug = 0;
  728 
  729 static struct {
  730         char *r_name;
  731         int   r_flag;
  732 } esp__read_regnames [] = {
  733         { "TCL", 0},                    /* 0/00 */
  734         { "TCM", 0},                    /* 1/04 */
  735         { "FIFO", 0},                   /* 2/08 */
  736         { "CMD", 0},                    /* 3/0c */
  737         { "STAT", 0},                   /* 4/10 */
  738         { "INTR", 0},                   /* 5/14 */
  739         { "STEP", 0},                   /* 6/18 */
  740         { "FFLAGS", 1},                 /* 7/1c */
  741         { "CFG1", 1},                   /* 8/20 */
  742         { "STAT2", 0},                  /* 9/24 */
  743         { "CFG4", 1},                   /* a/28 */
  744         { "CFG2", 1},                   /* b/2c */
  745         { "CFG3", 1},                   /* c/30 */
  746         { "-none", 1},                  /* d/34 */
  747         { "TCH", 1},                    /* e/38 */
  748         { "TCX", 1},                    /* f/3c */
  749 };
  750 
  751 static struct {
  752         char *r_name;
  753         int   r_flag;
  754 } esp__write_regnames[] = {
  755         { "TCL", 1},                    /* 0/00 */
  756         { "TCM", 1},                    /* 1/04 */
  757         { "FIFO", 0},                   /* 2/08 */
  758         { "CMD", 0},                    /* 3/0c */
  759         { "SELID", 1},                  /* 4/10 */
  760         { "TIMEOUT", 1},                /* 5/14 */
  761         { "SYNCTP", 1},                 /* 6/18 */
  762         { "SYNCOFF", 1},                /* 7/1c */
  763         { "CFG1", 1},                   /* 8/20 */
  764         { "CCF", 1},                    /* 9/24 */
  765         { "TEST", 1},                   /* a/28 */
  766         { "CFG2", 1},                   /* b/2c */
  767         { "CFG3", 1},                   /* c/30 */
  768         { "-none", 1},                  /* d/34 */
  769         { "TCH", 1},                    /* e/38 */
  770         { "TCX", 1},                    /* f/3c */
  771 };
  772 #endif
  773 
  774 static u_char
  775 esp_read_reg(struct ncr53c9x_softc *sc, int reg)
  776 {
  777         struct esp_softc *esc = (struct esp_softc *)sc;
  778         u_char v;
  779 
  780         v = bus_space_read_1(esc->sc_regt, esc->sc_regh, reg * 4);
  781 #ifdef ESP_SBUS_DEBUG
  782         if (esp_sbus_debug && (reg < 0x10) && esp__read_regnames[reg].r_flag)
  783                 printf("RD:%x <%s> %x\n", reg * 4,
  784                     ((unsigned)reg < 0x10) ? esp__read_regnames[reg].r_name : "<***>", v);
  785 #endif
  786         return v;
  787 }
  788 
  789 static void
  790 esp_write_reg(struct ncr53c9x_softc *sc, int reg, u_char v)
  791 {
  792         struct esp_softc *esc = (struct esp_softc *)sc;
  793 
  794 #ifdef ESP_SBUS_DEBUG
  795         if (esp_sbus_debug && (reg < 0x10) && esp__write_regnames[reg].r_flag)
  796                 printf("WR:%x <%s> %x\n", reg * 4,
  797                     ((unsigned)reg < 0x10) ? esp__write_regnames[reg].r_name : "<***>", v);
  798 #endif
  799         bus_space_write_1(esc->sc_regt, esc->sc_regh, reg * 4, v);
  800 }
  801 
  802 static int
  803 esp_dma_isintr(struct ncr53c9x_softc *sc)
  804 {
  805         struct esp_softc *esc = (struct esp_softc *)sc;
  806 
  807         return (DMA_ISINTR(esc->sc_dma));
  808 }
  809 
  810 static void
  811 esp_dma_reset(struct ncr53c9x_softc *sc)
  812 {
  813         struct esp_softc *esc = (struct esp_softc *)sc;
  814 
  815         DMA_RESET(esc->sc_dma);
  816 }
  817 
  818 static int
  819 esp_dma_intr(struct ncr53c9x_softc *sc)
  820 {
  821         struct esp_softc *esc = (struct esp_softc *)sc;
  822 
  823         return (DMA_INTR(esc->sc_dma));
  824 }
  825 
  826 static int
  827 esp_dma_setup(struct ncr53c9x_softc *sc, caddr_t *addr, size_t *len,
  828               int datain, size_t *dmasize)
  829 {
  830         struct esp_softc *esc = (struct esp_softc *)sc;
  831 
  832         return (DMA_SETUP(esc->sc_dma, addr, len, datain, dmasize));
  833 }
  834 
  835 static void
  836 esp_dma_go(struct ncr53c9x_softc *sc)
  837 {
  838         struct esp_softc *esc = (struct esp_softc *)sc;
  839 
  840         DMA_GO(esc->sc_dma);
  841 }
  842 
  843 static void
  844 esp_dma_stop(struct ncr53c9x_softc *sc)
  845 {
  846         struct esp_softc *esc = (struct esp_softc *)sc;
  847 
  848         L64854_SCSR(esc->sc_dma, L64854_GCSR(esc->sc_dma) & ~D_EN_DMA);
  849 }
  850 
  851 static int
  852 esp_dma_isactive(struct ncr53c9x_softc *sc)
  853 {
  854         struct esp_softc *esc = (struct esp_softc *)sc;
  855 
  856         return (DMA_ISACTIVE(esc->sc_dma));
  857 }

Cache object: bba1ada094893e8c52a61777cd8dc7cd


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