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

Cache object: b3ba7162fcdd676940646db9626b543a


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