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/ic/aac.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: aac.c,v 1.29.2.2 2008/10/03 09:12:16 jdc Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2002, 2007 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Andrew Doran.
    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  * Copyright (c) 2001 Scott Long
   41  * Copyright (c) 2001 Adaptec, Inc.
   42  * Copyright (c) 2000 Michael Smith
   43  * Copyright (c) 2000 BSDi
   44  * Copyright (c) 2000 Niklas Hallqvist
   45  * All rights reserved.
   46  *
   47  * Redistribution and use in source and binary forms, with or without
   48  * modification, are permitted provided that the following conditions
   49  * are met:
   50  * 1. Redistributions of source code must retain the above copyright
   51  *    notice, this list of conditions and the following disclaimer.
   52  * 2. Redistributions in binary form must reproduce the above copyright
   53  *    notice, this list of conditions and the following disclaimer in the
   54  *    documentation and/or other materials provided with the distribution.
   55  *
   56  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   57  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   58  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   59  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   60  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   61  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   62  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   63  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   64  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   65  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   66  * SUCH DAMAGE.
   67  */
   68 
   69 /*
   70  * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
   71  *
   72  * TODO:
   73  *
   74  * o Management interface.
   75  * o Look again at some of the portability issues.
   76  * o Handle various AIFs (e.g., notification that a container is going away).
   77  */
   78 
   79 #include <sys/cdefs.h>
   80 __KERNEL_RCSID(0, "$NetBSD: aac.c,v 1.29.2.2 2008/10/03 09:12:16 jdc Exp $");
   81 
   82 #include <sys/param.h>
   83 #include <sys/systm.h>
   84 #include <sys/buf.h>
   85 #include <sys/device.h>
   86 #include <sys/kernel.h>
   87 #include <sys/malloc.h>
   88 
   89 #include <machine/bus.h>
   90 
   91 #include <uvm/uvm_extern.h>
   92 
   93 #include <dev/ic/aacreg.h>
   94 #include <dev/ic/aacvar.h>
   95 #include <dev/ic/aac_tables.h>
   96 
   97 #include "locators.h"
   98 
   99 static int      aac_new_intr(void *);
  100 static int      aac_alloc_commands(struct aac_softc *);
  101 #ifdef notyet
  102 static void     aac_free_commands(struct aac_softc *);
  103 #endif
  104 static int      aac_check_firmware(struct aac_softc *);
  105 static void     aac_describe_controller(struct aac_softc *);
  106 static int      aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
  107                                 struct aac_fib **);
  108 static int      aac_enqueue_fib(struct aac_softc *, int, struct aac_ccb *);
  109 static int      aac_enqueue_response(struct aac_softc *, int, struct aac_fib *);
  110 static void     aac_host_command(struct aac_softc *);
  111 static void     aac_host_response(struct aac_softc *);
  112 static int      aac_init(struct aac_softc *);
  113 static int      aac_print(void *, const char *);
  114 static void     aac_shutdown(void *);
  115 static void     aac_startup(struct aac_softc *);
  116 static int      aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
  117                                  u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
  118 static int      aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
  119                              u_int16_t, void *, u_int16_t *);
  120 
  121 #ifdef AAC_DEBUG
  122 static void     aac_print_fib(struct aac_softc *, struct aac_fib *, const char *);
  123 #endif
  124 
  125 /*
  126  * Adapter-space FIB queue manipulation.
  127  *
  128  * Note that the queue implementation here is a little funky; neither the PI or
  129  * CI will ever be zero.  This behaviour is a controller feature.
  130  */
  131 static struct {
  132         int     size;
  133         int     notify;
  134 } const aac_qinfo[] = {
  135         { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
  136         { AAC_HOST_HIGH_CMD_ENTRIES, 0 },
  137         { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
  138         { AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
  139         { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
  140         { AAC_HOST_HIGH_RESP_ENTRIES, 0 },
  141         { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
  142         { AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
  143 };
  144 
  145 #ifdef AAC_DEBUG
  146 int     aac_debug = AAC_DEBUG;
  147 #endif
  148 
  149 MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for aac(4)");
  150 
  151 static void     *aac_sdh;
  152 
  153 extern struct   cfdriver aac_cd;
  154 
  155 int
  156 aac_attach(struct aac_softc *sc)
  157 {
  158         struct aac_attach_args aaca;
  159         int i, rv;
  160         int locs[AACCF_NLOCS];
  161 
  162         SIMPLEQ_INIT(&sc->sc_ccb_free);
  163         SIMPLEQ_INIT(&sc->sc_ccb_queue);
  164         SIMPLEQ_INIT(&sc->sc_ccb_complete);
  165 
  166         /*
  167          * Disable interrupts before we do anything.
  168          */
  169         AAC_MASK_INTERRUPTS(sc);
  170 
  171         /*
  172          * Initialise the adapter.
  173          */
  174         if (aac_check_firmware(sc))
  175                 return (EINVAL);
  176 
  177         if ((rv = aac_init(sc)) != 0)
  178                 return (rv);
  179 
  180         if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
  181                 rv = sc->sc_intr_set(sc, aac_new_intr, sc);
  182                 if (rv)
  183                         return (rv);
  184         }
  185 
  186         aac_startup(sc);
  187 
  188         /*
  189          * Print a little information about the controller.
  190          */
  191         aac_describe_controller(sc);
  192 
  193         /*
  194          * Attach devices.
  195          */
  196         for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
  197                 if (!sc->sc_hdr[i].hd_present)
  198                         continue;
  199                 aaca.aaca_unit = i;
  200 
  201                 locs[AACCF_UNIT] = i;
  202 
  203                 config_found_sm_loc(&sc->sc_dv, "aac", locs, &aaca,
  204                                     aac_print, config_stdsubmatch);
  205         }
  206 
  207         /*
  208          * Enable interrupts, and register our shutdown hook.
  209          */
  210         sc->sc_flags |= AAC_ONLINE;
  211         AAC_UNMASK_INTERRUPTS(sc);
  212         if (aac_sdh != NULL)
  213                 shutdownhook_establish(aac_shutdown, NULL);
  214         return (0);
  215 }
  216 
  217 static int
  218 aac_alloc_commands(struct aac_softc *sc)
  219 {
  220         struct aac_fibmap *fm;
  221         struct aac_ccb *ac;
  222         bus_addr_t fibpa;
  223         int size, nsegs;
  224         int i, error;
  225         int state;
  226 
  227         if (sc->sc_total_fibs + sc->sc_max_fibs_alloc > sc->sc_max_fibs)
  228                 return ENOMEM;
  229 
  230         fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, M_NOWAIT|M_ZERO);
  231         if (fm == NULL)
  232                 return ENOMEM;
  233 
  234         size = sc->sc_max_fibs_alloc * sc->sc_max_fib_size;
  235 
  236         state = 0;
  237         error = bus_dmamap_create(sc->sc_dmat, size, 1, size,
  238             0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &fm->fm_fibmap);
  239         if (error != 0) {
  240                 aprint_error("%s: cannot create fibs dmamap (%d)\n",
  241                     sc->sc_dv.dv_xname, error);
  242                 goto bail_out;
  243         }
  244         state++;
  245         error = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
  246             &fm->fm_fibseg, 1, &nsegs, BUS_DMA_NOWAIT);
  247         if (error != 0) {
  248                 aprint_error("%s: can't allocate fibs structure (%d)\n",
  249                     sc->sc_dv.dv_xname, error);
  250                 goto bail_out;
  251         }
  252         state++;
  253         error = bus_dmamem_map(sc->sc_dmat, &fm->fm_fibseg, nsegs, size,
  254             (caddr_t *) &fm->fm_fibs, 0);
  255         if (error != 0) {
  256                 aprint_error("%s: can't map fibs structure (%d)\n",
  257                     sc->sc_dv.dv_xname, error);
  258                 goto bail_out;
  259         }
  260         state++;
  261         error = bus_dmamap_load(sc->sc_dmat, fm->fm_fibmap, fm->fm_fibs,
  262             size, NULL, BUS_DMA_NOWAIT);
  263         if (error != 0) {
  264                 aprint_error("%s: cannot load fibs dmamap (%d)\n",
  265                     sc->sc_dv.dv_xname, error);
  266                 goto bail_out;
  267         }
  268 
  269         fm->fm_ccbs = sc->sc_ccbs + sc->sc_total_fibs;
  270         fibpa = fm->fm_fibseg.ds_addr;
  271 
  272         memset(fm->fm_fibs, 0, size);
  273         for (i = 0; i < sc->sc_max_fibs_alloc; i++) {
  274                 ac = fm->fm_ccbs + i;
  275 
  276                 error = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER(sc),
  277                     sc->sc_max_sgs, AAC_MAX_XFER(sc), 0,
  278                     BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
  279                 if (error) {
  280                         while (--i >= 0) {
  281                                 ac = fm->fm_ccbs + i;
  282                                 bus_dmamap_destroy(sc->sc_dmat,
  283                                     ac->ac_dmamap_xfer);
  284                                 sc->sc_total_fibs--;
  285                         }
  286                         aprint_error("%s: cannot create ccb dmamap (%d)",
  287                             sc->sc_dv.dv_xname, error);
  288                         goto bail_out;
  289                 }
  290 
  291                 ac->ac_fibmap = fm;
  292                 ac->ac_fib = (struct aac_fib *)
  293                     ((char *) fm->fm_fibs + i * sc->sc_max_fib_size);
  294                 ac->ac_fibphys = fibpa + i * sc->sc_max_fib_size;
  295                 aac_ccb_free(sc, ac);
  296                 sc->sc_total_fibs++;
  297         }
  298 
  299         TAILQ_INSERT_TAIL(&sc->sc_fibmap_tqh, fm, fm_link);
  300 
  301         return 0;
  302 bail_out:
  303         if (state > 3)
  304                 bus_dmamap_unload(sc->sc_dmat, fm->fm_fibmap);
  305         if (state > 2)
  306                 bus_dmamem_unmap(sc->sc_dmat, (void *) fm->fm_fibs, size);
  307         if (state > 1)
  308                 bus_dmamem_free(sc->sc_dmat, &fm->fm_fibseg, 1);
  309 
  310         bus_dmamap_destroy(sc->sc_dmat, fm->fm_fibmap);
  311 
  312         free(fm, M_AACBUF);
  313 
  314         return error;
  315 }
  316 
  317 #ifdef notyet
  318 static void
  319 aac_free_commands(struct aac_softc *sc)
  320 {
  321 }
  322 #endif
  323 
  324 /*
  325  * Print autoconfiguration message for a sub-device.
  326  */
  327 static int
  328 aac_print(void *aux, const char *pnp)
  329 {
  330         struct aac_attach_args *aaca;
  331 
  332         aaca = aux;
  333 
  334         if (pnp != NULL)
  335                 aprint_normal("block device at %s", pnp);
  336         aprint_normal(" unit %d", aaca->aaca_unit);
  337         return (UNCONF);
  338 }
  339 
  340 /*
  341  * Look up a text description of a numeric error code and return a pointer to
  342  * same.
  343  */
  344 const char *
  345 aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
  346 {
  347         int i;
  348 
  349         for (i = 0; table[i].string != NULL; i++)
  350                 if (table[i].code == code)
  351                         return (table[i].string);
  352 
  353         return (table[i + 1].string);
  354 }
  355 
  356 /*
  357  * bitmask_snprintf(9) format string for the adapter options.
  358  */
  359 static const char *optfmt = 
  360     "\2\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
  361     "\7WINDOW4GB"
  362     "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
  363 
  364 static void
  365 aac_describe_controller(struct aac_softc *sc)
  366 {
  367         u_int8_t fmtbuf[256];
  368         u_int8_t tbuf[AAC_FIB_DATASIZE];
  369         u_int16_t bufsize;
  370         struct aac_adapter_info *info;
  371         u_int8_t arg;
  372 
  373         arg = 0;
  374         if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &tbuf,
  375             &bufsize)) {
  376                 aprint_error("%s: RequestAdapterInfo failed\n",
  377                     sc->sc_dv.dv_xname);
  378                 return;
  379         }
  380         if (bufsize != sizeof(*info)) {
  381                 aprint_error("%s: "
  382                     "RequestAdapterInfo returned wrong data size (%d != %zu)\n",
  383                     sc->sc_dv.dv_xname, bufsize, sizeof(*info));
  384                 return;
  385         }
  386         info = (struct aac_adapter_info *)&tbuf[0];
  387 
  388         aprint_normal("%s: %s at %dMHz, %dMB mem (%dMB cache), %s\n",
  389             sc->sc_dv.dv_xname,
  390             aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
  391             le32toh(info->ClockSpeed),
  392             le32toh(info->TotalMem) / (1024 * 1024),
  393             le32toh(info->BufferMem) / (1024 * 1024),
  394             aac_describe_code(aac_battery_platform,
  395                               le32toh(info->batteryPlatform)));
  396 
  397         aprint_verbose("%s: Kernel %d.%d-%d [Build %d], ",
  398             sc->sc_dv.dv_xname,
  399             info->KernelRevision.external.comp.major,
  400             info->KernelRevision.external.comp.minor,
  401             info->KernelRevision.external.comp.dash,
  402             info->KernelRevision.buildNumber);
  403 
  404         aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
  405             info->MonitorRevision.external.comp.major,
  406             info->MonitorRevision.external.comp.minor,
  407             info->MonitorRevision.external.comp.dash,
  408             info->MonitorRevision.buildNumber,
  409             ((u_int32_t)info->SerialNumber & 0xffffff));
  410 
  411         aprint_verbose("%s: Controller supports: %s\n",
  412             sc->sc_dv.dv_xname,
  413             bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf,
  414                              sizeof(fmtbuf)));
  415 
  416         /* Save the kernel revision structure for later use. */
  417         sc->sc_revision = info->KernelRevision;
  418 }
  419 
  420 /*
  421  * Retrieve the firmware version numbers.  Dell PERC2/QC cards with firmware
  422  * version 1.x are not compatible with this driver.
  423  */
  424 static int
  425 aac_check_firmware(struct aac_softc *sc)
  426 {
  427         u_int32_t major, minor, opts, atusize = 0, status = 0;
  428         u_int32_t calcsgs;
  429 
  430         if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
  431                 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
  432                     NULL)) {
  433                         aprint_error("%s: error reading firmware version\n",
  434                             sc->sc_dv.dv_xname);
  435                         return (1);
  436                 }
  437 
  438                 /* These numbers are stored as ASCII! */
  439                 major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
  440                 minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
  441                 if (major == 1) {
  442                         aprint_error(
  443                             "%s: firmware version %d.%d not supported.\n",
  444                             sc->sc_dv.dv_xname, major, minor);
  445                         return (1);
  446                 }
  447         }
  448 
  449         if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) {
  450                 if (status != AAC_SRB_STS_INVALID_REQUEST) {
  451                         aprint_error("%s: GETINFO failed, status 0x%08x\n",
  452                                      sc->sc_dv.dv_xname, status);
  453                         return (1);
  454                 }
  455         } else {
  456                 opts = AAC_GET_MAILBOX(sc, 1);
  457                 atusize = AAC_GET_MAILBOX(sc, 2);
  458                 sc->sc_supported_options = opts;
  459 
  460                 if (((opts & AAC_SUPPORTED_4GB_WINDOW) != 0) &&
  461                     ((sc->sc_quirks & AAC_QUIRK_NO4GB) == 0) )
  462                         sc->sc_quirks |= AAC_QUIRK_4GB_WINDOW;
  463 
  464                 if (((opts & AAC_SUPPORTED_SGMAP_HOST64) != 0) &&
  465                     (sizeof(bus_addr_t) > 4)) {
  466                         aprint_normal("%s: Enabling 64-bit address support\n",
  467                                       sc->sc_dv.dv_xname);
  468                         sc->sc_quirks |= AAC_QUIRK_SG_64BIT;
  469                 }
  470                 if ((opts & AAC_SUPPORTED_NEW_COMM) &&
  471                     (sc->sc_if.aif_send_command != NULL)) {
  472                         sc->sc_quirks |= AAC_QUIRK_NEW_COMM;
  473                 }
  474                 if (opts & AAC_SUPPORTED_64BIT_ARRAYSIZE)
  475                         sc->sc_quirks |= AAC_QUIRK_ARRAY_64BIT;
  476         }
  477 
  478         sc->sc_max_fibs = (sc->sc_quirks & AAC_QUIRK_256FIBS) ? 256 : 512;
  479 
  480         if (   (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
  481             && (sc->sc_regsize < atusize)) {
  482                 aprint_error("%s: Not enabling new comm i/f -- "
  483                              "atusize 0x%08x, regsize 0x%08x\n",
  484                              sc->sc_dv.dv_xname, atusize,
  485                              (u_int32_t) sc->sc_regsize);
  486                 sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM;
  487         }
  488 #if 0
  489         if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
  490                 aprint_error("%s: Not enabling new comm i/f -- "
  491                              "driver not ready yet\n",
  492                              sc->sc_dv.dv_xname);
  493                 sc->sc_quirks &= ~AAC_QUIRK_NEW_COMM;
  494         }
  495 #endif
  496 
  497         sc->sc_max_fib_size = sizeof(struct aac_fib);
  498         sc->sc_max_sectors = 128;       /* 64KB */
  499         if (sc->sc_quirks & AAC_QUIRK_SG_64BIT)
  500                 sc->sc_max_sgs = (sc->sc_max_fib_size
  501                                         - sizeof(struct aac_blockwrite64)
  502                                         + sizeof(struct aac_sg_table64))
  503                                       / sizeof(struct aac_sg_table64);
  504         else
  505                 sc->sc_max_sgs = (sc->sc_max_fib_size
  506                                         - sizeof(struct aac_blockwrite)
  507                                         + sizeof(struct aac_sg_table))
  508                                       / sizeof(struct aac_sg_table);
  509 
  510         if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) {
  511                 u_int32_t       opt1, opt2, opt3;
  512                 u_int32_t       tmpval;
  513 
  514                 opt1 = AAC_GET_MAILBOX(sc, 1);
  515                 opt2 = AAC_GET_MAILBOX(sc, 2);
  516                 opt3 = AAC_GET_MAILBOX(sc, 3);
  517                 if (!opt1 || !opt2 || !opt3) {
  518                         aprint_verbose("%s: GETCOMMPREF appears untrustworthy."
  519                             "  Ignoring.\n", sc->sc_dv.dv_xname);
  520                 } else {
  521                         sc->sc_max_fib_size = le32toh(opt1) & 0xffff;
  522                         sc->sc_max_sectors = (le32toh(opt1) >> 16) << 1;
  523                         tmpval = (le32toh(opt2) >> 16);
  524                         if (tmpval < sc->sc_max_sgs) {
  525                                 sc->sc_max_sgs = tmpval;
  526                         }
  527                         tmpval = (le32toh(opt3) & 0xffff);
  528                         if (tmpval < sc->sc_max_fibs) {
  529                                 sc->sc_max_fibs = tmpval;
  530                         }
  531                 }
  532         }
  533         if (sc->sc_max_fib_size > PAGE_SIZE)
  534                 sc->sc_max_fib_size = PAGE_SIZE;
  535 
  536         if (sc->sc_quirks & AAC_QUIRK_SG_64BIT)
  537                 calcsgs = (sc->sc_max_fib_size
  538                            - sizeof(struct aac_blockwrite64)
  539                            + sizeof(struct aac_sg_table64))
  540                               / sizeof(struct aac_sg_table64);
  541         else
  542                 calcsgs = (sc->sc_max_fib_size
  543                            - sizeof(struct aac_blockwrite)
  544                            + sizeof(struct aac_sg_table))
  545                               / sizeof(struct aac_sg_table);
  546 
  547         if (calcsgs < sc->sc_max_sgs) {
  548                 sc->sc_max_sgs = calcsgs;
  549         }
  550 
  551         sc->sc_max_fibs_alloc = PAGE_SIZE / sc->sc_max_fib_size;
  552 
  553         if (sc->sc_max_fib_size > sizeof(struct aac_fib)) {
  554                 sc->sc_quirks |= AAC_QUIRK_RAW_IO;
  555                 aprint_debug("%s: Enable raw I/O\n", sc->sc_dv.dv_xname);
  556         }
  557         if ((sc->sc_quirks & AAC_QUIRK_RAW_IO) &&
  558             (sc->sc_quirks & AAC_QUIRK_ARRAY_64BIT)) {
  559                 sc->sc_quirks |= AAC_QUIRK_LBA_64BIT;
  560                 aprint_normal("%s: Enable 64-bit array support\n",
  561                     sc->sc_dv.dv_xname);
  562         }
  563 
  564         return (0);
  565 }
  566 
  567 static int
  568 aac_init(struct aac_softc *sc)
  569 {
  570         int nsegs, i, rv, state, norm, high;
  571         struct aac_adapter_init *ip;
  572         u_int32_t code, qoff;
  573 
  574         state = 0;
  575 
  576         /*
  577          * First wait for the adapter to come ready.
  578          */
  579         for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
  580                 code = AAC_GET_FWSTATUS(sc);
  581                 if ((code & AAC_SELF_TEST_FAILED) != 0) {
  582                         aprint_error("%s: FATAL: selftest failed\n",
  583                             sc->sc_dv.dv_xname);
  584                         return (ENXIO);
  585                 }
  586                 if ((code & AAC_KERNEL_PANIC) != 0) {
  587                         aprint_error("%s: FATAL: controller kernel panic\n",
  588                             sc->sc_dv.dv_xname);
  589                         return (ENXIO);
  590                 }
  591                 if ((code & AAC_UP_AND_RUNNING) != 0)
  592                         break;
  593                 DELAY(1000);
  594         }
  595         if (i == AAC_BOOT_TIMEOUT * 1000) {
  596                 aprint_error(
  597                     "%s: FATAL: controller not coming ready, status %x\n",
  598                     sc->sc_dv.dv_xname, code);
  599                 return (ENXIO);
  600         }
  601 
  602         sc->sc_aif_fib = malloc(sizeof(struct aac_fib), M_AACBUF,
  603             M_NOWAIT | M_ZERO);
  604         if (sc->sc_aif_fib == NULL) {
  605                 aprint_error("%s: cannot alloc fib structure\n",
  606                     sc->sc_dv.dv_xname);
  607                 return (ENOMEM);
  608         }
  609         if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
  610             sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
  611             &sc->sc_common_dmamap)) != 0) {
  612                 aprint_error("%s: cannot create common dmamap\n",
  613                     sc->sc_dv.dv_xname);
  614                 goto bail_out;
  615         }
  616         state++;
  617         if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
  618             PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
  619             BUS_DMA_NOWAIT)) != 0) {
  620                 aprint_error("%s: can't allocate common structure\n",
  621                     sc->sc_dv.dv_xname);
  622                 goto bail_out;
  623         }
  624         state++;
  625         if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
  626             sizeof(*sc->sc_common), (caddr_t *) &sc->sc_common, 0)) != 0) {
  627                 aprint_error("%s: can't map common structure\n",
  628                     sc->sc_dv.dv_xname);
  629                 goto bail_out;
  630         }
  631         state++;
  632         if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
  633             sc->sc_common, sizeof(*sc->sc_common), NULL,
  634             BUS_DMA_NOWAIT)) != 0) {
  635                 aprint_error("%s: cannot load common dmamap\n",
  636                     sc->sc_dv.dv_xname);
  637                 goto bail_out;
  638         }
  639         state++;
  640 
  641         memset(sc->sc_common, 0, sizeof(*sc->sc_common));
  642 
  643         TAILQ_INIT(&sc->sc_fibmap_tqh);
  644         sc->sc_ccbs = malloc(sizeof(struct aac_ccb) * sc->sc_max_fibs, M_AACBUF,
  645             M_NOWAIT | M_ZERO);
  646         if (sc->sc_ccbs == NULL) {
  647                 aprint_error("%s: memory allocation failure getting ccbs\n",
  648                     sc->sc_dv.dv_xname);
  649                 rv = ENOMEM;
  650                 goto bail_out;
  651         }
  652         state++;
  653         while (sc->sc_total_fibs < AAC_PREALLOCATE_FIBS(sc)) {
  654                 if (aac_alloc_commands(sc) != 0)
  655                         break;
  656         }
  657         if (sc->sc_total_fibs == 0)
  658                 goto bail_out;
  659 
  660         /*
  661          * Fill in the init structure.  This tells the adapter about the
  662          * physical location of various important shared data structures.
  663          */
  664         ip = &sc->sc_common->ac_init;
  665         ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
  666         if (sc->sc_quirks & AAC_QUIRK_RAW_IO)
  667                 ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION_4);
  668         ip->MiniPortRevision = htole32(AAC_INIT_STRUCT_MINIPORT_REVISION);
  669 
  670         ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
  671             offsetof(struct aac_common, ac_fibs));
  672         ip->AdapterFibsVirtualAddress = 0;
  673         ip->AdapterFibsSize =
  674             htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib));
  675         ip->AdapterFibAlign = htole32(sizeof(struct aac_fib));
  676 
  677         ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr +
  678             offsetof(struct aac_common, ac_printf));
  679         ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE);
  680 
  681         /*
  682          * The adapter assumes that pages are 4K in size, except on some
  683          * broken firmware versions that do the page->byte conversion twice,
  684          * therefore 'assuming' that this value is in 16MB units (2^24).
  685          * Round up since the granularity is so high.
  686          */
  687         ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE;
  688         if (sc->sc_quirks & AAC_QUIRK_BROKEN_MMAP) {
  689                 ip->HostPhysMemPages = 
  690                     (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
  691         }
  692         ip->HostElapsedSeconds = 0;     /* reset later if invalid */
  693 
  694         ip->InitFlags = 0;
  695         if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
  696                 ip->InitFlags = htole32(AAC_INITFLAGS_NEW_COMM_SUPPORTED);
  697                 aprint_normal("%s: New comm. interface enabled\n",
  698                                 sc->sc_dv.dv_xname);
  699         }
  700 
  701         ip->MaxIoCommands = htole32(sc->sc_max_fibs);
  702         ip->MaxIoSize = htole32(sc->sc_max_sectors << 9);
  703         ip->MaxFibSize = htole32(sc->sc_max_fib_size);
  704 
  705         /*
  706          * Initialise FIB queues.  Note that it appears that the layout of
  707          * the indexes and the segmentation of the entries is mandated by
  708          * the adapter, which is only told about the base of the queue index
  709          * fields.
  710          *
  711          * The initial values of the indices are assumed to inform the
  712          * adapter of the sizes of the respective queues.
  713          *
  714          * The Linux driver uses a much more complex scheme whereby several
  715          * header records are kept for each queue.  We use a couple of
  716          * generic list manipulation functions which 'know' the size of each
  717          * list by virtue of a table.
  718          */
  719         qoff = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
  720         qoff &= ~(AAC_QUEUE_ALIGN - 1);
  721         sc->sc_queues = (struct aac_queue_table *)((uintptr_t)sc->sc_common + qoff);
  722         ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr +
  723             ((char *)sc->sc_queues - (char *)sc->sc_common));
  724         memset(sc->sc_queues, 0, sizeof(struct aac_queue_table));
  725 
  726         norm = htole32(AAC_HOST_NORM_CMD_ENTRIES);
  727         high = htole32(AAC_HOST_HIGH_CMD_ENTRIES);
  728 
  729         sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
  730             norm;
  731         sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
  732             norm;
  733         sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
  734             high;
  735         sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
  736             high;
  737 
  738         norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES);
  739         high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES);
  740 
  741         sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
  742             norm;
  743         sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
  744             norm;
  745         sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
  746             high;
  747         sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
  748             high;
  749 
  750         norm = htole32(AAC_HOST_NORM_RESP_ENTRIES);
  751         high = htole32(AAC_HOST_HIGH_RESP_ENTRIES);
  752 
  753         sc->sc_queues->
  754             qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
  755         sc->sc_queues->
  756             qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
  757         sc->sc_queues->
  758             qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
  759         sc->sc_queues->
  760             qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
  761 
  762         norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES);
  763         high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES);
  764 
  765         sc->sc_queues->
  766             qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
  767         sc->sc_queues->
  768             qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
  769         sc->sc_queues->
  770             qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
  771         sc->sc_queues->
  772             qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
  773 
  774         sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] =
  775             &sc->sc_queues->qt_HostNormCmdQueue[0];
  776         sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
  777             &sc->sc_queues->qt_HostHighCmdQueue[0];
  778         sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
  779             &sc->sc_queues->qt_AdapNormCmdQueue[0];
  780         sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
  781             &sc->sc_queues->qt_AdapHighCmdQueue[0];
  782         sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] =
  783             &sc->sc_queues->qt_HostNormRespQueue[0];
  784         sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
  785             &sc->sc_queues->qt_HostHighRespQueue[0];
  786         sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
  787             &sc->sc_queues->qt_AdapNormRespQueue[0];
  788         sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
  789             &sc->sc_queues->qt_AdapHighRespQueue[0];
  790 
  791         /*
  792          * Do controller-type-specific initialisation
  793          */
  794         switch (sc->sc_hwif) {
  795         case AAC_HWIF_I960RX:
  796                 AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
  797                 break;
  798         }
  799 
  800         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0,
  801             sizeof(*sc->sc_common),
  802             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  803 
  804         /*
  805          * Give the init structure to the controller.
  806          */
  807         if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
  808             sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init),
  809             0, 0, 0, NULL)) {
  810                 aprint_error("%s: error establishing init structure\n",
  811                     sc->sc_dv.dv_xname);
  812                 rv = EIO;
  813                 goto bail_out;
  814         }
  815 
  816         return (0);
  817 
  818  bail_out:
  819         if (state > 4)
  820                 free(sc->sc_ccbs, M_AACBUF);
  821         if (state > 3)
  822                 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
  823         if (state > 2)
  824                 bus_dmamem_unmap(sc->sc_dmat, (void *)sc->sc_common,
  825                     sizeof(*sc->sc_common));
  826         if (state > 1)
  827                 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
  828         if (state > 0)
  829                 bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
  830 
  831         free(sc->sc_aif_fib, M_AACBUF);
  832 
  833         return (rv);
  834 }
  835 
  836 /*
  837  * Probe for containers, create disks.
  838  */
  839 static void
  840 aac_startup(struct aac_softc *sc)
  841 {
  842         struct aac_mntinfo mi;
  843         struct aac_mntinforesponse mir;
  844         struct aac_drive *hd;
  845         u_int16_t rsize;
  846         size_t ersize;
  847         int i;
  848 
  849         /*
  850          * Loop over possible containers.
  851          */
  852         hd = sc->sc_hdr;
  853 
  854         for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) {
  855                 /*
  856                  * Request information on this container.
  857                  */
  858                 memset(&mi, 0, sizeof(mi));
  859                 /* use 64-bit LBA if enabled */
  860                 if (sc->sc_quirks & AAC_QUIRK_LBA_64BIT) {
  861                         mi.Command = htole32(VM_NameServe64);
  862                         ersize = sizeof(mir);
  863                 } else {
  864                         mi.Command = htole32(VM_NameServe);
  865                         ersize = sizeof(mir) - sizeof(mir.MntTable[0].CapacityHigh);
  866                 }
  867                 mi.MntType = htole32(FT_FILESYS);
  868                 mi.MntCount = htole32(i);
  869                 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir,
  870                     &rsize)) {
  871                         aprint_error("%s: error probing container %d\n",
  872                             sc->sc_dv.dv_xname, i);
  873                         continue;
  874                 }
  875                 if (rsize != ersize) {
  876                         aprint_error("%s: container info response wrong size "
  877                             "(%d should be %zu)\n",
  878                             sc->sc_dv.dv_xname, rsize, ersize);
  879                         continue;
  880                 }
  881 
  882                 /*
  883                  * Check container volume type for validity.  Note that many
  884                  * of the possible types may never show up.
  885                  */
  886                 if (le32toh(mir.Status) != ST_OK ||
  887                     le32toh(mir.MntTable[0].VolType) == CT_NONE)
  888                         continue;
  889 
  890                 hd->hd_present = 1;
  891                 hd->hd_size = le32toh(mir.MntTable[0].Capacity);
  892                 if (sc->sc_quirks & AAC_QUIRK_LBA_64BIT)
  893                         hd->hd_size += (u_int64_t)
  894                             le32toh(mir.MntTable[0].CapacityHigh) << 32;
  895                 hd->hd_devtype = le32toh(mir.MntTable[0].VolType);
  896                 hd->hd_size &= ~0x1f;
  897                 sc->sc_nunits++;
  898         }
  899 }
  900 
  901 static void
  902 aac_shutdown(void *cookie)
  903 {
  904         struct aac_softc *sc;
  905         struct aac_close_command cc;
  906         u_int32_t i;
  907 
  908         for (i = 0; i < aac_cd.cd_ndevs; i++) {
  909                 if ((sc = device_lookup(&aac_cd, i)) == NULL)
  910                         continue;
  911                 if ((sc->sc_flags & AAC_ONLINE) == 0)
  912                         continue;
  913 
  914                 AAC_MASK_INTERRUPTS(sc);
  915 
  916                 /*
  917                  * Send a Container shutdown followed by a HostShutdown FIB
  918                  * to the controller to convince it that we don't want to
  919                  * talk to it anymore.  We've been closed and all I/O
  920                  * completed already
  921                  */
  922                 memset(&cc, 0, sizeof(cc));
  923                 cc.Command = htole32(VM_CloseAll);
  924                 cc.ContainerId = 0xffffffff;
  925                 if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc),
  926                     NULL, NULL)) {
  927                         printf("%s: unable to halt controller\n",
  928                             sc->sc_dv.dv_xname);
  929                         continue;
  930                 }
  931 
  932                 /*
  933                  * Note that issuing this command to the controller makes it
  934                  * shut down but also keeps it from coming back up without a
  935                  * reset of the PCI bus.
  936                  */
  937                 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
  938                     &i, sizeof(i), NULL, NULL))
  939                         printf("%s: unable to halt controller\n",
  940                             sc->sc_dv.dv_xname);
  941 
  942                 sc->sc_flags &= ~AAC_ONLINE;
  943         }
  944 }
  945 
  946 static int
  947 aac_new_intr(void *cookie)
  948 {
  949         struct aac_softc *sc;
  950         u_int32_t index, fast;
  951         struct aac_ccb *ac;
  952         struct aac_fib *fib;
  953         struct aac_fibmap *fm;
  954         int i;
  955 
  956         sc = (struct aac_softc *) cookie;
  957 
  958         for (;;) {
  959                 index = AAC_GET_OUTB_QUEUE(sc);
  960                 if (index == 0xffffffff)
  961                         index = AAC_GET_OUTB_QUEUE(sc);
  962                 if (index == 0xffffffff)
  963                         break;
  964                 if (index & 2) {
  965                         if (index == 0xfffffffe) {
  966                                 /* XXX This means that the controller wants
  967                                  * more work.  Ignore it for now.
  968                                  */
  969                                 continue;
  970                         }
  971                         /* AIF */
  972                         index &= ~2;
  973                         fib = sc->sc_aif_fib;
  974                         for (i = 0; i < sizeof(struct aac_fib)/4; i++) {
  975                                 ((u_int32_t*)fib)[i] =
  976                                     AAC_GETREG4(sc, index + i*4);
  977                         }
  978 #ifdef notyet
  979                         aac_handle_aif(sc, &fib);
  980 #endif
  981 
  982                         AAC_SET_OUTB_QUEUE(sc, index);
  983                         AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
  984                 } else {
  985                         fast = index & 1;
  986                         ac = sc->sc_ccbs + (index >> 2);
  987                         fib = ac->ac_fib;
  988                         fm = ac->ac_fibmap;
  989                         if (fast) {
  990                                 bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
  991                                     (char *)fib - (char *)fm->fm_fibs,
  992                                     sc->sc_max_fib_size,
  993                                     BUS_DMASYNC_POSTWRITE |
  994                                     BUS_DMASYNC_POSTREAD);
  995                                 fib->Header.XferState |=
  996                                     htole32(AAC_FIBSTATE_DONEADAP);
  997                                 *((u_int32_t *)(fib->data)) =
  998                                     htole32(AAC_ERROR_NORMAL);
  999                         }
 1000                         ac->ac_flags |= AAC_CCB_COMPLETED;
 1001 
 1002                         if (ac->ac_intr != NULL)
 1003                                 (*ac->ac_intr)(ac);
 1004                         else
 1005                                 wakeup(ac);
 1006                 }
 1007         }
 1008 
 1009         /*
 1010          * Try to submit more commands.
 1011          */
 1012         if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
 1013                 aac_ccb_enqueue(sc, NULL);
 1014 
 1015         return 1;
 1016 }
 1017 
 1018 /*
 1019  * Take an interrupt.
 1020  */
 1021 int
 1022 aac_intr(void *cookie)
 1023 {
 1024         struct aac_softc *sc;
 1025         u_int16_t reason;
 1026         int claimed;
 1027 
 1028         sc = cookie;
 1029         claimed = 0;
 1030 
 1031         AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
 1032 
 1033         reason = AAC_GET_ISTATUS(sc);
 1034         AAC_CLEAR_ISTATUS(sc, reason);
 1035 
 1036         AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
 1037 
 1038         /*
 1039          * Controller wants to talk to the log.  XXX Should we defer this?
 1040          */
 1041         if ((reason & AAC_DB_PRINTF) != 0) {
 1042                 if (sc->sc_common->ac_printf[0] == '\0')
 1043                         sc->sc_common->ac_printf[0] = ' ';
 1044                 printf("%s: WARNING: adapter logged message:\n",
 1045                         sc->sc_dv.dv_xname);
 1046                 printf("%s:     %.*s", sc->sc_dv.dv_xname,
 1047                         AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
 1048                 sc->sc_common->ac_printf[0] = '\0';
 1049                 AAC_QNOTIFY(sc, AAC_DB_PRINTF);
 1050                 claimed = 1;
 1051         }
 1052 
 1053         /*
 1054          * Controller has a message for us?
 1055          */
 1056         if ((reason & AAC_DB_COMMAND_READY) != 0) {
 1057                 aac_host_command(sc);
 1058                 claimed = 1;
 1059         }
 1060 
 1061         /*
 1062          * Controller has a response for us?
 1063          */
 1064         if ((reason & AAC_DB_RESPONSE_READY) != 0) {
 1065                 aac_host_response(sc);
 1066                 claimed = 1;
 1067         }
 1068 
 1069         /*
 1070          * Spurious interrupts that we don't use - reset the mask and clear
 1071          * the interrupts.
 1072          */
 1073         if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
 1074             AAC_DB_RESPONSE_NOT_FULL)) != 0) {
 1075                 AAC_UNMASK_INTERRUPTS(sc);
 1076                 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
 1077                     AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
 1078                 claimed = 1;
 1079         }
 1080 
 1081         return (claimed);
 1082 }
 1083 
 1084 /*
 1085  * Handle notification of one or more FIBs coming from the controller.
 1086  */
 1087 static void
 1088 aac_host_command(struct aac_softc *sc)
 1089 {
 1090         struct aac_fib *fib;
 1091         u_int32_t fib_size;
 1092 
 1093         for (;;) {
 1094                 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
 1095                     &fib))
 1096                         break;  /* nothing to do */
 1097 
 1098                 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1099                     (char *)fib - (char *)sc->sc_common, sizeof(*fib),
 1100                     BUS_DMASYNC_POSTREAD);
 1101 
 1102                 switch (le16toh(fib->Header.Command)) {
 1103                 case AifRequest:
 1104 #ifdef notyet
 1105                         aac_handle_aif(sc,
 1106                             (struct aac_aif_command *)&fib->data[0]);
 1107 #endif
 1108                         AAC_PRINT_FIB(sc, fib);
 1109                         break;
 1110                 default:
 1111                         printf("%s: unknown command from controller\n",
 1112                             sc->sc_dv.dv_xname);
 1113                         AAC_PRINT_FIB(sc, fib);
 1114                         break;
 1115                 }
 1116 
 1117                 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1118                     (char *)fib - (char *)sc->sc_common, sizeof(*fib),
 1119                     BUS_DMASYNC_PREREAD);
 1120 
 1121                 if ((fib->Header.XferState == 0) ||
 1122                     (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
 1123                         break; // continue; ???
 1124                 }
 1125 
 1126                 /* XXX reply to FIBs requesting responses ?? */
 1127 
 1128                 /* Return the AIF/FIB to the controller */
 1129                 if (le32toh(fib->Header.XferState) & AAC_FIBSTATE_FROMADAP) {
 1130                         u_int16_t       size;
 1131 
 1132                         fib->Header.XferState |=
 1133                                 htole32(AAC_FIBSTATE_DONEHOST);
 1134                         *(u_int32_t*)fib->data = htole32(ST_OK);
 1135 
 1136                         /* XXX Compute the Size field? */
 1137                         size = le16toh(fib->Header.Size);
 1138                         if (size > sizeof(struct aac_fib)) {
 1139                                 size = sizeof(struct aac_fib);
 1140                                 fib->Header.Size = htole16(size);
 1141                         }
 1142 
 1143                         /*
 1144                          * Since we didn't generate this command, it can't
 1145                          * go through the normal process.
 1146                          */
 1147                         aac_enqueue_response(sc,
 1148                                         AAC_ADAP_NORM_RESP_QUEUE, fib);
 1149                 }
 1150         }
 1151 }
 1152 
 1153 /*
 1154  * Handle notification of one or more FIBs completed by the controller
 1155  */
 1156 static void
 1157 aac_host_response(struct aac_softc *sc)
 1158 {
 1159         struct aac_ccb *ac;
 1160         struct aac_fib *fib;
 1161         u_int32_t fib_size;
 1162 
 1163         /*
 1164          * Look for completed FIBs on our queue.
 1165          */
 1166         for (;;) {
 1167                 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
 1168                     &fib))
 1169                         break;  /* nothing to do */
 1170 
 1171                 if ((fib->Header.SenderData & 0x80000000) == 0) {
 1172                         /* Not valid; not sent by us. */
 1173                         AAC_PRINT_FIB(sc, fib);
 1174                 } else {
 1175                         ac = (struct aac_ccb *)(sc->sc_ccbs +
 1176                             (fib->Header.SenderData & 0x7fffffff));
 1177                         fib->Header.SenderData = 0;
 1178                         SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain);
 1179                 }
 1180         }
 1181 
 1182         /*
 1183          * Deal with any completed commands.
 1184          */
 1185         while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) {
 1186                 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain);
 1187                 ac->ac_flags |= AAC_CCB_COMPLETED;
 1188 
 1189                 if (ac->ac_intr != NULL)
 1190                         (*ac->ac_intr)(ac);
 1191                 else
 1192                         wakeup(ac);
 1193         }
 1194 
 1195         /*
 1196          * Try to submit more commands.
 1197          */
 1198         if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
 1199                 aac_ccb_enqueue(sc, NULL);
 1200 }
 1201 
 1202 /*
 1203  * Send a synchronous command to the controller and wait for a result.
 1204  */
 1205 static int
 1206 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
 1207                  u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
 1208 {
 1209         int i;
 1210         u_int32_t status;
 1211         int s;
 1212 
 1213         s = splbio();
 1214 
 1215         /* Populate the mailbox. */
 1216         AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
 1217 
 1218         /* Ensure the sync command doorbell flag is cleared. */
 1219         AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
 1220 
 1221         /* ... then set it to signal the adapter. */
 1222         AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
 1223         DELAY(AAC_SYNC_DELAY);
 1224 
 1225         /* Spin waiting for the command to complete. */
 1226         for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
 1227                 if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
 1228                         break;
 1229                 DELAY(1000);
 1230         }
 1231         if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
 1232                 splx(s);
 1233                 return (EIO);
 1234         }
 1235 
 1236         /* Clear the completion flag. */
 1237         AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
 1238 
 1239         /* Get the command status. */
 1240         status = AAC_GET_MAILBOXSTATUS(sc);
 1241         splx(s);
 1242         if (sp != NULL)
 1243                 *sp = status;
 1244 
 1245         return (0);     /* XXX Check command return status? */
 1246 }
 1247 
 1248 /*
 1249  * Send a synchronous FIB to the controller and wait for a result.
 1250  */
 1251 static int
 1252 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
 1253              void *data, u_int16_t datasize, void *result,
 1254              u_int16_t *resultsize)
 1255 {
 1256         struct aac_fib *fib;
 1257         u_int32_t fibpa, status;
 1258 
 1259         fib = &sc->sc_common->ac_sync_fib;
 1260         fibpa = sc->sc_common_seg.ds_addr +
 1261             offsetof(struct aac_common, ac_sync_fib);
 1262 
 1263         if (datasize > AAC_FIB_DATASIZE)
 1264                 return (EINVAL);
 1265 
 1266         /*
 1267          * Set up the sync FIB.
 1268          */
 1269         fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED |
 1270             AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate);
 1271         fib->Header.Command = htole16(command);
 1272         fib->Header.StructType = AAC_FIBTYPE_TFIB;
 1273         fib->Header.Size = htole16(sizeof(*fib) + datasize);
 1274         fib->Header.SenderSize = htole16(sizeof(*fib));
 1275         fib->Header.SenderFibAddress = 0; /* not needed */
 1276         fib->Header.ReceiverFibAddress = htole32(fibpa);
 1277 
 1278         /*
 1279          * Copy in data.
 1280          */
 1281         if (data != NULL) {
 1282                 memcpy(fib->data, data, datasize);
 1283                 fib->Header.XferState |=
 1284                     htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM);
 1285         }
 1286 
 1287         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1288             (char *)fib - (char *)sc->sc_common, sizeof(*fib),
 1289             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1290 
 1291         /*
 1292          * Give the FIB to the controller, wait for a response.
 1293          */
 1294         if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status))
 1295                 return (EIO);
 1296         if (status != 1) {
 1297                 printf("%s: syncfib command %04x status %08x\n",
 1298                         sc->sc_dv.dv_xname, command, status);
 1299         }
 1300 
 1301         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1302             (char *)fib - (char *)sc->sc_common, sizeof(*fib),
 1303             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 1304 
 1305         /*
 1306          * Copy out the result
 1307          */
 1308         if (result != NULL) {
 1309                 *resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header);
 1310                 memcpy(result, fib->data, *resultsize);
 1311         }
 1312 
 1313         return (0);
 1314 }
 1315 
 1316 struct aac_ccb *
 1317 aac_ccb_alloc(struct aac_softc *sc, int flags)
 1318 {
 1319         struct aac_ccb *ac;
 1320         int s;
 1321 
 1322         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags));
 1323 
 1324         s = splbio();
 1325         ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
 1326         if (ac == NULL) {
 1327                 if (aac_alloc_commands(sc)) {
 1328                         splx(s);
 1329                         return NULL;
 1330                 }
 1331                 ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
 1332         }
 1333 #ifdef DIAGNOSTIC
 1334         if (ac == NULL)
 1335                 panic("aac_ccb_get: no free CCBS");
 1336 #endif
 1337         SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain);
 1338         splx(s);
 1339 
 1340         ac->ac_flags = flags;
 1341         return (ac);
 1342 }
 1343 
 1344 void
 1345 aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac)
 1346 {
 1347         int s;
 1348 
 1349         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac));
 1350 
 1351         ac->ac_flags = 0;
 1352         ac->ac_intr = NULL;
 1353         ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY);
 1354         ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
 1355         ac->ac_fib->Header.Flags = 0;
 1356         ac->ac_fib->Header.SenderSize = htole16(sc->sc_max_fib_size);
 1357 
 1358 #ifdef AAC_DEBUG
 1359         /*
 1360          * These are duplicated in aac_ccb_submit() to cover the case where
 1361          * an intermediate stage may have destroyed them.  They're left
 1362          * initialised here for debugging purposes only.
 1363          */
 1364         ac->ac_fib->Header.SenderFibAddress =
 1365             htole32(((u_int32_t) (ac - sc->sc_ccbs)) << 2);
 1366         ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
 1367 #endif
 1368 
 1369         s = splbio();
 1370         SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain);
 1371         splx(s);
 1372 }
 1373 
 1374 int
 1375 aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac)
 1376 {
 1377         int error;
 1378 
 1379         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac));
 1380 
 1381 #ifdef DIAGNOSTIC
 1382         if ((ac->ac_flags & AAC_CCB_MAPPED) != 0)
 1383                 panic("aac_ccb_map: already mapped");
 1384 #endif
 1385 
 1386         error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data,
 1387             ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
 1388             ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
 1389         if (error) {
 1390                 printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname);
 1391                 if (error == EFBIG)
 1392                         printf("more than %d DMA segs\n", sc->sc_max_sgs);
 1393                 else
 1394                         printf("error %d loading DMA map\n", error);
 1395                 return (error);
 1396         }
 1397 
 1398         bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
 1399             (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD :
 1400             BUS_DMASYNC_PREWRITE);
 1401 
 1402 #ifdef DIAGNOSTIC
 1403         ac->ac_flags |= AAC_CCB_MAPPED;
 1404 #endif
 1405         return (0);
 1406 }
 1407 
 1408 void
 1409 aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac)
 1410 {
 1411 
 1412         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac));
 1413 
 1414 #ifdef DIAGNOSTIC
 1415         if ((ac->ac_flags & AAC_CCB_MAPPED) == 0)
 1416                 panic("aac_ccb_unmap: not mapped");
 1417 #endif
 1418 
 1419         bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
 1420             (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD :
 1421             BUS_DMASYNC_POSTWRITE);
 1422         bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer);
 1423 
 1424 #ifdef DIAGNOSTIC
 1425         ac->ac_flags &= ~AAC_CCB_MAPPED;
 1426 #endif
 1427 }
 1428 
 1429 void
 1430 aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac)
 1431 {
 1432         int s;
 1433 
 1434         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac));
 1435 
 1436         s = splbio();
 1437 
 1438         if (ac != NULL)
 1439                 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain);
 1440 
 1441         while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
 1442                 if (aac_ccb_submit(sc, ac))
 1443                         break;
 1444                 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain);
 1445         }
 1446 
 1447         splx(s);
 1448 }
 1449 
 1450 int
 1451 aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac)
 1452 {
 1453         struct aac_fibmap *fm;
 1454         u_int32_t acidx;
 1455 
 1456         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
 1457 
 1458         acidx = (u_int32_t) (ac - sc->sc_ccbs);
 1459         /* Fix up the address values. */
 1460         ac->ac_fib->Header.SenderFibAddress = htole32(acidx << 2);
 1461         ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
 1462 
 1463         /* Save a pointer to the command for speedy reverse-lookup. */
 1464         ac->ac_fib->Header.SenderData = acidx | 0x80000000;
 1465 
 1466         fm = ac->ac_fibmap;
 1467         bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
 1468             (char *)ac->ac_fib - (char *)fm->fm_fibs, sc->sc_max_fib_size,
 1469             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1470 
 1471         /* Put the FIB on the outbound queue. */
 1472         if (sc->sc_quirks & AAC_QUIRK_NEW_COMM) {
 1473                 int count = 10000000L;
 1474                 while (AAC_SEND_COMMAND(sc, ac) != 0) {
 1475                         if (--count == 0) {
 1476                                 panic("aac: fixme!");
 1477                                 return EAGAIN;
 1478                         }
 1479                         DELAY(5);
 1480                 }
 1481                 return 0;
 1482         } else {
 1483                 return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac));
 1484         }
 1485 }
 1486 
 1487 int
 1488 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
 1489 {
 1490         int rv, s;
 1491 
 1492         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
 1493 
 1494         s = splbio();
 1495 
 1496         if ((rv = aac_ccb_submit(sc, ac)) != 0) {
 1497                 splx(s);
 1498                 return (rv);
 1499         }
 1500 
 1501         for (timo *= 1000; timo != 0; timo--) {
 1502                 if (sc->sc_quirks & AAC_QUIRK_NEW_COMM)
 1503                         aac_new_intr(sc);
 1504                 else
 1505                         aac_intr(sc);
 1506                 if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
 1507                         break;
 1508                 DELAY(100);
 1509         }
 1510 
 1511         splx(s);
 1512         return (timo == 0);
 1513 }
 1514 
 1515 /*
 1516  * Atomically insert an entry into the nominated queue, returns 0 on success
 1517  * or EBUSY if the queue is full.
 1518  *
 1519  * XXX Note that it would be more efficient to defer notifying the
 1520  * controller in the case where we may be inserting several entries in rapid
 1521  * succession, but implementing this usefully is difficult.
 1522  */
 1523 static int
 1524 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_ccb *ac)
 1525 {
 1526         u_int32_t fib_size, fib_addr, pi, ci;
 1527 
 1528         fib_size = le16toh(ac->ac_fib->Header.Size);
 1529         fib_addr = le32toh(ac->ac_fib->Header.ReceiverFibAddress);
 1530 
 1531         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1532             (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
 1533             sizeof(sc->sc_common->ac_qbuf),
 1534             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 1535 
 1536         /* Get the producer/consumer indices.  */
 1537         pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
 1538         ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
 1539 
 1540         /* Wrap the queue? */
 1541         if (pi >= aac_qinfo[queue].size)
 1542                 pi = 0;
 1543 
 1544         /* Check for queue full. */
 1545         if ((pi + 1) == ci)
 1546                 return (EAGAIN);
 1547 
 1548         /* Populate queue entry. */
 1549         (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
 1550         (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
 1551 
 1552         /* Update producer index. */
 1553         sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
 1554 
 1555         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1556             (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
 1557             sizeof(sc->sc_common->ac_qbuf),
 1558             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1559 
 1560         /* Notify the adapter if we know how. */
 1561         if (aac_qinfo[queue].notify != 0)
 1562                 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
 1563 
 1564         return (0);
 1565 }
 1566 
 1567 /*
 1568  * Atomically remove one entry from the nominated queue, returns 0 on success
 1569  * or ENOENT if the queue is empty.
 1570  */
 1571 static int
 1572 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
 1573                 struct aac_fib **fib_addr)
 1574 {
 1575         struct aac_fibmap *fm;
 1576         struct aac_ccb *ac;
 1577         u_int32_t pi, ci, idx;
 1578         int notify;
 1579 
 1580         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1581             (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
 1582             sizeof(sc->sc_common->ac_qbuf),
 1583             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 1584 
 1585         /* Get the producer/consumer indices. */
 1586         pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
 1587         ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
 1588 
 1589         /* Check for queue empty. */
 1590         if (ci == pi)
 1591                 return (ENOENT);
 1592 
 1593         notify = 0;
 1594         if (ci == pi + 1)
 1595                 notify = 1;
 1596 
 1597         /* Wrap the queue? */
 1598         if (ci >= aac_qinfo[queue].size)
 1599                 ci = 0;
 1600 
 1601         /* Fetch the entry. */
 1602         *fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
 1603 
 1604         switch (queue) {
 1605         case AAC_HOST_NORM_CMD_QUEUE:
 1606         case AAC_HOST_HIGH_CMD_QUEUE:
 1607                 idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
 1608                 idx /= sizeof(struct aac_fib);
 1609                 *fib_addr = &sc->sc_common->ac_fibs[idx];
 1610                 break;
 1611         case AAC_HOST_NORM_RESP_QUEUE:
 1612         case AAC_HOST_HIGH_RESP_QUEUE:
 1613                 idx = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_addr);
 1614                 ac = sc->sc_ccbs + (idx >> 2);
 1615                 *fib_addr = ac->ac_fib;
 1616                 if (idx & 0x01) {
 1617                         fm = ac->ac_fibmap;
 1618                         bus_dmamap_sync(sc->sc_dmat, fm->fm_fibmap,
 1619                             (char *)ac->ac_fib - (char *)fm->fm_fibs,
 1620                             sc->sc_max_fib_size,
 1621                             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 1622                         ac->ac_fib->Header.XferState |=
 1623                                 htole32(AAC_FIBSTATE_DONEADAP);
 1624                         *((u_int32_t*)(ac->ac_fib->data)) =
 1625                                 htole32(AAC_ERROR_NORMAL);
 1626                 }
 1627                 break;
 1628         default:
 1629                 panic("Invalid queue in aac_dequeue_fib()");
 1630                 break;
 1631         }
 1632 
 1633         /* Update consumer index. */
 1634         sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
 1635 
 1636         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1637             (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
 1638             sizeof(sc->sc_common->ac_qbuf),
 1639             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1640 
 1641         /* If we have made the queue un-full, notify the adapter. */
 1642         if (notify && (aac_qinfo[queue].notify != 0))
 1643                 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
 1644 
 1645         return (0);
 1646 }
 1647 
 1648 /*
 1649  * Put our response to an adapter-initiated fib (AIF) on the response queue.
 1650  */
 1651 static int
 1652 aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
 1653 {
 1654         u_int32_t fib_size, fib_addr, pi, ci;
 1655 
 1656         fib_size = le16toh(fib->Header.Size);
 1657         fib_addr = fib->Header.SenderFibAddress;
 1658         fib->Header.ReceiverFibAddress = fib_addr;
 1659 
 1660         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1661             (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
 1662             sizeof(sc->sc_common->ac_qbuf),
 1663             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 1664 
 1665         /* Get the producer/consumer indices.  */
 1666         pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
 1667         ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
 1668 
 1669         /* Wrap the queue? */
 1670         if (pi >= aac_qinfo[queue].size)
 1671                 pi = 0;
 1672 
 1673         /* Check for queue full. */
 1674         if ((pi + 1) == ci)
 1675                 return (EAGAIN);
 1676 
 1677         /* Populate queue entry. */
 1678         (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
 1679         (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
 1680 
 1681         /* Update producer index. */
 1682         sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
 1683 
 1684         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1685             (char *)sc->sc_common->ac_qbuf - (char *)sc->sc_common,
 1686             sizeof(sc->sc_common->ac_qbuf),
 1687             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1688 
 1689         /* Notify the adapter if we know how. */
 1690         if (aac_qinfo[queue].notify != 0)
 1691                 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
 1692 
 1693         return (0);
 1694 }
 1695 
 1696 #ifdef AAC_DEBUG
 1697 /*
 1698  * Print a FIB
 1699  */
 1700 static void
 1701 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib,
 1702     const char *caller)
 1703 {
 1704         struct aac_blockread *br;
 1705         struct aac_blockwrite *bw;
 1706         struct aac_sg_table *sg;
 1707         char tbuf[512];
 1708         int i;
 1709 
 1710         printf("%s: FIB @ %p\n", caller, fib);
 1711         bitmask_snprintf(le32toh(fib->Header.XferState),
 1712             "\2"
 1713             "\1HOSTOWNED"
 1714             "\2ADAPTEROWNED"
 1715             "\3INITIALISED"
 1716             "\4EMPTY"
 1717             "\5FROMPOOL"
 1718             "\6FROMHOST"
 1719             "\7FROMADAP"
 1720             "\10REXPECTED"
 1721             "\11RNOTEXPECTED"
 1722             "\12DONEADAP"
 1723             "\13DONEHOST"
 1724             "\14HIGH"
 1725             "\15NORM"
 1726             "\16ASYNC"
 1727             "\17PAGEFILEIO"
 1728             "\20SHUTDOWN"
 1729             "\21LAZYWRITE"
 1730             "\22ADAPMICROFIB"
 1731             "\23BIOSFIB"
 1732             "\24FAST_RESPONSE"
 1733             "\25APIFIB\n",
 1734             tbuf,
 1735             sizeof(tbuf));
 1736 
 1737         printf("  XferState       %s\n", tbuf);
 1738         printf("  Command         %d\n", le16toh(fib->Header.Command));
 1739         printf("  StructType      %d\n", fib->Header.StructType);
 1740         printf("  Flags           0x%x\n", fib->Header.Flags);
 1741         printf("  Size            %d\n", le16toh(fib->Header.Size));
 1742         printf("  SenderSize      %d\n", le16toh(fib->Header.SenderSize));
 1743         printf("  SenderAddress   0x%x\n",
 1744             le32toh(fib->Header.SenderFibAddress));
 1745         printf("  ReceiverAddress 0x%x\n",
 1746             le32toh(fib->Header.ReceiverFibAddress));
 1747         printf("  SenderData      0x%x\n", fib->Header.SenderData);
 1748 
 1749         switch (fib->Header.Command) {
 1750         case ContainerCommand: {
 1751                 br = (struct aac_blockread *)fib->data;
 1752                 bw = (struct aac_blockwrite *)fib->data;
 1753                 sg = NULL;
 1754 
 1755                 if (le32toh(br->Command) == VM_CtBlockRead) {
 1756                         printf("  BlockRead: container %d  0x%x/%d\n",
 1757                             le32toh(br->ContainerId), le32toh(br->BlockNumber),
 1758                             le32toh(br->ByteCount));
 1759                         sg = &br->SgMap;
 1760                 }
 1761                 if (le32toh(bw->Command) == VM_CtBlockWrite) {
 1762                         printf("  BlockWrite: container %d  0x%x/%d (%s)\n",
 1763                             le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
 1764                             le32toh(bw->ByteCount),
 1765                             le32toh(bw->Stable) == CSTABLE ?
 1766                             "stable" : "unstable");
 1767                         sg = &bw->SgMap;
 1768                 }
 1769                 if (sg != NULL) {
 1770                         printf("  %d s/g entries\n", le32toh(sg->SgCount));
 1771                         for (i = 0; i < le32toh(sg->SgCount); i++)
 1772                                 printf("  0x%08x/%d\n",
 1773                                     le32toh(sg->SgEntry[i].SgAddress),
 1774                                     le32toh(sg->SgEntry[i].SgByteCount));
 1775                 }
 1776                 break;
 1777         }
 1778         default:
 1779                 // dump first 32 bytes of fib->data
 1780                 printf("  Raw data:");
 1781                 for (i = 0; i < 32; i++)
 1782                         printf(" %02x", fib->data[i]);
 1783                 printf("\n");
 1784                 break;
 1785         }
 1786 }
 1787 #endif /* AAC_DEBUG */

Cache object: 3560ba0c3decd5cbdad647ceb3356f1e


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