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.18 2005/03/12 10:35:29 darcy Exp $   */
    2 
    3 /*-
    4  * Copyright (c) 2002 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.18 2005/03/12 10:35:29 darcy 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_check_firmware(struct aac_softc *);
  100 static void     aac_describe_controller(struct aac_softc *);
  101 static int      aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
  102                                 struct aac_fib **);
  103 static int      aac_enqueue_fib(struct aac_softc *, int, struct aac_fib *);
  104 static void     aac_host_command(struct aac_softc *);
  105 static void     aac_host_response(struct aac_softc *);
  106 static int      aac_init(struct aac_softc *);
  107 static int      aac_print(void *, const char *);
  108 static void     aac_shutdown(void *);
  109 static void     aac_startup(struct aac_softc *);
  110 static int      aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
  111                                  u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
  112 static int      aac_sync_fib(struct aac_softc *, u_int32_t, u_int32_t, void *,
  113                              u_int16_t, void *, u_int16_t *);
  114 static int      aac_submatch(struct device *, struct cfdata *,
  115                              const locdesc_t *, void *);
  116 
  117 #ifdef AAC_DEBUG
  118 static void     aac_print_fib(struct aac_softc *, struct aac_fib *, char *);
  119 #endif
  120 
  121 /*
  122  * Adapter-space FIB queue manipulation.
  123  *
  124  * Note that the queue implementation here is a little funky; neither the PI or
  125  * CI will ever be zero.  This behaviour is a controller feature.
  126  */
  127 static struct {
  128         int     size;
  129         int     notify;
  130 } const aac_qinfo[] = {
  131         { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
  132         { AAC_HOST_HIGH_CMD_ENTRIES, 0 },
  133         { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
  134         { AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
  135         { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
  136         { AAC_HOST_HIGH_RESP_ENTRIES, 0 },
  137         { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
  138         { AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
  139 };
  140 
  141 #ifdef AAC_DEBUG
  142 int     aac_debug = AAC_DEBUG;
  143 #endif
  144 
  145 static void     *aac_sdh;
  146 
  147 extern struct   cfdriver aac_cd;
  148 
  149 int
  150 aac_attach(struct aac_softc *sc)
  151 {
  152         struct aac_attach_args aaca;
  153         int nsegs, i, rv, state, size;
  154         struct aac_ccb *ac;
  155         struct aac_fib *fib;
  156         bus_addr_t fibpa;
  157         int help[2];
  158         locdesc_t *ldesc = (void *)help; /* XXX - Not clean
  159                 The big plan is to let config(8) issue information
  160                 about the length of the locator array in a useful way.
  161                 Then the allocation can be centralized. See also
  162                 http://mail-index.netbsd.org/tech-kern/2005/02/09/0025.html
  163         */
  164 
  165         SIMPLEQ_INIT(&sc->sc_ccb_free);
  166         SIMPLEQ_INIT(&sc->sc_ccb_queue);
  167         SIMPLEQ_INIT(&sc->sc_ccb_complete);
  168 
  169         /*
  170          * Disable interrupts before we do anything.
  171          */
  172         AAC_MASK_INTERRUPTS(sc);
  173 
  174         /*
  175          * Initialise the adapter.
  176          */
  177         if (aac_check_firmware(sc))
  178                 return (EINVAL);
  179 
  180         if ((rv = aac_init(sc)) != 0)
  181                 return (rv);
  182         aac_startup(sc);
  183 
  184         /*
  185          * Print a little information about the controller.
  186          */
  187         aac_describe_controller(sc);
  188 
  189         /*
  190          * Initialize the ccbs.
  191          */
  192         sc->sc_ccbs = malloc(sizeof(*ac) * AAC_NCCBS, M_DEVBUF,
  193             M_NOWAIT | M_ZERO);
  194         if (sc->sc_ccbs == NULL) {
  195                 aprint_error("%s: memory allocation failure\n",
  196                     sc->sc_dv.dv_xname);
  197                 return (ENOMEM);
  198         }
  199         state = 0;
  200         size = sizeof(*fib) * AAC_NCCBS;
  201 
  202         if ((rv = bus_dmamap_create(sc->sc_dmat, size, 1, size,
  203             0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &sc->sc_fibs_dmamap)) != 0) {
  204                 aprint_error("%s: cannot create fibs dmamap\n",
  205                     sc->sc_dv.dv_xname);
  206                 goto bail_out;
  207         }
  208         state++;
  209         if ((rv = bus_dmamem_alloc(sc->sc_dmat, size, PAGE_SIZE, 0,
  210             &sc->sc_fibs_seg, 1, &nsegs, BUS_DMA_NOWAIT)) != 0) {
  211                 aprint_error("%s: can't allocate fibs structure\n",
  212                     sc->sc_dv.dv_xname);
  213                 goto bail_out;
  214         }
  215         state++;
  216         if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_fibs_seg, nsegs, size,
  217             (caddr_t *)&sc->sc_fibs, 0)) != 0) {
  218                 aprint_error("%s: can't map fibs structure\n",
  219                     sc->sc_dv.dv_xname);
  220                 goto bail_out;
  221         }
  222         state++;
  223         if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_fibs_dmamap, sc->sc_fibs,
  224             size, NULL, BUS_DMA_NOWAIT)) != 0) {
  225                 aprint_error("%s: cannot load fibs dmamap\n",
  226                     sc->sc_dv.dv_xname);
  227                 goto bail_out;
  228         }
  229         state++;
  230 
  231         memset(sc->sc_fibs, 0, size);
  232         fibpa = sc->sc_fibs_seg.ds_addr;
  233         fib = sc->sc_fibs;
  234 
  235         for (i = 0, ac = sc->sc_ccbs; i < AAC_NCCBS; i++, ac++) {
  236                 rv = bus_dmamap_create(sc->sc_dmat, AAC_MAX_XFER,
  237                     AAC_MAX_SGENTRIES, AAC_MAX_XFER, 0,
  238                     BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW, &ac->ac_dmamap_xfer);
  239                 if (rv) {
  240                         while (--ac >= sc->sc_ccbs)
  241                                 bus_dmamap_destroy(sc->sc_dmat,
  242                                     ac->ac_dmamap_xfer);
  243                         aprint_error("%s: cannot create ccb dmamap (%d)",
  244                             sc->sc_dv.dv_xname, rv);
  245                         goto bail_out;
  246                 }
  247 
  248                 ac->ac_fib = fib++;
  249                 ac->ac_fibphys = fibpa;
  250                 fibpa += sizeof(*fib);
  251                 aac_ccb_free(sc, ac);
  252         }
  253 
  254         /*
  255          * Attach devices.
  256          */
  257         for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
  258                 if (!sc->sc_hdr[i].hd_present)
  259                         continue;
  260                 aaca.aaca_unit = i;
  261 
  262                 ldesc->len = 1;
  263                 ldesc->locs[AACCF_UNIT] = i;
  264 
  265                 config_found_sm_loc(&sc->sc_dv, "aac", ldesc, &aaca,
  266                                     aac_print, aac_submatch);
  267         }
  268 
  269         /*
  270          * Enable interrupts, and register our shutdown hook.
  271          */
  272         sc->sc_flags |= AAC_ONLINE;
  273         AAC_UNMASK_INTERRUPTS(sc);
  274         if (aac_sdh != NULL)
  275                 shutdownhook_establish(aac_shutdown, NULL);
  276         return (0);
  277 
  278  bail_out:
  279         bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
  280         bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common,
  281             sizeof(*sc->sc_common));
  282         bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
  283         bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
  284 
  285         if (state > 3)
  286                 bus_dmamap_unload(sc->sc_dmat, sc->sc_fibs_dmamap);
  287         if (state > 2)
  288                 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_fibs, size);
  289         if (state > 1)
  290                 bus_dmamem_free(sc->sc_dmat, &sc->sc_fibs_seg, 1);
  291         if (state > 0)
  292                 bus_dmamap_destroy(sc->sc_dmat, sc->sc_fibs_dmamap);
  293 
  294         free(sc->sc_ccbs, M_DEVBUF);
  295         return (rv);
  296 }
  297 
  298 /*
  299  * Print autoconfiguration message for a sub-device.
  300  */
  301 static int
  302 aac_print(void *aux, const char *pnp)
  303 {
  304         struct aac_attach_args *aaca;
  305 
  306         aaca = aux;
  307 
  308         if (pnp != NULL)
  309                 aprint_normal("block device at %s", pnp);
  310         aprint_normal(" unit %d", aaca->aaca_unit);
  311         return (UNCONF);
  312 }
  313 
  314 /*
  315  * Match a sub-device.
  316  */
  317 static int
  318 aac_submatch(struct device *parent, struct cfdata *cf,
  319              const locdesc_t *ldesc, void *aux)
  320 {
  321         struct aac_attach_args *aaca;
  322 
  323         aaca = aux;
  324 
  325         if (cf->cf_loc[AACCF_UNIT] != AACCF_UNIT_DEFAULT &&
  326             cf->cf_loc[AACCF_UNIT] != ldesc->locs[AACCF_UNIT])
  327                 return (0);
  328 
  329         return (config_match(parent, cf, aux));
  330 }
  331 
  332 /*
  333  * Look up a text description of a numeric error code and return a pointer to
  334  * same.
  335  */
  336 const char *
  337 aac_describe_code(const struct aac_code_lookup *table, u_int32_t code)
  338 {
  339         int i;
  340 
  341         for (i = 0; table[i].string != NULL; i++)
  342                 if (table[i].code == code)
  343                         return (table[i].string);
  344 
  345         return (table[i + 1].string);
  346 }
  347 
  348 /*
  349  * bitmask_snprintf(9) format string for the adapter options.
  350  */
  351 static char *optfmt = 
  352     "\2\1SNAPSHOT\2CLUSTERS\3WCACHE\4DATA64\5HOSTTIME\6RAID50"
  353     "\7WINDOW4GB"
  354     "\10SCSIUPGD\11SOFTERR\12NORECOND\13SGMAP64\14ALARM\15NONDASD";
  355 
  356 static void
  357 aac_describe_controller(struct aac_softc *sc)
  358 {
  359         u_int8_t fmtbuf[256];
  360         u_int8_t buf[AAC_FIB_DATASIZE];
  361         u_int16_t bufsize;
  362         struct aac_adapter_info *info;
  363         u_int8_t arg;
  364 
  365         arg = 0;
  366         if (aac_sync_fib(sc, RequestAdapterInfo, 0, &arg, sizeof(arg), &buf,
  367             &bufsize)) {
  368                 aprint_error("%s: RequestAdapterInfo failed\n",
  369                     sc->sc_dv.dv_xname);
  370                 return;
  371         }
  372         if (bufsize != sizeof(*info)) {
  373                 aprint_error("%s: "
  374                     "RequestAdapterInfo returned wrong data size (%d != %d)\n",
  375                     sc->sc_dv.dv_xname, bufsize, sizeof(*info));
  376                 return;
  377         }
  378         info = (struct aac_adapter_info *)&buf[0];
  379 
  380         aprint_normal("%s: %s at %dMHz, %dMB mem (%dMB cache), %s\n",
  381             sc->sc_dv.dv_xname,
  382             aac_describe_code(aac_cpu_variant, le32toh(info->CpuVariant)),
  383             le32toh(info->ClockSpeed),
  384             le32toh(info->TotalMem) / (1024 * 1024),
  385             le32toh(info->BufferMem) / (1024 * 1024),
  386             aac_describe_code(aac_battery_platform,
  387                               le32toh(info->batteryPlatform)));
  388 
  389         aprint_verbose("%s: Kernel %d.%d-%d [Build %d], ",
  390             sc->sc_dv.dv_xname,
  391             info->KernelRevision.external.comp.major,
  392             info->KernelRevision.external.comp.minor,
  393             info->KernelRevision.external.comp.dash,
  394             info->KernelRevision.buildNumber);
  395 
  396         aprint_verbose("Monitor %d.%d-%d [Build %d], S/N %6X\n",
  397             info->MonitorRevision.external.comp.major,
  398             info->MonitorRevision.external.comp.minor,
  399             info->MonitorRevision.external.comp.dash,
  400             info->MonitorRevision.buildNumber,
  401             ((u_int32_t)info->SerialNumber & 0xffffff));
  402 
  403         aprint_verbose("%s: Controller supports: %s\n",
  404             sc->sc_dv.dv_xname,
  405             bitmask_snprintf(sc->sc_supported_options, optfmt, fmtbuf,
  406                              sizeof(fmtbuf)));
  407 
  408         /* Save the kernel revision structure for later use. */
  409         sc->sc_revision = info->KernelRevision;
  410 }
  411 
  412 /*
  413  * Retrieve the firmware version numbers.  Dell PERC2/QC cards with firmware
  414  * version 1.x are not compatible with this driver.
  415  */
  416 static int
  417 aac_check_firmware(struct aac_softc *sc)
  418 {
  419         u_int32_t major, minor, opts;
  420 
  421         if ((sc->sc_quirks & AAC_QUIRK_PERC2QC) != 0) {
  422                 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
  423                     NULL)) {
  424                         aprint_error("%s: error reading firmware version\n",
  425                             sc->sc_dv.dv_xname);
  426                         return (1);
  427                 }
  428 
  429                 /* These numbers are stored as ASCII! */
  430                 major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
  431                 minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
  432                 if (major == 1) {
  433                         aprint_error(
  434                             "%s: firmware version %d.%d not supported.\n",
  435                             sc->sc_dv.dv_xname, major, minor);
  436                         return (1);
  437                 }
  438         }
  439 
  440         if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) {
  441                 aprint_error("%s: GETINFO failed\n", sc->sc_dv.dv_xname);
  442                 return (1);
  443         }
  444         opts = AAC_GET_MAILBOX(sc, 1);
  445         sc->sc_supported_options = opts;
  446 
  447         /* XXX -- Enable 64-bit sglists if we can */
  448 
  449         return (0);
  450 }
  451 
  452 static int
  453 aac_init(struct aac_softc *sc)
  454 {
  455         int nsegs, i, rv, state, norm, high;
  456         struct aac_adapter_init *ip;
  457         u_int32_t code;
  458         u_int8_t *qaddr;
  459 
  460         state = 0;
  461 
  462         /*
  463          * First wait for the adapter to come ready.
  464          */
  465         for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
  466                 code = AAC_GET_FWSTATUS(sc);
  467                 if ((code & AAC_SELF_TEST_FAILED) != 0) {
  468                         aprint_error("%s: FATAL: selftest failed\n",
  469                             sc->sc_dv.dv_xname);
  470                         return (ENXIO);
  471                 }
  472                 if ((code & AAC_KERNEL_PANIC) != 0) {
  473                         aprint_error("%s: FATAL: controller kernel panic\n",
  474                             sc->sc_dv.dv_xname);
  475                         return (ENXIO);
  476                 }
  477                 if ((code & AAC_UP_AND_RUNNING) != 0)
  478                         break;
  479                 DELAY(1000);
  480         }
  481         if (i == AAC_BOOT_TIMEOUT * 1000) {
  482                 aprint_error(
  483                     "%s: FATAL: controller not coming ready, status %x\n",
  484                     sc->sc_dv.dv_xname, code);
  485                 return (ENXIO);
  486         }
  487 
  488         if ((rv = bus_dmamap_create(sc->sc_dmat, sizeof(*sc->sc_common), 1,
  489             sizeof(*sc->sc_common), 0, BUS_DMA_NOWAIT | BUS_DMA_ALLOCNOW,
  490             &sc->sc_common_dmamap)) != 0) {
  491                 aprint_error("%s: cannot create common dmamap\n",
  492                     sc->sc_dv.dv_xname);
  493                 return (rv);
  494         }
  495         if ((rv = bus_dmamem_alloc(sc->sc_dmat, sizeof(*sc->sc_common),
  496             PAGE_SIZE, 0, &sc->sc_common_seg, 1, &nsegs,
  497             BUS_DMA_NOWAIT)) != 0) {
  498                 aprint_error("%s: can't allocate common structure\n",
  499                     sc->sc_dv.dv_xname);
  500                 goto bail_out;
  501         }
  502         state++;
  503         if ((rv = bus_dmamem_map(sc->sc_dmat, &sc->sc_common_seg, nsegs,
  504             sizeof(*sc->sc_common), (caddr_t *)&sc->sc_common, 0)) != 0) {
  505                 aprint_error("%s: can't map common structure\n",
  506                     sc->sc_dv.dv_xname);
  507                 goto bail_out;
  508         }
  509         state++;
  510         if ((rv = bus_dmamap_load(sc->sc_dmat, sc->sc_common_dmamap,
  511             sc->sc_common, sizeof(*sc->sc_common), NULL,
  512             BUS_DMA_NOWAIT)) != 0) {
  513                 aprint_error("%s: cannot load common dmamap\n",
  514                     sc->sc_dv.dv_xname);
  515                 goto bail_out;
  516         }
  517         state++;
  518 
  519         memset(sc->sc_common, 0, sizeof(*sc->sc_common));
  520 
  521         /*
  522          * Fill in the init structure.  This tells the adapter about the
  523          * physical location of various important shared data structures.
  524          */
  525         ip = &sc->sc_common->ac_init;
  526         ip->InitStructRevision = htole32(AAC_INIT_STRUCT_REVISION);
  527 
  528         ip->AdapterFibsPhysicalAddress = htole32(sc->sc_common_seg.ds_addr +
  529             offsetof(struct aac_common, ac_fibs));
  530         ip->AdapterFibsVirtualAddress =
  531             (void *)(intptr_t) htole32(&sc->sc_common->ac_fibs[0]);
  532         ip->AdapterFibsSize =
  533             htole32(AAC_ADAPTER_FIBS * sizeof(struct aac_fib));
  534         ip->AdapterFibAlign = htole32(sizeof(struct aac_fib));
  535 
  536         ip->PrintfBufferAddress = htole32(sc->sc_common_seg.ds_addr +
  537             offsetof(struct aac_common, ac_printf));
  538         ip->PrintfBufferSize = htole32(AAC_PRINTF_BUFSIZE);
  539 
  540         ip->HostPhysMemPages = 0;       /* not used? */
  541         ip->HostElapsedSeconds = 0;     /* reset later if invalid */
  542 
  543         /*
  544          * Initialise FIB queues.  Note that it appears that the layout of
  545          * the indexes and the segmentation of the entries is mandated by
  546          * the adapter, which is only told about the base of the queue index
  547          * fields.
  548          *
  549          * The initial values of the indices are assumed to inform the
  550          * adapter of the sizes of the respective queues.
  551          *
  552          * The Linux driver uses a much more complex scheme whereby several
  553          * header records are kept for each queue.  We use a couple of
  554          * generic list manipulation functions which 'know' the size of each
  555          * list by virtue of a table.
  556          */
  557         qaddr = &sc->sc_common->ac_qbuf[0] + AAC_QUEUE_ALIGN;
  558         qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN;    /* XXX not portable */
  559         sc->sc_queues = (struct aac_queue_table *)qaddr;
  560         ip->CommHeaderAddress = htole32(sc->sc_common_seg.ds_addr +
  561             ((caddr_t)sc->sc_queues - (caddr_t)sc->sc_common));
  562         memset(sc->sc_queues, 0, sizeof(struct aac_queue_table));
  563 
  564         norm = htole32(AAC_HOST_NORM_CMD_ENTRIES);
  565         high = htole32(AAC_HOST_HIGH_CMD_ENTRIES);
  566 
  567         sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
  568             norm;
  569         sc->sc_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
  570             norm;
  571         sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
  572             high;
  573         sc->sc_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
  574             high;
  575 
  576         norm = htole32(AAC_ADAP_NORM_CMD_ENTRIES);
  577         high = htole32(AAC_ADAP_HIGH_CMD_ENTRIES);
  578 
  579         sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
  580             norm;
  581         sc->sc_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
  582             norm;
  583         sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
  584             high;
  585         sc->sc_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
  586             high;
  587 
  588         norm = htole32(AAC_HOST_NORM_RESP_ENTRIES);
  589         high = htole32(AAC_HOST_HIGH_RESP_ENTRIES);
  590 
  591         sc->sc_queues->
  592             qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
  593         sc->sc_queues->
  594             qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
  595         sc->sc_queues->
  596             qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
  597         sc->sc_queues->
  598             qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
  599 
  600         norm = htole32(AAC_ADAP_NORM_RESP_ENTRIES);
  601         high = htole32(AAC_ADAP_HIGH_RESP_ENTRIES);
  602 
  603         sc->sc_queues->
  604             qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX] = norm;
  605         sc->sc_queues->
  606             qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX] = norm;
  607         sc->sc_queues->
  608             qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX] = high;
  609         sc->sc_queues->
  610             qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX] = high;
  611 
  612         sc->sc_qentries[AAC_HOST_NORM_CMD_QUEUE] =
  613             &sc->sc_queues->qt_HostNormCmdQueue[0];
  614         sc->sc_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
  615             &sc->sc_queues->qt_HostHighCmdQueue[0];
  616         sc->sc_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
  617             &sc->sc_queues->qt_AdapNormCmdQueue[0];
  618         sc->sc_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
  619             &sc->sc_queues->qt_AdapHighCmdQueue[0];
  620         sc->sc_qentries[AAC_HOST_NORM_RESP_QUEUE] =
  621             &sc->sc_queues->qt_HostNormRespQueue[0];
  622         sc->sc_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
  623             &sc->sc_queues->qt_HostHighRespQueue[0];
  624         sc->sc_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
  625             &sc->sc_queues->qt_AdapNormRespQueue[0];
  626         sc->sc_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
  627             &sc->sc_queues->qt_AdapHighRespQueue[0];
  628 
  629         /*
  630          * Do controller-type-specific initialisation
  631          */
  632         switch (sc->sc_hwif) {
  633         case AAC_HWIF_I960RX:
  634                 AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
  635                 break;
  636         }
  637 
  638         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap, 0,
  639             sizeof(*sc->sc_common),
  640             BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
  641 
  642         /*
  643          * Give the init structure to the controller.
  644          */
  645         if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
  646             sc->sc_common_seg.ds_addr + offsetof(struct aac_common, ac_init),
  647             0, 0, 0, NULL)) {
  648                 aprint_error("%s: error establishing init structure\n",
  649                     sc->sc_dv.dv_xname);
  650                 rv = EIO;
  651                 goto bail_out;
  652         }
  653 
  654         return (0);
  655 
  656  bail_out:
  657         if (state > 2)
  658                 bus_dmamap_unload(sc->sc_dmat, sc->sc_common_dmamap);
  659         if (state > 1)
  660                 bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_common,
  661                     sizeof(*sc->sc_common));
  662         if (state > 0)
  663                 bus_dmamem_free(sc->sc_dmat, &sc->sc_common_seg, 1);
  664         bus_dmamap_destroy(sc->sc_dmat, sc->sc_common_dmamap);
  665 
  666         return (rv);
  667 }
  668 
  669 /*
  670  * Probe for containers, create disks.
  671  */
  672 static void
  673 aac_startup(struct aac_softc *sc)
  674 {
  675         struct aac_mntinfo mi;
  676         struct aac_mntinforesponse mir;
  677         struct aac_drive *hd;
  678         u_int16_t rsize;
  679         int i;
  680 
  681         /*
  682          * Loop over possible containers.
  683          */
  684         hd = sc->sc_hdr;
  685 
  686         for (i = 0; i < AAC_MAX_CONTAINERS; i++, hd++) {
  687                 /*
  688                  * Request information on this container.
  689                  */
  690                 memset(&mi, 0, sizeof(mi));
  691                 mi.Command = htole32(VM_NameServe);
  692                 mi.MntType = htole32(FT_FILESYS);
  693                 mi.MntCount = htole32(i);
  694                 if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi), &mir,
  695                     &rsize)) {
  696                         aprint_error("%s: error probing container %d\n",
  697                             sc->sc_dv.dv_xname, i);
  698                         continue;
  699                 }
  700                 if (rsize != sizeof(mir)) {
  701                         aprint_error("%s: container info response wrong size "
  702                             "(%d should be %d)\n",
  703                             sc->sc_dv.dv_xname, rsize, sizeof(mir));
  704                         continue;
  705                 }
  706 
  707                 /*
  708                  * Check container volume type for validity.  Note that many
  709                  * of the possible types may never show up.
  710                  */
  711                 if (le32toh(mir.Status) != ST_OK ||
  712                     le32toh(mir.MntTable[0].VolType) == CT_NONE)
  713                         continue;
  714 
  715                 hd->hd_present = 1;
  716                 hd->hd_size = le32toh(mir.MntTable[0].Capacity);
  717                 hd->hd_devtype = le32toh(mir.MntTable[0].VolType);
  718                 hd->hd_size &= ~0x1f;
  719                 sc->sc_nunits++;
  720         }
  721 }
  722 
  723 static void
  724 aac_shutdown(void *cookie)
  725 {
  726         struct aac_softc *sc;
  727         struct aac_close_command cc;
  728         u_int32_t i;
  729 
  730         for (i = 0; i < aac_cd.cd_ndevs; i++) {
  731                 if ((sc = device_lookup(&aac_cd, i)) == NULL)
  732                         continue;
  733                 if ((sc->sc_flags & AAC_ONLINE) == 0)
  734                         continue;
  735 
  736                 AAC_MASK_INTERRUPTS(sc);
  737 
  738                 /*
  739                  * Send a Container shutdown followed by a HostShutdown FIB
  740                  * to the controller to convince it that we don't want to
  741                  * talk to it anymore.  We've been closed and all I/O
  742                  * completed already
  743                  */
  744                 memset(&cc, 0, sizeof(cc));
  745                 cc.Command = htole32(VM_CloseAll);
  746                 cc.ContainerId = 0xffffffff;
  747                 if (aac_sync_fib(sc, ContainerCommand, 0, &cc, sizeof(cc),
  748                     NULL, NULL)) {
  749                         printf("%s: unable to halt controller\n",
  750                             sc->sc_dv.dv_xname);
  751                         continue;
  752                 }
  753 
  754                 /*
  755                  * Note that issuing this command to the controller makes it
  756                  * shut down but also keeps it from coming back up without a
  757                  * reset of the PCI bus.
  758                  */
  759                 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
  760                     &i, sizeof(i), NULL, NULL))
  761                         printf("%s: unable to halt controller\n",
  762                             sc->sc_dv.dv_xname);
  763 
  764                 sc->sc_flags &= ~AAC_ONLINE;
  765         }
  766 }
  767 
  768 /*
  769  * Take an interrupt.
  770  */
  771 int
  772 aac_intr(void *cookie)
  773 {
  774         struct aac_softc *sc;
  775         u_int16_t reason;
  776         int claimed;
  777 
  778         sc = cookie;
  779         claimed = 0;
  780 
  781         AAC_DPRINTF(AAC_D_INTR, ("aac_intr(%p) ", sc));
  782 
  783         reason = AAC_GET_ISTATUS(sc);
  784         AAC_DPRINTF(AAC_D_INTR, ("istatus 0x%04x ", reason));
  785 
  786         /*
  787          * Controller wants to talk to the log.  XXX Should we defer this?
  788          */
  789         if ((reason & AAC_DB_PRINTF) != 0) {
  790                 if (sc->sc_common->ac_printf[0] != '\0') {
  791                         printf("%s: WARNING: adapter logged message:\n",
  792                             sc->sc_dv.dv_xname);
  793                         printf("%s:     %.*s", sc->sc_dv.dv_xname,
  794                             AAC_PRINTF_BUFSIZE, sc->sc_common->ac_printf);
  795                         sc->sc_common->ac_printf[0] = '\0';
  796                 }
  797                 AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
  798                 AAC_QNOTIFY(sc, AAC_DB_PRINTF);
  799                 claimed = 1;
  800         }
  801 
  802         /*
  803          * Controller has a message for us?
  804          */
  805         if ((reason & AAC_DB_COMMAND_READY) != 0) {
  806                 aac_host_command(sc);
  807                 AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
  808                 claimed = 1;
  809         }
  810 
  811         /*
  812          * Controller has a response for us?
  813          */
  814         if ((reason & AAC_DB_RESPONSE_READY) != 0) {
  815                 aac_host_response(sc);
  816                 AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
  817                 claimed = 1;
  818         }
  819 
  820         /*
  821          * Spurious interrupts that we don't use - reset the mask and clear
  822          * the interrupts.
  823          */
  824         if ((reason & (AAC_DB_SYNC_COMMAND | AAC_DB_COMMAND_NOT_FULL |
  825             AAC_DB_RESPONSE_NOT_FULL)) != 0) {
  826                 AAC_UNMASK_INTERRUPTS(sc);
  827                 AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND |
  828                     AAC_DB_COMMAND_NOT_FULL | AAC_DB_RESPONSE_NOT_FULL);
  829                 claimed = 1;
  830         }
  831 
  832         return (claimed);
  833 }
  834 
  835 /*
  836  * Handle notification of one or more FIBs coming from the controller.
  837  */
  838 static void
  839 aac_host_command(struct aac_softc *sc)
  840 {
  841         struct aac_fib *fib;
  842         u_int32_t fib_size;
  843 
  844         for (;;) {
  845                 if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size,
  846                     &fib))
  847                         break;  /* nothing to do */
  848 
  849                 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
  850                     (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
  851                     BUS_DMASYNC_POSTREAD);
  852 
  853                 switch (le16toh(fib->Header.Command)) {
  854                 case AifRequest:
  855 #ifdef notyet
  856                         aac_handle_aif(sc,
  857                             (struct aac_aif_command *)&fib->data[0]);
  858 #endif
  859                         break;
  860                 default:
  861                         printf("%s: unknown command from controller\n",
  862                             sc->sc_dv.dv_xname);
  863                         AAC_PRINT_FIB(sc, fib);
  864                         break;
  865                 }
  866 
  867                 bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
  868                     (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
  869                     BUS_DMASYNC_PREREAD);
  870 
  871                 /* XXX reply to FIBs requesting responses ?? */
  872                 /* XXX how do we return these FIBs to the controller? */
  873         }
  874 }
  875 
  876 /*
  877  * Handle notification of one or more FIBs completed by the controller
  878  */
  879 static void
  880 aac_host_response(struct aac_softc *sc)
  881 {
  882         struct aac_ccb *ac;
  883         struct aac_fib *fib;
  884         u_int32_t fib_size;
  885 
  886         /*
  887          * Look for completed FIBs on our queue.
  888          */
  889         for (;;) {
  890                 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
  891                     &fib))
  892                         break;  /* nothing to do */
  893 
  894                 bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
  895                     (caddr_t)fib - (caddr_t)sc->sc_fibs, sizeof(*fib),
  896                     BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
  897 
  898                 if ((fib->Header.SenderData & 0x80000000) == 0) {
  899                         /* Not valid; not sent by us. */
  900                         AAC_PRINT_FIB(sc, fib);
  901                 } else {
  902                         ac = (struct aac_ccb *)((caddr_t)sc->sc_ccbs +
  903                             (fib->Header.SenderData & 0x7fffffff));
  904                         fib->Header.SenderData = 0;
  905                         SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_complete, ac, ac_chain);
  906                 }
  907         }
  908 
  909         /*
  910          * Deal with any completed commands.
  911          */
  912         while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_complete)) != NULL) {
  913                 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_complete, ac_chain);
  914                 ac->ac_flags |= AAC_CCB_COMPLETED;
  915 
  916                 if (ac->ac_intr != NULL)
  917                         (*ac->ac_intr)(ac);
  918         }
  919 
  920         /*
  921          * Try to submit more commands.
  922          */
  923         if (! SIMPLEQ_EMPTY(&sc->sc_ccb_queue))
  924                 aac_ccb_enqueue(sc, NULL);
  925 }
  926 
  927 /*
  928  * Send a synchronous command to the controller and wait for a result.
  929  */
  930 static int
  931 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
  932                  u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
  933 {
  934         int i;
  935         u_int32_t status;
  936         int s;
  937 
  938         s = splbio();
  939 
  940         /* Populate the mailbox. */
  941         AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
  942 
  943         /* Ensure the sync command doorbell flag is cleared. */
  944         AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
  945 
  946         /* ... then set it to signal the adapter. */
  947         AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
  948         DELAY(AAC_SYNC_DELAY);
  949 
  950         /* Spin waiting for the command to complete. */
  951         for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
  952                 if (AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)
  953                         break;
  954                 DELAY(1000);
  955         }
  956         if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
  957                 splx(s);
  958                 return (EIO);
  959         }
  960 
  961         /* Clear the completion flag. */
  962         AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
  963 
  964         /* Get the command status. */
  965         status = AAC_GET_MAILBOXSTATUS(sc);
  966         splx(s);
  967         if (sp != NULL)
  968                 *sp = status;
  969 
  970         return (0);     /* XXX Check command return status? */
  971 }
  972 
  973 /*
  974  * Send a synchronous FIB to the controller and wait for a result.
  975  */
  976 static int
  977 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
  978              void *data, u_int16_t datasize, void *result,
  979              u_int16_t *resultsize)
  980 {
  981         struct aac_fib *fib;
  982         u_int32_t fibpa, status;
  983 
  984         fib = &sc->sc_common->ac_sync_fib;
  985         fibpa = sc->sc_common_seg.ds_addr +
  986             offsetof(struct aac_common, ac_sync_fib);
  987 
  988         if (datasize > AAC_FIB_DATASIZE)
  989                 return (EINVAL);
  990 
  991         /*
  992          * Set up the sync FIB.
  993          */
  994         fib->Header.XferState = htole32(AAC_FIBSTATE_HOSTOWNED |
  995             AAC_FIBSTATE_INITIALISED | AAC_FIBSTATE_EMPTY | xferstate);
  996         fib->Header.Command = htole16(command);
  997         fib->Header.StructType = AAC_FIBTYPE_TFIB;
  998         fib->Header.Size = htole16(sizeof(*fib) + datasize);
  999         fib->Header.SenderSize = htole16(sizeof(*fib));
 1000         fib->Header.SenderFibAddress = 0; /* htole32((u_int32_t)fib);   * XXX */
 1001         fib->Header.ReceiverFibAddress = htole32(fibpa);
 1002 
 1003         /*
 1004          * Copy in data.
 1005          */
 1006         if (data != NULL) {
 1007                 memcpy(fib->data, data, datasize);
 1008                 fib->Header.XferState |=
 1009                     htole32(AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_NORM);
 1010         }
 1011 
 1012         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1013             (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
 1014             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1015 
 1016         /*
 1017          * Give the FIB to the controller, wait for a response.
 1018          */
 1019         if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fibpa, 0, 0, 0, &status))
 1020                 return (EIO);
 1021         if (status != 1) {
 1022                 printf("%s: syncfib command %04x status %08x\n",
 1023                         sc->sc_dv.dv_xname, command, status);
 1024         }
 1025 
 1026         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1027             (caddr_t)fib - (caddr_t)sc->sc_common, sizeof(*fib),
 1028             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 1029 
 1030         /*
 1031          * Copy out the result
 1032          */
 1033         if (result != NULL) {
 1034                 *resultsize = le16toh(fib->Header.Size) - sizeof(fib->Header);
 1035                 memcpy(result, fib->data, *resultsize);
 1036         }
 1037 
 1038         return (0);
 1039 }
 1040 
 1041 struct aac_ccb *
 1042 aac_ccb_alloc(struct aac_softc *sc, int flags)
 1043 {
 1044         struct aac_ccb *ac;
 1045         int s;
 1046 
 1047         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_alloc(%p, 0x%x) ", sc, flags));
 1048 
 1049         s = splbio();
 1050         ac = SIMPLEQ_FIRST(&sc->sc_ccb_free);
 1051 #ifdef DIAGNOSTIC
 1052         if (ac == NULL)
 1053                 panic("aac_ccb_get: no free CCBS");
 1054 #endif
 1055         SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_free, ac_chain);
 1056         splx(s);
 1057 
 1058         ac->ac_flags = flags;
 1059         return (ac);
 1060 }
 1061 
 1062 void
 1063 aac_ccb_free(struct aac_softc *sc, struct aac_ccb *ac)
 1064 {
 1065         int s;
 1066 
 1067         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_free(%p, %p) ", sc, ac));
 1068 
 1069         ac->ac_flags = 0;
 1070         ac->ac_intr = NULL;
 1071         ac->ac_fib->Header.XferState = htole32(AAC_FIBSTATE_EMPTY);
 1072         ac->ac_fib->Header.StructType = AAC_FIBTYPE_TFIB;
 1073         ac->ac_fib->Header.Flags = 0;
 1074         ac->ac_fib->Header.SenderSize = htole16(sizeof(*ac->ac_fib));
 1075 
 1076 #ifdef AAC_DEBUG
 1077         /*
 1078          * These are duplicated in aac_ccb_submit() to cover the case where
 1079          * an intermediate stage may have destroyed them.  They're left
 1080          * initialised here for debugging purposes only.
 1081          */
 1082         ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)ac->ac_fib);
 1083         ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
 1084 #endif
 1085 
 1086         s = splbio();
 1087         SIMPLEQ_INSERT_HEAD(&sc->sc_ccb_free, ac, ac_chain);
 1088         splx(s);
 1089 }
 1090 
 1091 int
 1092 aac_ccb_map(struct aac_softc *sc, struct aac_ccb *ac)
 1093 {
 1094         int error;
 1095 
 1096         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_map(%p, %p) ", sc, ac));
 1097 
 1098 #ifdef DIAGNOSTIC
 1099         if ((ac->ac_flags & AAC_CCB_MAPPED) != 0)
 1100                 panic("aac_ccb_map: already mapped");
 1101 #endif
 1102 
 1103         error = bus_dmamap_load(sc->sc_dmat, ac->ac_dmamap_xfer, ac->ac_data,
 1104             ac->ac_datalen, NULL, BUS_DMA_NOWAIT | BUS_DMA_STREAMING |
 1105             ((ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMA_READ : BUS_DMA_WRITE));
 1106         if (error) {
 1107                 printf("%s: aac_ccb_map: ", sc->sc_dv.dv_xname);
 1108                 if (error == EFBIG)
 1109                         printf("more than %d DMA segs\n", AAC_MAX_SGENTRIES);
 1110                 else
 1111                         printf("error %d loading DMA map\n", error);
 1112                 return (error);
 1113         }
 1114 
 1115         bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
 1116             (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_PREREAD :
 1117             BUS_DMASYNC_PREWRITE);
 1118 
 1119 #ifdef DIAGNOSTIC
 1120         ac->ac_flags |= AAC_CCB_MAPPED;
 1121 #endif
 1122         return (0);
 1123 }
 1124 
 1125 void
 1126 aac_ccb_unmap(struct aac_softc *sc, struct aac_ccb *ac)
 1127 {
 1128 
 1129         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_unmap(%p, %p) ", sc, ac));
 1130 
 1131 #ifdef DIAGNOSTIC
 1132         if ((ac->ac_flags & AAC_CCB_MAPPED) == 0)
 1133                 panic("aac_ccb_unmap: not mapped");
 1134 #endif
 1135 
 1136         bus_dmamap_sync(sc->sc_dmat, ac->ac_dmamap_xfer, 0, ac->ac_datalen,
 1137             (ac->ac_flags & AAC_CCB_DATA_IN) ? BUS_DMASYNC_POSTREAD :
 1138             BUS_DMASYNC_POSTWRITE);
 1139         bus_dmamap_unload(sc->sc_dmat, ac->ac_dmamap_xfer);
 1140 
 1141 #ifdef DIAGNOSTIC
 1142         ac->ac_flags &= ~AAC_CCB_MAPPED;
 1143 #endif
 1144 }
 1145 
 1146 void
 1147 aac_ccb_enqueue(struct aac_softc *sc, struct aac_ccb *ac)
 1148 {
 1149         int s;
 1150 
 1151         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_enqueue(%p, %p) ", sc, ac));
 1152 
 1153         s = splbio();
 1154 
 1155         if (ac != NULL)
 1156                 SIMPLEQ_INSERT_TAIL(&sc->sc_ccb_queue, ac, ac_chain);
 1157 
 1158         while ((ac = SIMPLEQ_FIRST(&sc->sc_ccb_queue)) != NULL) {
 1159                 if (aac_ccb_submit(sc, ac))
 1160                         break;
 1161                 SIMPLEQ_REMOVE_HEAD(&sc->sc_ccb_queue, ac_chain);
 1162         }
 1163 
 1164         splx(s);
 1165 }
 1166 
 1167 int
 1168 aac_ccb_submit(struct aac_softc *sc, struct aac_ccb *ac)
 1169 {
 1170 
 1171         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_submit(%p, %p) ", sc, ac));
 1172 
 1173         /* Fix up the address values. */
 1174         ac->ac_fib->Header.SenderFibAddress = htole32((u_int32_t)ac->ac_fib);
 1175         ac->ac_fib->Header.ReceiverFibAddress = htole32(ac->ac_fibphys);
 1176 
 1177         /* Save a pointer to the command for speedy reverse-lookup. */
 1178         ac->ac_fib->Header.SenderData =
 1179             (u_int32_t)((caddr_t)ac - (caddr_t)sc->sc_ccbs) | 0x80000000;
 1180 
 1181         bus_dmamap_sync(sc->sc_dmat, sc->sc_fibs_dmamap,
 1182             (caddr_t)ac->ac_fib - (caddr_t)sc->sc_fibs, sizeof(*ac->ac_fib),
 1183             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1184 
 1185         /* Put the FIB on the outbound queue. */
 1186         return (aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, ac->ac_fib));
 1187 }
 1188 
 1189 int
 1190 aac_ccb_poll(struct aac_softc *sc, struct aac_ccb *ac, int timo)
 1191 {
 1192         int rv, s;
 1193 
 1194         AAC_DPRINTF(AAC_D_QUEUE, ("aac_ccb_poll(%p, %p, %d) ", sc, ac, timo));
 1195 
 1196         s = splbio();
 1197 
 1198         if ((rv = aac_ccb_submit(sc, ac)) != 0) {
 1199                 splx(s);
 1200                 return (rv);
 1201         }
 1202 
 1203         for (timo *= 1000; timo != 0; timo--) {
 1204                 aac_intr(sc);
 1205                 if ((ac->ac_flags & AAC_CCB_COMPLETED) != 0)
 1206                         break;
 1207                 DELAY(100);
 1208         }
 1209 
 1210         splx(s);
 1211         return (timo == 0);
 1212 }
 1213 
 1214 /*
 1215  * Atomically insert an entry into the nominated queue, returns 0 on success
 1216  * or EBUSY if the queue is full.
 1217  *
 1218  * XXX Note that it would be more efficient to defer notifying the
 1219  * controller in the case where we may be inserting several entries in rapid
 1220  * succession, but implementing this usefully is difficult.
 1221  */
 1222 static int
 1223 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_fib *fib)
 1224 {
 1225         u_int32_t fib_size, fib_addr, pi, ci;
 1226 
 1227         fib_size = le16toh(fib->Header.Size);
 1228         fib_addr = le32toh(fib->Header.ReceiverFibAddress);
 1229 
 1230         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1231             (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
 1232             sizeof(sc->sc_common->ac_qbuf),
 1233             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 1234 
 1235         /* Get the producer/consumer indices.  */
 1236         pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
 1237         ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
 1238 
 1239         /* Wrap the queue? */
 1240         if (pi >= aac_qinfo[queue].size)
 1241                 pi = 0;
 1242 
 1243         /* Check for queue full. */
 1244         if ((pi + 1) == ci)
 1245                 return (EAGAIN);
 1246 
 1247         /* Populate queue entry. */
 1248         (sc->sc_qentries[queue] + pi)->aq_fib_size = htole32(fib_size);
 1249         (sc->sc_qentries[queue] + pi)->aq_fib_addr = htole32(fib_addr);
 1250 
 1251         /* Update producer index. */
 1252         sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = htole32(pi + 1);
 1253 
 1254         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1255             (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
 1256             sizeof(sc->sc_common->ac_qbuf),
 1257             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1258 
 1259         /* Notify the adapter if we know how. */
 1260         if (aac_qinfo[queue].notify != 0)
 1261                 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
 1262 
 1263         return (0);
 1264 }
 1265 
 1266 /*
 1267  * Atomically remove one entry from the nominated queue, returns 0 on success
 1268  * or ENOENT if the queue is empty.
 1269  */
 1270 static int
 1271 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
 1272                 struct aac_fib **fib_addr)
 1273 {
 1274         u_int32_t pi, ci;
 1275         int notify;
 1276 
 1277         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1278             (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
 1279             sizeof(sc->sc_common->ac_qbuf),
 1280             BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
 1281 
 1282         /* Get the producer/consumer indices. */
 1283         pi = le32toh(sc->sc_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]);
 1284         ci = le32toh(sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX]);
 1285 
 1286         /* Check for queue empty. */
 1287         if (ci == pi)
 1288                 return (ENOENT);
 1289 
 1290         notify = 0;
 1291         if (ci == pi + 1)
 1292                 notify = 1;
 1293 
 1294         /* Wrap the queue? */
 1295         if (ci >= aac_qinfo[queue].size)
 1296                 ci = 0;
 1297 
 1298         /* Fetch the entry. */
 1299         *fib_size = le32toh((sc->sc_qentries[queue] + ci)->aq_fib_size);
 1300         *fib_addr = (void *)(intptr_t) le32toh((struct aac_fib *)
 1301             (sc->sc_qentries[queue] + ci)->aq_fib_addr);
 1302 
 1303         /* Update consumer index. */
 1304         sc->sc_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
 1305 
 1306         bus_dmamap_sync(sc->sc_dmat, sc->sc_common_dmamap,
 1307             (caddr_t)sc->sc_common->ac_qbuf - (caddr_t)sc->sc_common,
 1308             sizeof(sc->sc_common->ac_qbuf),
 1309             BUS_DMASYNC_PREWRITE | BUS_DMASYNC_PREREAD);
 1310 
 1311         /* If we have made the queue un-full, notify the adapter. */
 1312         if (notify && (aac_qinfo[queue].notify != 0))
 1313                 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
 1314 
 1315         return (0);
 1316 }
 1317 
 1318 #ifdef AAC_DEBUG
 1319 /*
 1320  * Print a FIB
 1321  */
 1322 static void
 1323 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, char *caller)
 1324 {
 1325         struct aac_blockread *br;
 1326         struct aac_blockwrite *bw;
 1327         struct aac_sg_table *sg;
 1328         char buf[512];
 1329         int i;
 1330 
 1331         printf("%s: FIB @ %p\n", caller, fib);
 1332         bitmask_snprintf(le32toh(fib->Header.XferState),
 1333             "\2"
 1334             "\1HOSTOWNED"
 1335             "\2ADAPTEROWNED"
 1336             "\3INITIALISED"
 1337             "\4EMPTY"
 1338             "\5FROMPOOL"
 1339             "\6FROMHOST"
 1340             "\7FROMADAP"
 1341             "\10REXPECTED"
 1342             "\11RNOTEXPECTED"
 1343             "\12DONEADAP"
 1344             "\13DONEHOST"
 1345             "\14HIGH"
 1346             "\15NORM"
 1347             "\16ASYNC"
 1348             "\17PAGEFILEIO"
 1349             "\20SHUTDOWN"
 1350             "\21LAZYWRITE"
 1351             "\22ADAPMICROFIB"
 1352             "\23BIOSFIB"
 1353             "\24FAST_RESPONSE"
 1354             "\25APIFIB\n",
 1355             buf,
 1356             sizeof(buf));
 1357 
 1358         printf("  XferState       %s\n", buf);
 1359         printf("  Command         %d\n", le16toh(fib->Header.Command));
 1360         printf("  StructType      %d\n", fib->Header.StructType);
 1361         printf("  Flags           0x%x\n", fib->Header.Flags);
 1362         printf("  Size            %d\n", le16toh(fib->Header.Size));
 1363         printf("  SenderSize      %d\n", le16toh(fib->Header.SenderSize));
 1364         printf("  SenderAddress   0x%x\n",
 1365             le32toh(fib->Header.SenderFibAddress));
 1366         printf("  ReceiverAddress 0x%x\n",
 1367             le32toh(fib->Header.ReceiverFibAddress));
 1368         printf("  SenderData      0x%x\n", fib->Header.SenderData);
 1369 
 1370         switch (fib->Header.Command) {
 1371         case ContainerCommand: {
 1372                 br = (struct aac_blockread *)fib->data;
 1373                 bw = (struct aac_blockwrite *)fib->data;
 1374                 sg = NULL;
 1375 
 1376                 if (le32toh(br->Command) == VM_CtBlockRead) {
 1377                         printf("  BlockRead: container %d  0x%x/%d\n",
 1378                             le32toh(br->ContainerId), le32toh(br->BlockNumber),
 1379                             le32toh(br->ByteCount));
 1380                         sg = &br->SgMap;
 1381                 }
 1382                 if (le32toh(bw->Command) == VM_CtBlockWrite) {
 1383                         printf("  BlockWrite: container %d  0x%x/%d (%s)\n",
 1384                             le32toh(bw->ContainerId), le32toh(bw->BlockNumber),
 1385                             le32toh(bw->ByteCount),
 1386                             le32toh(bw->Stable) == CSTABLE ?
 1387                             "stable" : "unstable");
 1388                         sg = &bw->SgMap;
 1389                 }
 1390                 if (sg != NULL) {
 1391                         printf("  %d s/g entries\n", le32toh(sg->SgCount));
 1392                         for (i = 0; i < le32toh(sg->SgCount); i++)
 1393                                 printf("  0x%08x/%d\n",
 1394                                     le32toh(sg->SgEntry[i].SgAddress),
 1395                                     le32toh(sg->SgEntry[i].SgByteCount));
 1396                 }
 1397                 break;
 1398         }
 1399         default:
 1400                 printf("   %16D\n", fib->data, " ");
 1401                 printf("   %16D\n", fib->data + 16, " ");
 1402                 break;
 1403         }
 1404 }
 1405 #endif /* AAC_DEBUG */

Cache object: 1e80a9da1532f880d25510ef5e3db4e7


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