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

Cache object: 951b42a939ed217795d2de4a8de9e810


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