root/dev/ic/aac.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. aac_attach
  2. aac_create_thread
  3. aac_startup
  4. aac_add_container
  5. aac_free
  6. aac_detach
  7. aac_shutdown
  8. aac_suspend
  9. aac_resume
  10. aac_intr
  11. aac_startio
  12. aac_map_command
  13. aac_command_thread
  14. aac_complete
  15. aac_bio_command
  16. aac_bio_complete
  17. aac_wait_command
  18. aac_alloc_command
  19. aac_release_command
  20. aac_alloc_commands
  21. aac_free_commands
  22. aac_map_command_sg
  23. aac_unmap_command
  24. aac_check_firmware
  25. aac_init
  26. aac_sync_command
  27. aac_alloc_sync_fib
  28. aac_release_sync_fib
  29. aac_sync_fib
  30. aac_enqueue_fib
  31. aac_dequeue_fib
  32. aac_enqueue_response
  33. aac_command_timeout
  34. aac_timeout
  35. aac_sa_get_fwstatus
  36. aac_rx_get_fwstatus
  37. aac_fa_get_fwstatus
  38. aac_rkt_get_fwstatus
  39. aac_sa_qnotify
  40. aac_rx_qnotify
  41. aac_fa_qnotify
  42. aac_rkt_qnotify
  43. aac_sa_get_istatus
  44. aac_rx_get_istatus
  45. aac_fa_get_istatus
  46. aac_rkt_get_istatus
  47. aac_sa_clear_istatus
  48. aac_rx_clear_istatus
  49. aac_fa_clear_istatus
  50. aac_rkt_clear_istatus
  51. aac_sa_set_mailbox
  52. aac_rx_set_mailbox
  53. aac_fa_set_mailbox
  54. aac_rkt_set_mailbox
  55. aac_sa_get_mailbox
  56. aac_rx_get_mailbox
  57. aac_fa_get_mailbox
  58. aac_rkt_get_mailbox
  59. aac_sa_set_interrupts
  60. aac_rx_set_interrupts
  61. aac_fa_set_interrupts
  62. aac_rkt_set_interrupts
  63. aac_eval_mapping
  64. aac_copy_internal_data
  65. aac_internal_cache_cmd
  66. aacminphys
  67. aac_raw_scsi_cmd
  68. aac_scsi_cmd
  69. aac_describe_controller
  70. aac_describe_code
  71. aac_print_fib
  72. aac_print_aif

    1 /*      $OpenBSD: aac.c,v 1.35 2007/03/20 10:30:32 mickey Exp $ */
    2 
    3 /*-
    4  * Copyright (c) 2000 Michael Smith
    5  * Copyright (c) 2001 Scott Long
    6  * Copyright (c) 2000 BSDi
    7  * Copyright (c) 2001 Adaptec, Inc.
    8  * Copyright (c) 2000 Niklas Hallqvist
    9  * Copyright (c) 2004 Nathan Binkert
   10  * All rights reserved.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  *      $FreeBSD: /c/ncvs/src/sys/dev/aac/aac.c,v 1.1 2000/09/13 03:20:34 msmith Exp $
   34  */
   35 
   36 /*
   37  * Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
   38  */
   39 
   40 /*
   41  * This driver would not have rewritten for OpenBSD if it was not for the
   42  * hardware donation from Nocom.  I want to thank them for their support.
   43  * Of course, credit should go to Mike Smith for the original work he did
   44  * in the FreeBSD driver where I found lots of reusable code and inspiration.
   45  * - Niklas Hallqvist
   46  */
   47 
   48 #include <sys/param.h>
   49 #include <sys/systm.h>
   50 #include <sys/buf.h>
   51 #include <sys/device.h>
   52 #include <sys/kernel.h>
   53 #include <sys/kthread.h>
   54 #include <sys/malloc.h>
   55 #include <sys/rwlock.h>
   56 #include <sys/time.h>
   57 
   58 #include <machine/bus.h>
   59 
   60 #include <uvm/uvm_extern.h>
   61 
   62 #include <scsi/scsi_all.h>
   63 #include <scsi/scsi_disk.h>
   64 #include <scsi/scsiconf.h>
   65 
   66 #include <dev/ic/aacreg.h>
   67 #include <dev/ic/aacvar.h>
   68 #include <dev/ic/aac_tables.h>
   69 
   70 /* Geometry constants. */
   71 #define AAC_MAXCYLS             1024
   72 #define AAC_HEADS               64
   73 #define AAC_SECS                32      /* mapping 64*32 */
   74 #define AAC_MEDHEADS            127
   75 #define AAC_MEDSECS             63      /* mapping 127*63 */
   76 #define AAC_BIGHEADS            255
   77 #define AAC_BIGSECS             63      /* mapping 255*63 */
   78 #define AAC_SECS32              0x1f    /* round capacity */
   79 
   80 struct scsi_xfer;
   81 
   82 void    aac_copy_internal_data(struct scsi_xfer *, u_int8_t *, size_t);
   83 char   *aac_describe_code(struct aac_code_lookup *, u_int32_t);
   84 void    aac_describe_controller(struct aac_softc *);
   85 int     aac_enqueue_fib(struct aac_softc *, int, struct aac_command *);
   86 int     aac_dequeue_fib(struct aac_softc *, int, u_int32_t *,
   87                         struct aac_fib **);
   88 int     aac_enqueue_response(struct aac_softc *sc, int queue,
   89                              struct aac_fib *fib);
   90 
   91 void    aac_eval_mapping(u_int32_t, int *, int *, int *);
   92 void    aac_print_printf(struct aac_softc *);
   93 int     aac_init(struct aac_softc *);
   94 int     aac_check_firmware(struct aac_softc *);
   95 void    aac_internal_cache_cmd(struct scsi_xfer *);
   96 
   97 /* Command Processing */
   98 void    aac_timeout(struct aac_softc *);
   99 void    aac_command_timeout(struct aac_command *);
  100 int     aac_map_command(struct aac_command *);
  101 void    aac_complete(void *);
  102 int     aac_bio_command(struct aac_softc *, struct aac_command **);
  103 void    aac_bio_complete(struct aac_command *);
  104 int     aac_wait_command(struct aac_command *, int);
  105 void    aac_create_thread(void *);
  106 void    aac_command_thread(void *);
  107 
  108 /* Command Buffer Management */
  109 void    aac_map_command_sg(void *, bus_dma_segment_t *, int, int);
  110 int     aac_alloc_commands(struct aac_softc *);
  111 void    aac_free_commands(struct aac_softc *);
  112 void    aac_unmap_command(struct aac_command *);
  113 
  114 int     aac_raw_scsi_cmd(struct scsi_xfer *);
  115 int     aac_scsi_cmd(struct scsi_xfer *);
  116 void    aac_startio(struct aac_softc *);
  117 void    aac_startup(struct aac_softc *);
  118 void    aac_add_container(struct aac_softc *, struct aac_mntinforesp *, int);
  119 void    aac_shutdown(void *);
  120 int     aac_sync_command(struct aac_softc *, u_int32_t, u_int32_t,
  121     u_int32_t, u_int32_t, u_int32_t, u_int32_t *);
  122 
  123 struct cfdriver aac_cd = {
  124         NULL, "aac", DV_DULL
  125 };
  126 
  127 struct scsi_adapter aac_switch = {
  128         aac_scsi_cmd, aacminphys, 0, 0,
  129 };
  130 
  131 struct scsi_adapter aac_raw_switch = {
  132         aac_raw_scsi_cmd, aacminphys, 0, 0,
  133 };
  134 
  135 struct scsi_device aac_dev = {
  136         NULL, NULL, NULL, NULL
  137 };
  138 
  139 /* Falcon/PPC interface */
  140 int     aac_fa_get_fwstatus(struct aac_softc *);
  141 void    aac_fa_qnotify(struct aac_softc *, int);
  142 int     aac_fa_get_istatus(struct aac_softc *);
  143 void    aac_fa_clear_istatus(struct aac_softc *, int);
  144 void    aac_fa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t, u_int32_t,
  145                            u_int32_t, u_int32_t);
  146 int     aac_fa_get_mailbox(struct aac_softc *, int);
  147 void    aac_fa_set_interrupts(struct aac_softc *, int);
  148 
  149 struct aac_interface aac_fa_interface = {
  150         aac_fa_get_fwstatus,
  151         aac_fa_qnotify,
  152         aac_fa_get_istatus,
  153         aac_fa_clear_istatus,
  154         aac_fa_set_mailbox,
  155         aac_fa_get_mailbox,
  156         aac_fa_set_interrupts
  157 };
  158 
  159 /* StrongARM interface */
  160 int     aac_sa_get_fwstatus(struct aac_softc *);
  161 void    aac_sa_qnotify(struct aac_softc *, int);
  162 int     aac_sa_get_istatus(struct aac_softc *);
  163 void    aac_sa_clear_istatus(struct aac_softc *, int);
  164 void    aac_sa_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
  165     u_int32_t, u_int32_t, u_int32_t);
  166 int     aac_sa_get_mailbox(struct aac_softc *, int);
  167 void    aac_sa_set_interrupts(struct aac_softc *, int);
  168 
  169 struct aac_interface aac_sa_interface = {
  170         aac_sa_get_fwstatus,
  171         aac_sa_qnotify,
  172         aac_sa_get_istatus,
  173         aac_sa_clear_istatus,
  174         aac_sa_set_mailbox,
  175         aac_sa_get_mailbox,
  176         aac_sa_set_interrupts
  177 };
  178 
  179 /* i960Rx interface */    
  180 int     aac_rx_get_fwstatus(struct aac_softc *);
  181 void    aac_rx_qnotify(struct aac_softc *, int);
  182 int     aac_rx_get_istatus(struct aac_softc *);
  183 void    aac_rx_clear_istatus(struct aac_softc *, int);
  184 void    aac_rx_set_mailbox(struct aac_softc *, u_int32_t, u_int32_t,
  185     u_int32_t, u_int32_t, u_int32_t);
  186 int     aac_rx_get_mailbox(struct aac_softc *, int);
  187 void    aac_rx_set_interrupts(struct aac_softc *, int);
  188 
  189 struct aac_interface aac_rx_interface = {
  190         aac_rx_get_fwstatus,
  191         aac_rx_qnotify,
  192         aac_rx_get_istatus,
  193         aac_rx_clear_istatus,
  194         aac_rx_set_mailbox,
  195         aac_rx_get_mailbox,
  196         aac_rx_set_interrupts
  197 };
  198 
  199 /* Rocket/MIPS interface */     
  200 int     aac_rkt_get_fwstatus(struct aac_softc *);
  201 void    aac_rkt_qnotify(struct aac_softc *, int);
  202 int     aac_rkt_get_istatus(struct aac_softc *);
  203 void    aac_rkt_clear_istatus(struct aac_softc *, int);
  204 void    aac_rkt_set_mailbox(struct aac_softc *, u_int32_t,
  205                                     u_int32_t, u_int32_t,
  206                                     u_int32_t, u_int32_t);
  207 int     aac_rkt_get_mailbox(struct aac_softc *, int);
  208 void    aac_rkt_set_interrupts(struct aac_softc *, int);
  209 
  210 struct aac_interface aac_rkt_interface = {
  211         aac_rkt_get_fwstatus,
  212         aac_rkt_qnotify,
  213         aac_rkt_get_istatus,
  214         aac_rkt_clear_istatus,
  215         aac_rkt_set_mailbox,
  216         aac_rkt_get_mailbox,
  217         aac_rkt_set_interrupts
  218 };
  219 
  220 #ifdef AAC_DEBUG
  221 int     aac_debug = AAC_DEBUG;
  222 #endif
  223 
  224 int
  225 aac_attach(struct aac_softc *sc)
  226 {
  227         struct scsibus_attach_args saa;
  228         int error;
  229 
  230         /*
  231          * Initialise per-controller queues.
  232          */
  233         aac_initq_free(sc);
  234         aac_initq_ready(sc);
  235         aac_initq_busy(sc);
  236         aac_initq_bio(sc);
  237 
  238         /* disable interrupts before we enable anything */
  239         AAC_MASK_INTERRUPTS(sc);
  240 
  241         /* mark controller as suspended until we get ourselves organised */
  242         sc->aac_state |= AAC_STATE_SUSPEND;
  243 
  244         /*
  245          * Check that the firmware on the card is supported.
  246          */
  247         error = aac_check_firmware(sc);
  248         if (error)
  249                 return (error);
  250 
  251         /*
  252          * Initialize locks
  253          */
  254         AAC_LOCK_INIT(&sc->aac_sync_lock, "AAC sync FIB lock");
  255         AAC_LOCK_INIT(&sc->aac_aifq_lock, "AAC AIF lock");
  256         AAC_LOCK_INIT(&sc->aac_io_lock, "AAC I/O lock");
  257         AAC_LOCK_INIT(&sc->aac_container_lock, "AAC container lock");
  258         TAILQ_INIT(&sc->aac_container_tqh);
  259 
  260         /* Initialize the local AIF queue pointers */
  261         sc->aac_aifq_head = sc->aac_aifq_tail = AAC_AIFQ_LENGTH;
  262 
  263         /*
  264          * Initialise the adapter.
  265          */
  266         error = aac_init(sc);
  267         if (error)
  268                 return (error);
  269 
  270         /* Fill in the prototype scsi_link. */
  271         sc->aac_link.adapter_softc = sc;
  272         sc->aac_link.adapter = &aac_switch;
  273         sc->aac_link.device = &aac_dev;
  274         sc->aac_link.openings = (sc->total_fibs - 8) / 
  275             (sc->aac_container_count ? sc->aac_container_count : 1);
  276         sc->aac_link.adapter_buswidth = AAC_MAX_CONTAINERS;
  277         sc->aac_link.adapter_target = AAC_MAX_CONTAINERS;
  278 
  279         bzero(&saa, sizeof(saa));
  280         saa.saa_sc_link = &sc->aac_link;
  281 
  282         config_found(&sc->aac_dev, &saa, scsiprint);
  283 
  284         /* Create the AIF thread */
  285         sc->aifthread = 0;
  286         sc->aifflags = 0;
  287         kthread_create_deferred(aac_create_thread, sc);
  288 
  289 #if 0
  290         /* Register the shutdown method to only be called post-dump */
  291         sc->aac_sdh = shutdownhook_establish(aac_shutdown, (void *)sc);
  292 #endif
  293 
  294         return (0);
  295 }
  296 
  297 void
  298 aac_create_thread(void *arg)
  299 {
  300         struct aac_softc *sc = arg;
  301 
  302         if (kthread_create(aac_command_thread, sc, &sc->aifthread, "%s",
  303             sc->aac_dev.dv_xname)) {
  304                 /* TODO disable aac */
  305                 printf("%s: failed to create kernel thread, disabled",
  306                 sc->aac_dev.dv_xname);
  307         }
  308         AAC_DPRINTF(AAC_D_MISC, ("%s: aac_create_thread\n",
  309             sc->aac_dev.dv_xname));
  310 
  311 }
  312 
  313 /*
  314  * Probe for containers, create disks.
  315  */
  316 void
  317 aac_startup(struct aac_softc *sc)
  318 {
  319         struct aac_fib *fib;
  320         struct aac_mntinfo *mi;
  321         struct aac_mntinforesp *mir = NULL;
  322         int count = 0, i = 0;
  323 
  324 
  325         aac_alloc_sync_fib(sc, &fib, 0);
  326         mi = (struct aac_mntinfo *)&fib->data[0];
  327 
  328         AAC_DPRINTF(AAC_D_MISC, ("%s: aac startup\n", sc->aac_dev.dv_xname));
  329 
  330         sc->aac_container_count = 0;
  331         /* loop over possible containers */
  332         do {
  333                 /* request information on this container */
  334                 bzero(mi, sizeof(struct aac_mntinfo));
  335                 mi->Command = VM_NameServe;
  336                 mi->MntType = FT_FILESYS;
  337                 mi->MntCount = i;
  338                 if (aac_sync_fib(sc, ContainerCommand, 0, fib,
  339                                  sizeof(struct aac_mntinfo))) {
  340                         printf("%s: error probing container %d\n",
  341                                sc->aac_dev.dv_xname, i);
  342                         continue;
  343                 }
  344 
  345                 mir = (struct aac_mntinforesp *)&fib->data[0];
  346                 /* XXX Need to check if count changed */
  347                 count = mir->MntRespCount;
  348 
  349 #if 0
  350                 aac_add_container(sc, mir, 0);
  351 #else
  352                 /* 
  353                  * Check container volume type for validity.  Note
  354                  * that many of the possible types may never show up.
  355                  */
  356                 if (mir->Status == ST_OK && 
  357                     mir->MntTable[0].VolType != CT_NONE) {
  358                         int drv_cyls, drv_hds, drv_secs;
  359 
  360                         AAC_DPRINTF(AAC_D_MISC,
  361                             ("%s: %d: id %x  name '%.16s'  size %u  type %d\n",
  362                              sc->aac_dev.dv_xname, i,
  363                              mir->MntTable[0].ObjectId,
  364                              mir->MntTable[0].FileSystemName,
  365                              mir->MntTable[0].Capacity,
  366                              mir->MntTable[0].VolType));
  367 
  368                         sc->aac_container_count++;
  369                         sc->aac_hdr[i].hd_present = 1;
  370                         sc->aac_hdr[i].hd_size = mir->MntTable[0].Capacity;
  371 
  372                         /*
  373                          * Evaluate mapping (sectors per head, heads per cyl)
  374                          */
  375                         sc->aac_hdr[i].hd_size &= ~AAC_SECS32;
  376                         aac_eval_mapping(sc->aac_hdr[i].hd_size, &drv_cyls,
  377                                          &drv_hds, &drv_secs);
  378                         sc->aac_hdr[i].hd_heads = drv_hds;
  379                         sc->aac_hdr[i].hd_secs = drv_secs;
  380                         /* Round the size */
  381                         sc->aac_hdr[i].hd_size = drv_cyls * drv_hds * drv_secs;
  382 
  383                         sc->aac_hdr[i].hd_devtype = mir->MntTable[0].VolType;
  384 
  385                         /* XXX Save the name too for use in IDENTIFY later */
  386                 }
  387 #endif
  388 
  389                 i++;
  390         } while ((i < count) && (i < AAC_MAX_CONTAINERS));
  391 
  392         aac_release_sync_fib(sc);
  393 
  394 #if 0
  395         /* poke the bus to actually attach the child devices */
  396         if (bus_generic_attach(sc->aac_dev))
  397                 printf("%s: bus_generic_attach failed\n",
  398                        sc->aac_dev.dv_xname);
  399 #endif
  400 
  401 
  402         /* mark the controller up */
  403         sc->aac_state &= ~AAC_STATE_SUSPEND;
  404 
  405         /* enable interrupts now */
  406         AAC_UNMASK_INTERRUPTS(sc);
  407 }
  408 
  409 #if 0
  410 /*
  411  * Create a device to respresent a new container
  412  */
  413 void
  414 aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
  415 {
  416         struct aac_container *co;
  417         device_t child;
  418 
  419         /* 
  420          * Check container volume type for validity.  Note that many of
  421          * the possible types may never show up.
  422          */
  423         if ((mir->Status == ST_OK) && (mir->MntTable[0].VolType != CT_NONE)) {
  424                 co = (struct aac_container *)malloc(sizeof *co, M_DEVBUF,
  425                        M_NOWAIT);
  426                 if (co == NULL)
  427                         panic("Out of memory?!\n");
  428                 bzero(co, sizeof *co);
  429                 AAC_DPRINTF(AAC_D_MISC,
  430                             ("%s: id %x  name '%.16s'  size %u  type %d\n", 
  431                              sc->aac_dev.dv_xname,
  432                              mir->MntTable[0].ObjectId,
  433                              mir->MntTable[0].FileSystemName,
  434                              mir->MntTable[0].Capacity,
  435                              mir->MntTable[0].VolType);
  436         
  437                 if ((child = device_add_child(sc->aac_dev, "aacd", -1)) == NULL)
  438                         printf("%s: device_add_child failed\n",
  439                                sc->aac_dev.dv_xname);
  440                 else
  441                         device_set_ivars(child, co);
  442                 device_set_desc(child, aac_describe_code(aac_container_types,
  443                                 mir->MntTable[0].VolType));
  444                 co->co_disk = child;
  445                 co->co_found = f;
  446                 bcopy(&mir->MntTable[0], &co->co_mntobj,
  447                       sizeof(struct aac_mntobj));
  448                 AAC_LOCK_ACQUIRE(&sc->aac_container_lock);
  449                 TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link);
  450                 AAC_LOCK_RELEASE(&sc->aac_container_lock);
  451         }
  452 }
  453 #endif
  454 
  455 #if 0
  456 /*
  457  * Free all of the resources associated with (sc)
  458  *
  459  * Should not be called if the controller is active.
  460  */
  461 void
  462 aac_free(struct aac_softc *sc)
  463 {
  464 
  465         debug_called(1);
  466 
  467         /* remove the control device */
  468         if (sc->aac_dev_t != NULL)
  469                 destroy_dev(sc->aac_dev_t);
  470 
  471         /* throw away any FIB buffers, discard the FIB DMA tag */
  472         aac_free_commands(sc);
  473         if (sc->aac_fib_dmat)
  474                 bus_dma_tag_destroy(sc->aac_fib_dmat);
  475 
  476         free(sc->aac_commands, M_AACBUF);
  477 
  478         /* destroy the common area */
  479         if (sc->aac_common) {
  480                 bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap);
  481                 bus_dmamem_free(sc->aac_common_dmat, sc->aac_common,
  482                                 sc->aac_common_dmamap);
  483         }
  484         if (sc->aac_common_dmat)
  485                 bus_dma_tag_destroy(sc->aac_common_dmat);
  486 
  487         /* disconnect the interrupt handler */
  488         if (sc->aac_intr)
  489                 bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr);
  490         if (sc->aac_irq != NULL)
  491                 bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid,
  492                                      sc->aac_irq);
  493 
  494         /* destroy data-transfer DMA tag */
  495         if (sc->aac_buffer_dmat)
  496                 bus_dma_tag_destroy(sc->aac_buffer_dmat);
  497 
  498         /* destroy the parent DMA tag */
  499         if (sc->aac_parent_dmat)
  500                 bus_dma_tag_destroy(sc->aac_parent_dmat);
  501 
  502         /* release the register window mapping */
  503         if (sc->aac_regs_resource != NULL)
  504                 bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
  505                                      sc->aac_regs_rid, sc->aac_regs_resource);
  506 }
  507 
  508 /*
  509  * Disconnect from the controller completely, in preparation for unload.
  510  */
  511 int
  512 aac_detach(device_t dev)
  513 {
  514         struct aac_softc *sc;
  515         struct aac_container *co;
  516         struct aac_sim  *sim;
  517         int error;
  518 
  519         debug_called(1);
  520 
  521         sc = device_get_softc(dev);
  522 
  523         if (sc->aac_state & AAC_STATE_OPEN)
  524                 return(EBUSY);
  525 
  526         /* Remove the child containers */
  527         while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) {
  528                 error = device_delete_child(dev, co->co_disk);
  529                 if (error)
  530                         return (error);
  531                 TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
  532                 free(co, M_AACBUF);
  533         }
  534 
  535         /* Remove the CAM SIMs */
  536         while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) {
  537                 TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link);
  538                 error = device_delete_child(dev, sim->sim_dev);
  539                 if (error)
  540                         return (error);
  541                 free(sim, M_AACBUF);
  542         }
  543 
  544         if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
  545                 sc->aifflags |= AAC_AIFFLAGS_EXIT;
  546                 wakeup(sc->aifthread);
  547                 tsleep(sc->aac_dev, PUSER | PCATCH, "aacdch", 30 * hz);
  548         }
  549 
  550         if (sc->aifflags & AAC_AIFFLAGS_RUNNING)
  551                 panic("Cannot shutdown AIF thread\n");
  552 
  553         if ((error = aac_shutdown(dev)))
  554                 return(error);
  555 
  556         EVENTHANDLER_DEREGISTER(shutdown_final, sc->eh);
  557 
  558         aac_free(sc);
  559 
  560         return(0);
  561 }
  562 
  563 /*
  564  * Bring the controller down to a dormant state and detach all child devices.
  565  *
  566  * This function is called before detach or system shutdown.
  567  *
  568  * Note that we can assume that the bioq on the controller is empty, as we won't
  569  * allow shutdown if any device is open.
  570  */
  571 int
  572 aac_shutdown(device_t dev)
  573 {
  574         struct aac_softc *sc;
  575         struct aac_fib *fib;
  576         struct aac_close_command *cc;
  577 
  578         debug_called(1);
  579 
  580         sc = device_get_softc(dev);
  581 
  582         sc->aac_state |= AAC_STATE_SUSPEND;
  583 
  584         /* 
  585          * Send a Container shutdown followed by a HostShutdown FIB to the
  586          * controller to convince it that we don't want to talk to it anymore.
  587          * We've been closed and all I/O completed already
  588          */
  589         device_printf(sc->aac_dev, "shutting down controller...");
  590 
  591         aac_alloc_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
  592         cc = (struct aac_close_command *)&fib->data[0];
  593 
  594         bzero(cc, sizeof(struct aac_close_command));
  595         cc->Command = VM_CloseAll;
  596         cc->ContainerId = 0xffffffff;
  597         if (aac_sync_fib(sc, ContainerCommand, 0, fib,
  598             sizeof(struct aac_close_command)))
  599                 printf("FAILED.\n");
  600         else
  601                 printf("done\n");
  602         else {
  603                 fib->data[0] = 0;
  604                 /*
  605                  * XXX Issuing this command to the controller makes it
  606                  * shut down but also keeps it from coming back up
  607                  * without a reset of the PCI bus.  This is not
  608                  * desirable if you are just unloading the driver
  609                  * module with the intent to reload it later.
  610                  */
  611                 if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN,
  612                     fib, 1)) {
  613                         printf("FAILED.\n");
  614                 } else {
  615                         printf("done.\n");
  616                 }
  617         }
  618 
  619         AAC_MASK_INTERRUPTS(sc);
  620 
  621         return(0);
  622 }
  623 
  624 /*
  625  * Bring the controller to a quiescent state, ready for system suspend.
  626  */
  627 int
  628 aac_suspend(device_t dev)
  629 {
  630         struct aac_softc *sc;
  631 
  632         debug_called(1);
  633 
  634         sc = device_get_softc(dev);
  635 
  636         sc->aac_state |= AAC_STATE_SUSPEND;
  637         
  638         AAC_MASK_INTERRUPTS(sc);
  639         return(0);
  640 }
  641 
  642 /*
  643  * Bring the controller back to a state ready for operation.
  644  */
  645 int
  646 aac_resume(device_t dev)
  647 {
  648         struct aac_softc *sc;
  649 
  650         debug_called(1);
  651 
  652         sc = device_get_softc(dev);
  653 
  654         sc->aac_state &= ~AAC_STATE_SUSPEND;
  655         AAC_UNMASK_INTERRUPTS(sc);
  656         return(0);
  657 }
  658 #endif
  659 
  660 /*
  661  * Take an interrupt.
  662  */
  663 int
  664 aac_intr(void *arg)
  665 {
  666         struct aac_softc *sc = arg;
  667         u_int16_t reason;
  668 
  669 
  670         /*
  671          * Read the status register directly.  This is faster than taking the
  672          * driver lock and reading the queues directly.  It also saves having
  673          * to turn parts of the driver lock into a spin mutex, which would be
  674          * ugly.
  675          */
  676         reason = AAC_GET_ISTATUS(sc);
  677         AAC_CLEAR_ISTATUS(sc, reason);
  678         (void)AAC_GET_ISTATUS(sc);
  679 
  680         if (reason == 0)
  681                 return (0);
  682 
  683         AAC_DPRINTF(AAC_D_INTR, ("%s: intr: sc=%p: reason=%#x\n",
  684                                  sc->aac_dev.dv_xname, sc, reason));
  685 
  686         /* controller wants to talk to us */
  687         if (reason & (AAC_DB_PRINTF | AAC_DB_COMMAND_READY |
  688                       AAC_DB_RESPONSE_READY)) {
  689 
  690                 if (reason & AAC_DB_RESPONSE_READY) {
  691                         /* handle completion processing */
  692                         if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
  693                                 sc->aifflags |= AAC_AIFFLAGS_COMPLETE;
  694                         } else {
  695                                 AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
  696                                 aac_complete(sc);
  697                                 AAC_LOCK_RELEASE(&sc->aac_io_lock);
  698                         }
  699                 }
  700 
  701 
  702                 /*
  703                  * XXX Make sure that we don't get fooled by strange messages
  704                  * that start with a NULL.
  705                  */
  706                 if (reason & AAC_DB_PRINTF)
  707                         if (sc->aac_common->ac_printf[0] == 0)
  708                                 sc->aac_common->ac_printf[0] = 32;
  709 
  710                 /*
  711                  * This might miss doing the actual wakeup.  However, the
  712                  * msleep that this is waking up has a timeout, so it will
  713                  * wake up eventually.  AIFs and printfs are low enough
  714                  * priority that they can handle hanging out for a few seconds
  715                  * if needed.
  716                  */
  717                 if (sc->aifthread)
  718                         wakeup(sc->aifthread);
  719 
  720         }
  721 
  722         return (1);
  723 }
  724 
  725 /*
  726  * Command Processing
  727  */
  728 
  729 /*
  730  * Start as much queued I/O as possible on the controller
  731  */
  732 void
  733 aac_startio(struct aac_softc *sc)
  734 {
  735         struct aac_command *cm;
  736 
  737         AAC_DPRINTF(AAC_D_CMD, ("%s: start command", sc->aac_dev.dv_xname));
  738 
  739         if (sc->flags & AAC_QUEUE_FRZN) {
  740                 AAC_DPRINTF(AAC_D_CMD, (": queue frozen"));
  741                 return;
  742         }
  743 
  744         AAC_DPRINTF(AAC_D_CMD, ("\n"));
  745 
  746         for (;;) {
  747                 /*
  748                  * Try to get a command that's been put off for lack of 
  749                  * resources
  750                  */
  751                 cm = aac_dequeue_ready(sc);
  752 
  753                 /*
  754                  * Try to build a command off the bio queue (ignore error 
  755                  * return)
  756                  */
  757                 if (cm == NULL) {
  758                         AAC_DPRINTF(AAC_D_CMD, ("\n"));
  759                         aac_bio_command(sc, &cm);
  760                         AAC_DPRINTF(AAC_D_CMD, ("%s: start done bio",
  761                                                 sc->aac_dev.dv_xname));
  762                 }
  763 
  764                 /* nothing to do? */
  765                 if (cm == NULL)
  766                         break;
  767 
  768                 /*
  769                  * Try to give the command to the controller.  Any error is
  770                  * catastrophic since it means that bus_dmamap_load() failed.
  771                  */
  772                 if (aac_map_command(cm) != 0)
  773                         panic("aac: error mapping command %p\n", cm);
  774 
  775                 AAC_DPRINTF(AAC_D_CMD, ("\n%s: another command",
  776                                         sc->aac_dev.dv_xname));
  777         }
  778 
  779         AAC_DPRINTF(AAC_D_CMD, ("\n"));
  780 }
  781 
  782 /*
  783  * Deliver a command to the controller; allocate controller resources at the
  784  * last moment when possible.
  785  */
  786 int
  787 aac_map_command(struct aac_command *cm)
  788 {
  789         struct aac_softc *sc = cm->cm_sc;
  790         int error = 0;
  791 
  792         AAC_DPRINTF(AAC_D_CMD, (": map command"));
  793 
  794         /* don't map more than once */
  795         if (cm->cm_flags & AAC_CMD_MAPPED)
  796                 panic("aac: command %p already mapped", cm);
  797 
  798         if (cm->cm_datalen != 0) {
  799                 error = bus_dmamap_load(sc->aac_dmat, cm->cm_datamap,
  800                                         cm->cm_data, cm->cm_datalen, NULL,
  801                                         BUS_DMA_NOWAIT);
  802                 if (error)
  803                         return (error);
  804 
  805                 aac_map_command_sg(cm, cm->cm_datamap->dm_segs,
  806                                    cm->cm_datamap->dm_nsegs, 0);
  807         } else {
  808                 aac_map_command_sg(cm, NULL, 0, 0);
  809         }
  810 
  811         return (error);
  812 }
  813 
  814 /*
  815  * Handle notification of one or more FIBs coming from the controller.
  816  */
  817 void
  818 aac_command_thread(void *arg)
  819 {
  820         struct aac_softc *sc = arg;
  821         struct aac_fib *fib;
  822         u_int32_t fib_size;
  823         int size, retval;
  824 
  825         AAC_DPRINTF(AAC_D_THREAD, ("%s: aac_command_thread: starting\n",
  826             sc->aac_dev.dv_xname));
  827         AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
  828         sc->aifflags = AAC_AIFFLAGS_RUNNING;
  829 
  830         while ((sc->aifflags & AAC_AIFFLAGS_EXIT) == 0) {
  831 
  832                 AAC_DPRINTF(AAC_D_THREAD,
  833                     ("%s: aac_command_thread: aifflags=%#x\n",
  834                     sc->aac_dev.dv_xname, sc->aifflags));
  835                 retval = 0;
  836 
  837                 if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0) {
  838                         AAC_DPRINTF(AAC_D_THREAD,
  839                                     ("%s: command thread sleeping\n",
  840                                      sc->aac_dev.dv_xname));
  841                         AAC_LOCK_RELEASE(&sc->aac_io_lock);
  842                         retval = tsleep(sc->aifthread, PRIBIO, "aifthd",
  843                                         AAC_PERIODIC_INTERVAL * hz);
  844                         AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
  845                 }
  846 
  847                 if ((sc->aifflags & AAC_AIFFLAGS_COMPLETE) != 0) {
  848                         aac_complete(sc);
  849                         sc->aifflags &= ~AAC_AIFFLAGS_COMPLETE;
  850                 }
  851 
  852                 /*
  853                  * While we're here, check to see if any commands are stuck.
  854                  * This is pretty low-priority, so it's ok if it doesn't
  855                  * always fire.
  856                  */
  857                 if (retval == EWOULDBLOCK)
  858                         aac_timeout(sc);
  859 
  860                 /* Check the hardware printf message buffer */
  861                 if (sc->aac_common->ac_printf[0] != 0)
  862                         aac_print_printf(sc);
  863 
  864                 /* Also check to see if the adapter has a command for us. */
  865                 while (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE,
  866                                        &fib_size, &fib) == 0) {
  867         
  868                         AAC_PRINT_FIB(sc, fib);
  869         
  870                         switch (fib->Header.Command) {
  871                         case AifRequest:
  872                                 //aac_handle_aif(sc, fib);
  873                                 break;
  874                         default:
  875                                 printf("%s: unknown command from controller\n",
  876                                        sc->aac_dev.dv_xname);
  877                                 break;
  878                         }
  879 
  880                         if ((fib->Header.XferState == 0) ||
  881                             (fib->Header.StructType != AAC_FIBTYPE_TFIB))
  882                                 break;
  883 
  884                         /* Return the AIF to the controller. */
  885                         if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) {
  886                                 fib->Header.XferState |= AAC_FIBSTATE_DONEHOST;
  887                                 *(AAC_FSAStatus*)fib->data = ST_OK;
  888 
  889                                 /* XXX Compute the Size field? */
  890                                 size = fib->Header.Size;
  891                                 if (size > sizeof(struct aac_fib)) {
  892                                         size = sizeof(struct aac_fib);
  893                                         fib->Header.Size = size;
  894                                 }
  895                 
  896                                 /*
  897                                  * Since we did not generate this command, it
  898                                  * cannot go through the normal
  899                                  * enqueue->startio chain.
  900                                  */
  901                                 aac_enqueue_response(sc,
  902                                                      AAC_ADAP_NORM_RESP_QUEUE,
  903                                                      fib);
  904                         }
  905                 }
  906         }
  907         sc->aifflags &= ~AAC_AIFFLAGS_RUNNING;
  908         AAC_LOCK_RELEASE(&sc->aac_io_lock);
  909 
  910 #if 0
  911         /*
  912          * if we ever implement detach, we should have detach tsleep
  913          * to wait for this thread to finish
  914          */
  915         wakeup(sc->aac_dev);
  916 #endif
  917 
  918         AAC_DPRINTF(AAC_D_THREAD, ("%s: aac_command_thread: exiting\n",
  919             sc->aac_dev.dv_xname));
  920         kthread_exit(0);
  921 }
  922 
  923 /*
  924  * Process completed commands.
  925  */
  926 void
  927 aac_complete(void *context)
  928 {
  929         struct aac_softc *sc = (struct aac_softc *)context;
  930         struct aac_command *cm;
  931         struct aac_fib *fib;
  932         u_int32_t fib_size;
  933 
  934         AAC_DPRINTF(AAC_D_CMD, ("%s: complete", sc->aac_dev.dv_xname));
  935 
  936         /* pull completed commands off the queue */
  937         for (;;) {
  938                 /* look for completed FIBs on our queue */
  939                 if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
  940                                     &fib))
  941                         break;  /* nothing to do */
  942 
  943                 /* get the command, unmap and hand off for processing */
  944                 cm = sc->aac_commands + fib->Header.SenderData;
  945                 if (cm == NULL) {
  946                         AAC_PRINT_FIB(sc, fib);
  947                         break;
  948                 }
  949 
  950                 aac_remove_busy(cm);
  951                 aac_unmap_command(cm);
  952                 cm->cm_flags |= AAC_CMD_COMPLETED;
  953 
  954                 /* is there a completion handler? */
  955                 if (cm->cm_complete != NULL) {
  956                         cm->cm_complete(cm);
  957                 } else {
  958                         /* assume that someone is sleeping on this command */
  959                         wakeup(cm);
  960                 }
  961         }
  962 
  963         AAC_DPRINTF(AAC_D_CMD, ("\n"));
  964         /* see if we can start some more I/O */
  965         sc->flags &= ~AAC_QUEUE_FRZN;
  966         aac_startio(sc);
  967 }
  968 
  969 /*
  970  * Get a bio and build a command to go with it.
  971  */
  972 int
  973 aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
  974 {
  975         struct aac_command *cm;
  976         struct aac_fib *fib;
  977         struct scsi_xfer *xs;
  978         u_int8_t opcode = 0;
  979 
  980         AAC_DPRINTF(AAC_D_CMD, ("%s: bio command", sc->aac_dev.dv_xname));
  981 
  982         /* get the resources we will need */
  983         if ((cm = aac_dequeue_bio(sc)) == NULL)
  984                 goto fail;
  985         xs = cm->cm_private;
  986 
  987         /* build the FIB */
  988         fib = cm->cm_fib;
  989         fib->Header.Size = sizeof(struct aac_fib_header);
  990         fib->Header.XferState =  
  991                 AAC_FIBSTATE_HOSTOWNED   | 
  992                 AAC_FIBSTATE_INITIALISED | 
  993                 AAC_FIBSTATE_EMPTY       | 
  994                 AAC_FIBSTATE_FROMHOST    |
  995                 AAC_FIBSTATE_REXPECTED   |
  996                 AAC_FIBSTATE_NORM        |
  997                 AAC_FIBSTATE_ASYNC       |
  998                 AAC_FIBSTATE_FAST_RESPONSE;
  999 
 1000         switch(xs->cmd->opcode) {
 1001         case READ_COMMAND:
 1002         case READ_BIG:
 1003                 opcode = READ_COMMAND;
 1004                 break;
 1005         case WRITE_COMMAND:
 1006         case WRITE_BIG:
 1007                 opcode = WRITE_COMMAND;
 1008                 break;
 1009         default:
 1010                 panic("%s: invalid opcode %#x\n", sc->aac_dev.dv_xname,
 1011                       xs->cmd->opcode);
 1012         }
 1013 
 1014         /* build the read/write request */
 1015         if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
 1016                 fib->Header.Command = ContainerCommand;
 1017                 if (opcode == READ_COMMAND) {
 1018                         struct aac_blockread *br;
 1019                         br = (struct aac_blockread *)&fib->data[0];
 1020                         br->Command = VM_CtBlockRead;
 1021                         br->ContainerId = xs->sc_link->target;
 1022                         br->BlockNumber = cm->cm_blkno;
 1023                         br->ByteCount = cm->cm_bcount * AAC_BLOCK_SIZE;
 1024                         fib->Header.Size += sizeof(struct aac_blockread);
 1025                         cm->cm_sgtable = &br->SgMap;
 1026                         cm->cm_flags |= AAC_CMD_DATAIN;
 1027                 } else {
 1028                         struct aac_blockwrite *bw;
 1029                         bw = (struct aac_blockwrite *)&fib->data[0];
 1030                         bw->Command = VM_CtBlockWrite;
 1031                         bw->ContainerId = xs->sc_link->target;
 1032                         bw->BlockNumber = cm->cm_blkno;
 1033                         bw->ByteCount = cm->cm_bcount * AAC_BLOCK_SIZE;
 1034                         bw->Stable = CUNSTABLE;
 1035                         fib->Header.Size += sizeof(struct aac_blockwrite);
 1036                         cm->cm_flags |= AAC_CMD_DATAOUT;
 1037                         cm->cm_sgtable = &bw->SgMap;
 1038                 }
 1039         } else {
 1040                 fib->Header.Command = ContainerCommand64;
 1041                 if (opcode == READ_COMMAND) {
 1042                         struct aac_blockread64 *br;
 1043                         br = (struct aac_blockread64 *)&fib->data[0];
 1044                         br->Command = VM_CtHostRead64;
 1045                         br->ContainerId = xs->sc_link->target;
 1046                         br->BlockNumber = cm->cm_blkno;
 1047                         br->SectorCount = cm->cm_bcount;
 1048                         br->Pad = 0;
 1049                         br->Flags = 0;
 1050                         fib->Header.Size += sizeof(struct aac_blockread64);
 1051                         cm->cm_flags |= AAC_CMD_DATAOUT;
 1052                         (struct aac_sg_table64 *)cm->cm_sgtable = &br->SgMap64;
 1053                 } else {
 1054                         struct aac_blockwrite64 *bw;
 1055                         bw = (struct aac_blockwrite64 *)&fib->data[0];
 1056                         bw->Command = VM_CtHostWrite64;
 1057                         bw->ContainerId = xs->sc_link->target;
 1058                         bw->BlockNumber = cm->cm_blkno;
 1059                         bw->SectorCount = cm->cm_bcount;
 1060                         bw->Pad = 0;
 1061                         bw->Flags = 0;
 1062                         fib->Header.Size += sizeof(struct aac_blockwrite64);
 1063                         cm->cm_flags |= AAC_CMD_DATAIN;
 1064                         (struct aac_sg_table64 *)cm->cm_sgtable = &bw->SgMap64;
 1065                 }
 1066         }
 1067 
 1068         *cmp = cm;
 1069         AAC_DPRINTF(AAC_D_CMD, ("\n"));
 1070         return(0);
 1071 
 1072 fail:
 1073         AAC_DPRINTF(AAC_D_CMD, ("\n"));
 1074         return(ENOMEM);
 1075 }
 1076 
 1077 /*
 1078  * Handle a bio-instigated command that has been completed.
 1079  */
 1080 void
 1081 aac_bio_complete(struct aac_command *cm)
 1082 {
 1083         struct aac_blockread_response *brr;
 1084         struct aac_blockwrite_response *bwr;
 1085         struct scsi_xfer *xs = (struct scsi_xfer *)cm->cm_private;
 1086         AAC_FSAStatus status;
 1087         int s;
 1088 
 1089         AAC_DPRINTF(AAC_D_CMD,
 1090                     ("%s: bio complete\n", cm->cm_sc->aac_dev.dv_xname));
 1091 
 1092         /* fetch relevant status and then release the command */
 1093         if (xs->flags & SCSI_DATA_IN) {
 1094                 brr = (struct aac_blockread_response *)&cm->cm_fib->data[0];
 1095                 status = brr->Status;
 1096         } else {
 1097                 bwr = (struct aac_blockwrite_response *)&cm->cm_fib->data[0];
 1098                 status = bwr->Status;
 1099         }
 1100 
 1101         s = splbio();
 1102         aac_release_command(cm);
 1103 
 1104         xs->error = status == ST_OK? XS_NOERROR : XS_DRIVER_STUFFUP;
 1105         xs->resid = 0;
 1106         xs->flags |= ITSDONE;
 1107         scsi_done(xs);
 1108         splx(s);
 1109 }
 1110 
 1111 /*
 1112  * Submit a command to the controller, return when it completes.
 1113  * XXX This is very dangerous!  If the card has gone out to lunch, we could
 1114  *     be stuck here forever.  At the same time, signals are not caught
 1115  *     because there is a risk that a signal could wakeup the tsleep before
 1116  *     the card has a chance to complete the command.  The passed in timeout
 1117  *     is ignored for the same reason.  Since there is no way to cancel a
 1118  *     command in progress, we should probably create a 'dead' queue where
 1119  *     commands go that have been interrupted/timed-out/etc, that keeps them
 1120  *     out of the free pool.  That way, if the card is just slow, it won't
 1121  *     spam the memory of a command that has been recycled.
 1122  */
 1123 int
 1124 aac_wait_command(struct aac_command *cm, int timeout)
 1125 {
 1126         struct aac_softc *sc = cm->cm_sc;
 1127         int error = 0;
 1128 
 1129         AAC_DPRINTF(AAC_D_CMD, (": wait for command"));
 1130 
 1131         /* Put the command on the ready queue and get things going */
 1132         cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
 1133         aac_enqueue_ready(cm);
 1134         AAC_DPRINTF(AAC_D_CMD, ("\n"));
 1135         aac_startio(sc);
 1136         while (!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) {
 1137                 AAC_DPRINTF(AAC_D_MISC, ("%s: sleeping until command done\n",
 1138                                          sc->aac_dev.dv_xname));
 1139                 AAC_LOCK_RELEASE(&sc->aac_io_lock);
 1140                 error = tsleep(cm, PRIBIO, "aacwait", timeout);
 1141                 AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
 1142         }
 1143         return (error);
 1144 }
 1145 
 1146 /*
 1147  *Command Buffer Management
 1148  */
 1149 
 1150 /*
 1151  * Allocate a command.
 1152  */
 1153 int
 1154 aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
 1155 {
 1156         struct aac_command *cm;
 1157 
 1158         AAC_DPRINTF(AAC_D_CMD, (": allocate command"));
 1159         if ((cm = aac_dequeue_free(sc)) == NULL) {
 1160                 AAC_DPRINTF(AAC_D_CMD, (" failed"));
 1161                 return (EBUSY);
 1162         }
 1163 
 1164         *cmp = cm;
 1165         return(0);
 1166 }
 1167 
 1168 /*
 1169  * Release a command back to the freelist.
 1170  */
 1171 void
 1172 aac_release_command(struct aac_command *cm)
 1173 {
 1174         AAC_DPRINTF(AAC_D_CMD, (": release command"));
 1175 
 1176         /* (re)initialise the command/FIB */
 1177         cm->cm_sgtable = NULL;
 1178         cm->cm_flags = 0;
 1179         cm->cm_complete = NULL;
 1180         cm->cm_private = NULL;
 1181         cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
 1182         cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB;
 1183         cm->cm_fib->Header.Flags = 0;
 1184         cm->cm_fib->Header.SenderSize = sizeof(struct aac_fib);
 1185 
 1186         /* 
 1187          * These are duplicated in aac_start to cover the case where an
 1188          * intermediate stage may have destroyed them.  They're left
 1189          * initialised here for debugging purposes only.
 1190          */
 1191         cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
 1192         cm->cm_fib->Header.SenderData = 0;
 1193 
 1194         aac_enqueue_free(cm);
 1195 }
 1196 
 1197 /*
 1198  * Allocate and initialise commands/FIBs for this adapter.
 1199  */
 1200 int
 1201 aac_alloc_commands(struct aac_softc *sc)
 1202 {
 1203         struct aac_command *cm;
 1204         struct aac_fibmap *fm;
 1205         int i, error;
 1206 
 1207         if (sc->total_fibs + AAC_FIB_COUNT > sc->aac_max_fibs)
 1208                 return (ENOMEM);
 1209 
 1210         fm = malloc(sizeof(struct aac_fibmap), M_DEVBUF, M_NOWAIT);
 1211         if (fm == NULL)
 1212                 goto exit;
 1213         bzero(fm, sizeof(struct aac_fibmap));
 1214 
 1215         /* allocate the FIBs in DMAable memory and load them */
 1216         if (bus_dmamem_alloc(sc->aac_dmat, AAC_FIBMAP_SIZE, PAGE_SIZE, 0,
 1217             &fm->aac_seg, 1, &fm->aac_nsegs, BUS_DMA_NOWAIT)) {
 1218                 printf("%s: can't alloc FIBs\n", sc->aac_dev.dv_xname);
 1219                 error = ENOBUFS;
 1220                 goto exit_alloc;
 1221         }
 1222 
 1223         if (bus_dmamem_map(sc->aac_dmat, &fm->aac_seg, 1,
 1224             AAC_FIBMAP_SIZE, (caddr_t *)&fm->aac_fibs, BUS_DMA_NOWAIT)) {
 1225                 printf("%s: can't map FIB structure\n", sc->aac_dev.dv_xname);
 1226                 error = ENOBUFS;
 1227                 goto exit_map;
 1228         }
 1229 
 1230         if (bus_dmamap_create(sc->aac_dmat, AAC_FIBMAP_SIZE, 1,
 1231             AAC_FIBMAP_SIZE, 0, BUS_DMA_NOWAIT, &fm->aac_fibmap)) {
 1232                 printf("%s: can't create dma map\n", sc->aac_dev.dv_xname);
 1233                 error = ENOBUFS;
 1234                 goto exit_create;
 1235         }
 1236 
 1237         if (bus_dmamap_load(sc->aac_dmat, fm->aac_fibmap, fm->aac_fibs, 
 1238             AAC_FIBMAP_SIZE, NULL, BUS_DMA_NOWAIT)) {
 1239                 printf("%s: can't load dma map\n", sc->aac_dev.dv_xname);
 1240                 error = ENOBUFS;
 1241                 goto exit_load;
 1242         }
 1243 
 1244         /* initialise constant fields in the command structure */
 1245         AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
 1246         bzero(fm->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib));
 1247         for (i = 0; i < AAC_FIB_COUNT; i++) {
 1248                 cm = sc->aac_commands + sc->total_fibs;
 1249                 fm->aac_commands = cm;
 1250                 cm->cm_sc = sc;
 1251                 cm->cm_fib = fm->aac_fibs + i;
 1252                 cm->cm_fibphys = fm->aac_fibmap->dm_segs[0].ds_addr +
 1253                         (i * sizeof(struct aac_fib));
 1254                 cm->cm_index = sc->total_fibs;
 1255 
 1256                 if (bus_dmamap_create(sc->aac_dmat, MAXBSIZE, AAC_MAXSGENTRIES,
 1257                     MAXBSIZE, 0, BUS_DMA_NOWAIT, &cm->cm_datamap)) {
 1258                         break;
 1259                 }
 1260                 aac_release_command(cm);
 1261                 sc->total_fibs++;
 1262         }
 1263 
 1264         if (i > 0) {
 1265                 TAILQ_INSERT_TAIL(&sc->aac_fibmap_tqh, fm, fm_link);
 1266                 AAC_DPRINTF(AAC_D_MISC, ("%s: total_fibs= %d\n",
 1267                                          sc->aac_dev.dv_xname,
 1268                                          sc->total_fibs));
 1269                 AAC_LOCK_RELEASE(&sc->aac_io_lock);
 1270                 return (0);
 1271         } 
 1272 
 1273  exit_load:
 1274         bus_dmamap_destroy(sc->aac_dmat, fm->aac_fibmap);
 1275  exit_create:
 1276         bus_dmamem_unmap(sc->aac_dmat, (caddr_t)fm->aac_fibs, AAC_FIBMAP_SIZE);
 1277  exit_map:
 1278         bus_dmamem_free(sc->aac_dmat, &fm->aac_seg, fm->aac_nsegs);
 1279  exit_alloc:
 1280         free(fm, M_DEVBUF);
 1281  exit:
 1282         AAC_LOCK_RELEASE(&sc->aac_io_lock);
 1283         return (error);
 1284 }
 1285 
 1286 /*
 1287  * Free FIBs owned by this adapter.
 1288  */
 1289 void
 1290 aac_free_commands(struct aac_softc *sc)
 1291 {
 1292         struct aac_fibmap *fm;
 1293         struct aac_command *cm;
 1294         int i;
 1295 
 1296         while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) {
 1297 
 1298                 TAILQ_REMOVE(&sc->aac_fibmap_tqh, fm, fm_link);
 1299 
 1300                 /*
 1301                  * We check against total_fibs to handle partially
 1302                  * allocated blocks.
 1303                  */
 1304                 for (i = 0; i < AAC_FIB_COUNT && sc->total_fibs--; i++) {
 1305                         cm = fm->aac_commands + i;
 1306                         bus_dmamap_destroy(sc->aac_dmat, cm->cm_datamap);
 1307                 }
 1308 
 1309                 bus_dmamap_unload(sc->aac_dmat, fm->aac_fibmap);
 1310                 bus_dmamap_destroy(sc->aac_dmat, fm->aac_fibmap);
 1311                 bus_dmamem_unmap(sc->aac_dmat, (caddr_t)fm->aac_fibs,
 1312                                  AAC_FIBMAP_SIZE);
 1313                 bus_dmamem_free(sc->aac_dmat, &fm->aac_seg, fm->aac_nsegs);
 1314                 free(fm, M_DEVBUF);
 1315         }
 1316 }
 1317 
 1318 
 1319 /*
 1320  * Command-mapping helper function - populate this command's s/g table.
 1321  */
 1322 void
 1323 aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
 1324 {
 1325         struct aac_command *cm = arg;
 1326         struct aac_softc *sc = cm->cm_sc;
 1327         struct aac_fib *fib = cm->cm_fib;
 1328         int i;
 1329 
 1330         /* copy into the FIB */
 1331         if (cm->cm_sgtable != NULL) {
 1332                 if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
 1333                         struct aac_sg_table *sg = cm->cm_sgtable;
 1334                         sg->SgCount = nseg;
 1335                         for (i = 0; i < nseg; i++) {
 1336                                 sg->SgEntry[i].SgAddress = segs[i].ds_addr;
 1337                                 sg->SgEntry[i].SgByteCount = segs[i].ds_len;
 1338                         }
 1339                         /* update the FIB size for the s/g count */
 1340                         fib->Header.Size += nseg * sizeof(struct aac_sg_entry);
 1341                 } else {
 1342                         struct aac_sg_table64 *sg;
 1343                         sg = (struct aac_sg_table64 *)cm->cm_sgtable;
 1344                         sg->SgCount = nseg;
 1345                         for (i = 0; i < nseg; i++) {
 1346                                 sg->SgEntry64[i].SgAddress = segs[i].ds_addr;
 1347                                 sg->SgEntry64[i].SgByteCount = segs[i].ds_len;
 1348                         }
 1349                         /* update the FIB size for the s/g count */
 1350                         fib->Header.Size += nseg*sizeof(struct aac_sg_entry64);
 1351                 }
 1352         }
 1353 
 1354         /* Fix up the address values in the FIB.  Use the command array index
 1355          * instead of a pointer since these fields are only 32 bits.  Shift
 1356          * the SenderFibAddress over to make room for the fast response bit.
 1357          */
 1358         cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 1);
 1359         cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys;
 1360 
 1361         /* save a pointer to the command for speedy reverse-lookup */
 1362         cm->cm_fib->Header.SenderData = cm->cm_index;
 1363 
 1364         if (cm->cm_flags & AAC_CMD_DATAIN)
 1365                 bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0,
 1366                                 cm->cm_datamap->dm_mapsize,
 1367                                 BUS_DMASYNC_PREREAD);
 1368         if (cm->cm_flags & AAC_CMD_DATAOUT)
 1369                 bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0,
 1370                                 cm->cm_datamap->dm_mapsize,
 1371                                 BUS_DMASYNC_PREWRITE);
 1372         cm->cm_flags |= AAC_CMD_MAPPED;
 1373 
 1374         /* put the FIB on the outbound queue */
 1375         if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) {
 1376                 aac_remove_busy(cm);
 1377                 aac_unmap_command(cm);
 1378                 aac_requeue_ready(cm);
 1379         }
 1380 }
 1381 
 1382 /*
 1383  * Unmap a command from controller-visible space.
 1384  */
 1385 void
 1386 aac_unmap_command(struct aac_command *cm)
 1387 {
 1388         struct aac_softc *sc = cm->cm_sc;
 1389 
 1390         if (!(cm->cm_flags & AAC_CMD_MAPPED))
 1391                 return;
 1392 
 1393         if (cm->cm_datalen != 0) {
 1394                 if (cm->cm_flags & AAC_CMD_DATAIN)
 1395                         bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0,
 1396                                         cm->cm_datamap->dm_mapsize,
 1397                                         BUS_DMASYNC_POSTREAD);
 1398                 if (cm->cm_flags & AAC_CMD_DATAOUT)
 1399                         bus_dmamap_sync(sc->aac_dmat, cm->cm_datamap, 0,
 1400                                         cm->cm_datamap->dm_mapsize,
 1401                                         BUS_DMASYNC_POSTWRITE);
 1402 
 1403                 bus_dmamap_unload(sc->aac_dmat, cm->cm_datamap);
 1404         }
 1405         cm->cm_flags &= ~AAC_CMD_MAPPED;
 1406 }
 1407 
 1408 /*
 1409  * Hardware Interface
 1410  */
 1411 
 1412 /*
 1413  * Initialise the adapter.
 1414  */
 1415 int
 1416 aac_check_firmware(struct aac_softc *sc)
 1417 {
 1418         u_int32_t major, minor, options;
 1419 
 1420         /*
 1421          * Retrieve the firmware version numbers.  Dell PERC2/QC cards with
 1422          * firmware version 1.x are not compatible with this driver.
 1423          */
 1424         if (sc->flags & AAC_FLAGS_PERC2QC) {
 1425                 if (aac_sync_command(sc, AAC_MONKER_GETKERNVER, 0, 0, 0, 0,
 1426                                      NULL)) {
 1427                         printf("%s: Error reading firmware version\n",
 1428                                sc->aac_dev.dv_xname);
 1429                         return (EIO);
 1430                 }
 1431 
 1432                 /* These numbers are stored as ASCII! */
 1433                 major = (AAC_GET_MAILBOX(sc, 1) & 0xff) - 0x30;
 1434                 minor = (AAC_GET_MAILBOX(sc, 2) & 0xff) - 0x30;
 1435                 if (major == 1) {
 1436                         printf("%s: Firmware version %d.%d is not supported\n",
 1437                                sc->aac_dev.dv_xname, major, minor);
 1438                         return (EINVAL);
 1439                 }
 1440         }
 1441 
 1442         /*
 1443          * Retrieve the capabilities/supported options word so we know what
 1444          * work-arounds to enable.
 1445          */
 1446         if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) {
 1447                 printf("%s: RequestAdapterInfo failed\n",
 1448                        sc->aac_dev.dv_xname);
 1449                 return (EIO);
 1450         }
 1451         options = AAC_GET_MAILBOX(sc, 1);
 1452         sc->supported_options = options;
 1453 
 1454         if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
 1455             (sc->flags & AAC_FLAGS_NO4GB) == 0)
 1456                 sc->flags |= AAC_FLAGS_4GB_WINDOW;
 1457         if (options & AAC_SUPPORTED_NONDASD)
 1458                 sc->flags |= AAC_FLAGS_ENABLE_CAM;
 1459         if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0
 1460              && (sizeof(bus_addr_t) > 4)) {
 1461                 printf("%s: Enabling 64-bit address support\n",
 1462                        sc->aac_dev.dv_xname);
 1463                 sc->flags |= AAC_FLAGS_SG_64BIT;
 1464         }
 1465 
 1466         /* Check for broken hardware that does a lower number of commands */
 1467         if ((sc->flags & AAC_FLAGS_256FIBS) == 0)
 1468                 sc->aac_max_fibs = AAC_MAX_FIBS;
 1469         else
 1470                 sc->aac_max_fibs = 256;
 1471 
 1472         return (0);
 1473 }
 1474 
 1475 int
 1476 aac_init(struct aac_softc *sc)
 1477 {
 1478         bus_dma_segment_t seg;
 1479         int nsegs;
 1480         int i, error;
 1481         int state = 0;
 1482         struct aac_adapter_init *ip;
 1483         time_t then;
 1484         u_int32_t code, qoffset;
 1485 
 1486         /*
 1487          * First wait for the adapter to come ready.
 1488          */
 1489         then = time_uptime;
 1490         for (i = 0; i < AAC_BOOT_TIMEOUT * 1000; i++) {
 1491                 code = AAC_GET_FWSTATUS(sc);
 1492                 if (code & AAC_SELF_TEST_FAILED) {
 1493                         printf("%s: FATAL: selftest failed\n",
 1494                             sc->aac_dev.dv_xname);
 1495                         return (ENXIO);
 1496                 }
 1497                 if (code & AAC_KERNEL_PANIC) {
 1498                         printf("%s: FATAL: controller kernel panic\n",
 1499                             sc->aac_dev.dv_xname);
 1500                         return (ENXIO);
 1501                 }
 1502                 if (code & AAC_UP_AND_RUNNING)
 1503                         break;
 1504                 DELAY(1000);
 1505         }
 1506         if (i == AAC_BOOT_TIMEOUT * 1000) {
 1507                 printf("%s: FATAL: controller not coming ready, status %x\n",
 1508                     sc->aac_dev.dv_xname, code);
 1509                 return (ENXIO);
 1510         }
 1511 
 1512         /*
 1513          * Work around a bug in the 2120 and 2200 that cannot DMA commands
 1514          * below address 8192 in physical memory.
 1515          * XXX If the padding is not needed, can it be put to use instead
 1516          * of ignored?
 1517          */
 1518         if (bus_dmamem_alloc(sc->aac_dmat, AAC_COMMON_ALLOCSIZE, PAGE_SIZE, 0,
 1519                              &seg, 1, &nsegs, BUS_DMA_NOWAIT)) {
 1520                 printf("%s: can't allocate common structure\n",
 1521                     sc->aac_dev.dv_xname);
 1522                 return (ENOMEM);
 1523         }
 1524         state++;
 1525 
 1526         if (bus_dmamem_map(sc->aac_dmat, &seg, nsegs, AAC_COMMON_ALLOCSIZE,
 1527                            (caddr_t *)&sc->aac_common, BUS_DMA_NOWAIT)) {
 1528                 printf("%s: can't map common structure\n",
 1529                     sc->aac_dev.dv_xname);
 1530                 error = ENOMEM;
 1531                 goto bail_out;
 1532         }
 1533         state++;
 1534 
 1535         if (bus_dmamap_create(sc->aac_dmat, AAC_COMMON_ALLOCSIZE, 1,
 1536             AAC_COMMON_ALLOCSIZE, 0, BUS_DMA_NOWAIT, &sc->aac_common_map)) {
 1537                 printf("%s: can't create dma map\n", sc->aac_dev.dv_xname);
 1538                 error = ENOBUFS;
 1539                 goto bail_out;
 1540         }
 1541         state++;
 1542 
 1543         if (bus_dmamap_load(sc->aac_dmat, sc->aac_common_map, sc->aac_common, 
 1544             AAC_COMMON_ALLOCSIZE, NULL, BUS_DMA_NOWAIT)) {
 1545                 printf("%s: can't load dma map\n", sc->aac_dev.dv_xname);
 1546                 error = ENOBUFS;
 1547                 goto bail_out;
 1548         }
 1549         state++;
 1550 
 1551         sc->aac_common_busaddr = sc->aac_common_map->dm_segs[0].ds_addr;
 1552 
 1553         if (sc->aac_common_busaddr < 8192) {
 1554                 (uint8_t *)sc->aac_common += 8192;
 1555                 sc->aac_common_busaddr += 8192;
 1556         }
 1557         bzero(sc->aac_common, sizeof *sc->aac_common);
 1558     
 1559         /* Allocate some FIBs and associated command structs */
 1560         TAILQ_INIT(&sc->aac_fibmap_tqh);
 1561         sc->aac_commands = malloc(AAC_MAX_FIBS * sizeof(struct aac_command),
 1562                                   M_DEVBUF, M_WAITOK);
 1563         bzero(sc->aac_commands, AAC_MAX_FIBS * sizeof(struct aac_command));
 1564         while (sc->total_fibs < AAC_MAX_FIBS) {
 1565                 if (aac_alloc_commands(sc) != 0)
 1566                         break;
 1567         }
 1568         if (sc->total_fibs == 0)
 1569                 goto out;
 1570         
 1571         /*
 1572          * Fill in the init structure.  This tells the adapter about the
 1573          * physical location of various important shared data structures.
 1574          */
 1575         ip = &sc->aac_common->ac_init;
 1576         ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
 1577         ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION;
 1578 
 1579         ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr +
 1580                                          offsetof(struct aac_common, ac_fibs);
 1581         ip->AdapterFibsVirtualAddress = 0;
 1582         ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
 1583         ip->AdapterFibAlign = sizeof(struct aac_fib);
 1584 
 1585         ip->PrintfBufferAddress = sc->aac_common_busaddr +
 1586                                   offsetof(struct aac_common, ac_printf);
 1587         ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
 1588 
 1589         /* 
 1590          * The adapter assumes that pages are 4K in size, except on some
 1591          * broken firmware versions that do the page->byte conversion twice,
 1592          * therefore 'assuming' that this value is in 16MB units (2^24).
 1593          * Round up since the granularity is so high.
 1594          */
 1595         ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE;
 1596         if (sc->flags & AAC_FLAGS_BROKEN_MEMMAP) {
 1597                 ip->HostPhysMemPages =
 1598                     (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
 1599         }
 1600         ip->HostElapsedSeconds = time_uptime; /* reset later if invalid */
 1601 
 1602         /*
 1603          * Initialise FIB queues.  Note that it appears that the layout of the
 1604          * indexes and the segmentation of the entries may be mandated by the
 1605          * adapter, which is only told about the base of the queue index fields.
 1606          *
 1607          * The initial values of the indices are assumed to inform the adapter
 1608          * of the sizes of the respective queues, and theoretically it could 
 1609          * work out the entire layout of the queue structures from this.  We
 1610          * take the easy route and just lay this area out like everyone else
 1611          * does.
 1612          *
 1613          * The Linux driver uses a much more complex scheme whereby several 
 1614          * header records are kept for each queue.  We use a couple of generic 
 1615          * list manipulation functions which 'know' the size of each list by
 1616          * virtue of a table.
 1617          */
 1618         qoffset = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
 1619         qoffset &= ~(AAC_QUEUE_ALIGN - 1);
 1620         sc->aac_queues =
 1621             (struct aac_queue_table *)((caddr_t)sc->aac_common + qoffset);
 1622         ip->CommHeaderAddress = sc->aac_common_busaddr + qoffset;
 1623 
 1624         sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
 1625                 AAC_HOST_NORM_CMD_ENTRIES;
 1626         sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
 1627                 AAC_HOST_NORM_CMD_ENTRIES;
 1628         sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
 1629                 AAC_HOST_HIGH_CMD_ENTRIES;
 1630         sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
 1631                 AAC_HOST_HIGH_CMD_ENTRIES;
 1632         sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
 1633                 AAC_ADAP_NORM_CMD_ENTRIES;
 1634         sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX] =
 1635                 AAC_ADAP_NORM_CMD_ENTRIES;
 1636         sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_PRODUCER_INDEX] =
 1637                 AAC_ADAP_HIGH_CMD_ENTRIES;
 1638         sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][AAC_CONSUMER_INDEX] =
 1639                 AAC_ADAP_HIGH_CMD_ENTRIES;
 1640         sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]=
 1641                 AAC_HOST_NORM_RESP_ENTRIES;
 1642         sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]=
 1643                 AAC_HOST_NORM_RESP_ENTRIES;
 1644         sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]=
 1645                 AAC_HOST_HIGH_RESP_ENTRIES;
 1646         sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]=
 1647                 AAC_HOST_HIGH_RESP_ENTRIES;
 1648         sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_PRODUCER_INDEX]=
 1649                 AAC_ADAP_NORM_RESP_ENTRIES;
 1650         sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][AAC_CONSUMER_INDEX]=
 1651                 AAC_ADAP_NORM_RESP_ENTRIES;
 1652         sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_PRODUCER_INDEX]=
 1653                 AAC_ADAP_HIGH_RESP_ENTRIES;
 1654         sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][AAC_CONSUMER_INDEX]=
 1655                 AAC_ADAP_HIGH_RESP_ENTRIES;
 1656         sc->aac_qentries[AAC_HOST_NORM_CMD_QUEUE] =
 1657                 &sc->aac_queues->qt_HostNormCmdQueue[0];
 1658         sc->aac_qentries[AAC_HOST_HIGH_CMD_QUEUE] =
 1659                 &sc->aac_queues->qt_HostHighCmdQueue[0];
 1660         sc->aac_qentries[AAC_ADAP_NORM_CMD_QUEUE] =
 1661                 &sc->aac_queues->qt_AdapNormCmdQueue[0];
 1662         sc->aac_qentries[AAC_ADAP_HIGH_CMD_QUEUE] =
 1663                 &sc->aac_queues->qt_AdapHighCmdQueue[0];
 1664         sc->aac_qentries[AAC_HOST_NORM_RESP_QUEUE] =
 1665                 &sc->aac_queues->qt_HostNormRespQueue[0];
 1666         sc->aac_qentries[AAC_HOST_HIGH_RESP_QUEUE] =
 1667                 &sc->aac_queues->qt_HostHighRespQueue[0];
 1668         sc->aac_qentries[AAC_ADAP_NORM_RESP_QUEUE] =
 1669                 &sc->aac_queues->qt_AdapNormRespQueue[0];
 1670         sc->aac_qentries[AAC_ADAP_HIGH_RESP_QUEUE] =
 1671                 &sc->aac_queues->qt_AdapHighRespQueue[0];
 1672 
 1673         /*
 1674          * Do controller-type-specific initialisation
 1675          */
 1676         switch (sc->aac_hwif) {
 1677         case AAC_HWIF_I960RX:
 1678                 AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
 1679                 break;
 1680         case AAC_HWIF_RKT:
 1681                 AAC_SETREG4(sc, AAC_RKT_ODBR, ~0);
 1682                 break;
 1683         default:
 1684                 break;
 1685         }
 1686 
 1687         /*
 1688          * Give the init structure to the controller.
 1689          */
 1690         if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT, 
 1691                              sc->aac_common_busaddr +
 1692                              offsetof(struct aac_common, ac_init), 0, 0, 0,
 1693                              NULL)) {
 1694                 printf("%s: error establishing init structure\n",
 1695                     sc->aac_dev.dv_xname);
 1696                 error = EIO;
 1697                 goto bail_out;
 1698         }
 1699 
 1700         aac_describe_controller(sc);
 1701         aac_startup(sc);
 1702 
 1703         return (0);
 1704 
 1705  bail_out:
 1706         if (state > 3)
 1707                 bus_dmamap_unload(sc->aac_dmat, sc->aac_common_map);
 1708         if (state > 2)
 1709                 bus_dmamap_destroy(sc->aac_dmat, sc->aac_common_map);
 1710         if (state > 1)
 1711                 bus_dmamem_unmap(sc->aac_dmat, (caddr_t)sc->aac_common,
 1712                     sizeof *sc->aac_common);
 1713         if (state > 0)
 1714                 bus_dmamem_free(sc->aac_dmat, &seg, 1);
 1715 
 1716  out:
 1717         return (error);
 1718 }
 1719 
 1720 /*
 1721  * Send a synchronous command to the controller and wait for a result.
 1722  */
 1723 int
 1724 aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
 1725                  u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp)
 1726 {
 1727 //      time_t then;
 1728         int i;
 1729         u_int32_t status;
 1730         u_int16_t reason;
 1731 
 1732         /* populate the mailbox */
 1733         AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3);
 1734 
 1735         /* ensure the sync command doorbell flag is cleared */
 1736         AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
 1737 
 1738         /* then set it to signal the adapter */
 1739         AAC_QNOTIFY(sc, AAC_DB_SYNC_COMMAND);
 1740 
 1741 #if 0
 1742         /* spin waiting for the command to complete */
 1743         then = time_uptime;
 1744         do {
 1745                 if (time_uptime > (then + AAC_IMMEDIATE_TIMEOUT)) {
 1746                         AAC_DPRINTF(AAC_D_MISC, ("timed out"));
 1747                         return(EIO);
 1748                 }
 1749         } while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND));
 1750 #else
 1751         DELAY(AAC_SYNC_DELAY);
 1752 
 1753         /* spin waiting for the command to complete */
 1754         for (i = 0; i < AAC_IMMEDIATE_TIMEOUT * 1000; i++) {
 1755                 reason = AAC_GET_ISTATUS(sc);
 1756                 if (reason & AAC_DB_SYNC_COMMAND)
 1757                         break;
 1758                 reason = AAC_GET_ISTATUS(sc);
 1759                 if (reason & AAC_DB_SYNC_COMMAND)
 1760                         break;
 1761                 reason = AAC_GET_ISTATUS(sc);
 1762                 if (reason & AAC_DB_SYNC_COMMAND)
 1763                         break;
 1764                 DELAY(1000);
 1765         }
 1766         if (i == AAC_IMMEDIATE_TIMEOUT * 1000) {
 1767                 printf("aac_sync_command: failed, reason=%#x\n", reason);
 1768                 return (EIO);
 1769         }
 1770 #endif
 1771 
 1772         /* clear the completion flag */
 1773         AAC_CLEAR_ISTATUS(sc, AAC_DB_SYNC_COMMAND);
 1774 
 1775         /* get the command status */
 1776         status = AAC_GET_MAILBOX(sc, 0);
 1777 
 1778         if (sp != NULL)
 1779                 *sp = status;
 1780 
 1781         return(0);
 1782 }
 1783 
 1784 /*
 1785  * Grab the sync fib area.
 1786  */
 1787 int
 1788 aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags)
 1789 {
 1790 
 1791         /*
 1792          * If the force flag is set, the system is shutting down, or in
 1793          * trouble.  Ignore the mutex.
 1794          */
 1795         if (!(flags & AAC_SYNC_LOCK_FORCE))
 1796                 AAC_LOCK_ACQUIRE(&sc->aac_sync_lock);
 1797 
 1798         *fib = &sc->aac_common->ac_sync_fib;
 1799 
 1800         return (1);
 1801 }
 1802 
 1803 /*
 1804  * Release the sync fib area.
 1805  */
 1806 void
 1807 aac_release_sync_fib(struct aac_softc *sc)
 1808 {
 1809         AAC_LOCK_RELEASE(&sc->aac_sync_lock);
 1810 }
 1811 
 1812 /*
 1813  * Send a synchronous FIB to the controller and wait for a result.
 1814  */
 1815 int
 1816 aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, 
 1817              struct aac_fib *fib, u_int16_t datasize)
 1818 {
 1819 
 1820         if (datasize > AAC_FIB_DATASIZE) {
 1821                 printf("aac_sync_fib 1: datasize=%d AAC_FIB_DATASIZE %lu\n",
 1822                     datasize, AAC_FIB_DATASIZE);
 1823                 return(EINVAL);
 1824         }
 1825 
 1826         /*
 1827          * Set up the sync FIB
 1828          */
 1829         fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED |
 1830                                 AAC_FIBSTATE_INITIALISED |
 1831                                 AAC_FIBSTATE_EMPTY;
 1832         fib->Header.XferState |= xferstate;
 1833         fib->Header.Command = command;
 1834         fib->Header.StructType = AAC_FIBTYPE_TFIB;
 1835         fib->Header.Size = sizeof(struct aac_fib) + datasize;
 1836         fib->Header.SenderSize = sizeof(struct aac_fib);
 1837         fib->Header.SenderFibAddress = 0;       /* Not needed */
 1838         fib->Header.ReceiverFibAddress = sc->aac_common_busaddr +
 1839                                          offsetof(struct aac_common,
 1840                                                   ac_sync_fib);
 1841 
 1842         /*
 1843          * Give the FIB to the controller, wait for a response.
 1844          */
 1845         if (aac_sync_command(sc, AAC_MONKER_SYNCFIB,
 1846                              fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) {
 1847                 AAC_DPRINTF(AAC_D_IO, ("%s: aac_sync_fib: IO error\n",
 1848                                        sc->aac_dev.dv_xname));
 1849                 printf("aac_sync_fib 2\n");
 1850                 return(EIO);
 1851         }
 1852 
 1853         return (0);
 1854 }
 1855 
 1856 /*****************************************************************************
 1857  * Adapter-space FIB queue manipulation
 1858  *
 1859  * Note that the queue implementation here is a little funky; neither the PI or
 1860  * CI will ever be zero.  This behaviour is a controller feature.
 1861  */
 1862 static struct {
 1863         int size;
 1864         int notify;
 1865 } aac_qinfo[] = {
 1866         { AAC_HOST_NORM_CMD_ENTRIES, AAC_DB_COMMAND_NOT_FULL },
 1867         { AAC_HOST_HIGH_CMD_ENTRIES, 0 },
 1868         { AAC_ADAP_NORM_CMD_ENTRIES, AAC_DB_COMMAND_READY },
 1869         { AAC_ADAP_HIGH_CMD_ENTRIES, 0 },
 1870         { AAC_HOST_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_NOT_FULL },
 1871         { AAC_HOST_HIGH_RESP_ENTRIES, 0 },
 1872         { AAC_ADAP_NORM_RESP_ENTRIES, AAC_DB_RESPONSE_READY },
 1873         { AAC_ADAP_HIGH_RESP_ENTRIES, 0 }
 1874 };
 1875 
 1876 /*
 1877  * Atomically insert an entry into the nominated queue, returns 0 on success
 1878  * or EBUSY if the queue is full.
 1879  *
 1880  * Note: it would be more efficient to defer notifying the controller in
 1881  *       the case where we may be inserting several entries in rapid
 1882  *       succession, but implementing this usefully may be difficult
 1883  *       (it would involve a separate queue/notify interface).
 1884  */
 1885 int
 1886 aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
 1887 {
 1888         u_int32_t pi, ci;
 1889         int error;
 1890         u_int32_t fib_size;
 1891         u_int32_t fib_addr;
 1892 
 1893         fib_size = cm->cm_fib->Header.Size;
 1894         fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
 1895 
 1896         /* get the producer/consumer indices */
 1897         pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
 1898         ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
 1899 
 1900         /* wrap the queue? */
 1901         if (pi >= aac_qinfo[queue].size)
 1902                 pi = 0;
 1903 
 1904         /* check for queue full */
 1905         if ((pi + 1) == ci) {
 1906                 error = EBUSY;
 1907                 goto out;
 1908         }
 1909 
 1910         /* populate queue entry */
 1911         (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
 1912         (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
 1913 
 1914         /* update producer index */
 1915         sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
 1916 
 1917         /*
 1918          * To avoid a race with its completion interrupt, place this command on
 1919          * the busy queue prior to advertising it to the controller.
 1920          */
 1921         aac_enqueue_busy(cm);
 1922 
 1923         /* notify the adapter if we know how */
 1924         if (aac_qinfo[queue].notify != 0)
 1925                 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
 1926 
 1927         error = 0;
 1928 
 1929 out:
 1930         return (error);
 1931 }
 1932 
 1933 /*
 1934  * Atomically remove one entry from the nominated queue, returns 0 on success
 1935  * or ENOENT if the queue is empty.
 1936  */
 1937 int
 1938 aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
 1939                 struct aac_fib **fib_addr)
 1940 {
 1941         u_int32_t pi, ci;
 1942         u_int32_t fib_index;
 1943         int notify;
 1944         int error;
 1945 
 1946         /* get the producer/consumer indices */
 1947         pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
 1948         ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
 1949 
 1950         /* check for queue empty */
 1951         if (ci == pi) {
 1952                 error = ENOENT;
 1953                 goto out;
 1954         }
 1955 
 1956         /* wrap the pi so the following test works */
 1957         if (pi >= aac_qinfo[queue].size)
 1958                 pi = 0;
 1959 
 1960         notify = 0;
 1961         if (ci == pi + 1)
 1962                 notify++;
 1963 
 1964         /* wrap the queue? */
 1965         if (ci >= aac_qinfo[queue].size)
 1966                 ci = 0;
 1967 
 1968         /* fetch the entry */
 1969         *fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size;
 1970 
 1971         switch (queue) {
 1972         case AAC_HOST_NORM_CMD_QUEUE:
 1973         case AAC_HOST_HIGH_CMD_QUEUE:
 1974                 /*
 1975                  * The aq_fib_addr is only 32 bits wide so it can't be counted
 1976                  * on to hold an address.  For AIF's, the adapter assumes
 1977                  * that it's giving us an address into the array of AIF fibs.
 1978                  * Therefore, we have to convert it to an index.
 1979                  */
 1980                 fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr /
 1981                         sizeof(struct aac_fib);
 1982                 *fib_addr = &sc->aac_common->ac_fibs[fib_index];
 1983                 break;
 1984 
 1985         case AAC_HOST_NORM_RESP_QUEUE:
 1986         case AAC_HOST_HIGH_RESP_QUEUE:
 1987         {
 1988                 struct aac_command *cm;
 1989 
 1990                 /*
 1991                  * As above, an index is used instead of an actual address.
 1992                  * Gotta shift the index to account for the fast response
 1993                  * bit.  No other correction is needed since this value was
 1994                  * originally provided by the driver via the SenderFibAddress
 1995                  * field.
 1996                  */
 1997                 fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr;
 1998                 cm = sc->aac_commands + (fib_index >> 1);
 1999                 *fib_addr = cm->cm_fib;
 2000 
 2001                 /*
 2002                  * Is this a fast response? If it is, update the fib fields in
 2003                  * local memory since the whole fib isn't DMA'd back up.
 2004                  */
 2005                 if (fib_index & 0x01) {
 2006                         (*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP;
 2007                         *((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL;
 2008                 }
 2009                 break;
 2010         }
 2011         default:
 2012                 panic("Invalid queue in aac_dequeue_fib()");
 2013                 break;
 2014         }
 2015 
 2016 
 2017         /* update consumer index */
 2018         sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
 2019 
 2020         /* if we have made the queue un-full, notify the adapter */
 2021         if (notify && (aac_qinfo[queue].notify != 0))
 2022                 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
 2023         error = 0;
 2024 
 2025 out:
 2026         return (error);
 2027 }
 2028 
 2029 /*
 2030  * Put our response to an Adapter Initialed Fib on the response queue
 2031  */
 2032 int
 2033 aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
 2034 {
 2035         u_int32_t pi, ci;
 2036         int error;
 2037         u_int32_t fib_size;
 2038         u_int32_t fib_addr;
 2039 
 2040         /* Tell the adapter where the FIB is */
 2041         fib_size = fib->Header.Size; 
 2042         fib_addr = fib->Header.SenderFibAddress;
 2043         fib->Header.ReceiverFibAddress = fib_addr;
 2044 
 2045         /* get the producer/consumer indices */
 2046         pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
 2047         ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
 2048 
 2049         /* wrap the queue? */
 2050         if (pi >= aac_qinfo[queue].size)
 2051                 pi = 0;
 2052 
 2053         /* check for queue full */
 2054         if ((pi + 1) == ci) {
 2055                 error = EBUSY;
 2056                 goto out;
 2057         }
 2058 
 2059         /* populate queue entry */
 2060         (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
 2061         (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
 2062 
 2063         /* update producer index */
 2064         sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
 2065 
 2066         /* notify the adapter if we know how */
 2067         if (aac_qinfo[queue].notify != 0)
 2068                 AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
 2069 
 2070         error = 0;
 2071 
 2072 out:
 2073         return(error);
 2074 }
 2075 
 2076 void
 2077 aac_command_timeout(struct aac_command *cm)
 2078 {
 2079         struct aac_softc *sc = cm->cm_sc;
 2080 
 2081         printf("%s: COMMAND %p (flags=%#x) TIMEOUT AFTER %d SECONDS\n",
 2082                sc->aac_dev.dv_xname, cm, cm->cm_flags,
 2083                (int)(time_uptime - cm->cm_timestamp));
 2084 
 2085         if (cm->cm_flags & AAC_CMD_TIMEDOUT)
 2086                 return;
 2087 
 2088         cm->cm_flags |= AAC_CMD_TIMEDOUT;
 2089 
 2090         AAC_PRINT_FIB(sc, cm->cm_fib);
 2091 
 2092         if (cm->cm_flags & AAC_ON_AACQ_BIO) {
 2093                 struct scsi_xfer *xs = cm->cm_private;
 2094                 int s = splbio();
 2095                 xs->error = XS_DRIVER_STUFFUP;
 2096                 xs->flags |= ITSDONE;
 2097                 scsi_done(xs);
 2098                 splx(s);
 2099 
 2100                 aac_remove_bio(cm);
 2101                 aac_unmap_command(cm);
 2102         }
 2103 }
 2104 
 2105 void
 2106 aac_timeout(struct aac_softc *sc)
 2107 {
 2108         struct aac_command *cm;
 2109         time_t deadline;
 2110 
 2111         /*
 2112          * Traverse the busy command list and timeout any commands
 2113          * that are past their deadline.
 2114          */
 2115         deadline = time_uptime - AAC_CMD_TIMEOUT;
 2116         TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
 2117                 if (cm->cm_timestamp  < deadline)
 2118                         aac_command_timeout(cm);
 2119         }
 2120 }
 2121 
 2122 /*
 2123  * Interface Function Vectors
 2124  */
 2125 
 2126 /*
 2127  * Read the current firmware status word.
 2128  */
 2129 int
 2130 aac_sa_get_fwstatus(struct aac_softc *sc)
 2131 {
 2132         return (AAC_GETREG4(sc, AAC_SA_FWSTATUS));
 2133 }
 2134 
 2135 int
 2136 aac_rx_get_fwstatus(struct aac_softc *sc)
 2137 {
 2138         return (AAC_GETREG4(sc, AAC_RX_FWSTATUS));
 2139 }
 2140 
 2141 int
 2142 aac_fa_get_fwstatus(struct aac_softc *sc)
 2143 {
 2144         return (AAC_GETREG4(sc, AAC_FA_FWSTATUS));
 2145 }
 2146 
 2147 int
 2148 aac_rkt_get_fwstatus(struct aac_softc *sc)
 2149 {
 2150         return(AAC_GETREG4(sc, AAC_RKT_FWSTATUS));
 2151 }
 2152 
 2153 /*
 2154  * Notify the controller of a change in a given queue
 2155  */
 2156 
 2157 void
 2158 aac_sa_qnotify(struct aac_softc *sc, int qbit)
 2159 {
 2160         AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit);
 2161 }
 2162 
 2163 void
 2164 aac_rx_qnotify(struct aac_softc *sc, int qbit)
 2165 {
 2166         AAC_SETREG4(sc, AAC_RX_IDBR, qbit);
 2167 }
 2168 
 2169 void
 2170 aac_fa_qnotify(struct aac_softc *sc, int qbit)
 2171 {
 2172         AAC_SETREG2(sc, AAC_FA_DOORBELL1, qbit);
 2173         AAC_FA_HACK(sc);
 2174 }
 2175 
 2176 void
 2177 aac_rkt_qnotify(struct aac_softc *sc, int qbit)
 2178 {
 2179         AAC_SETREG4(sc, AAC_RKT_IDBR, qbit);
 2180 }
 2181 
 2182 /*
 2183  * Get the interrupt reason bits
 2184  */
 2185 int
 2186 aac_sa_get_istatus(struct aac_softc *sc)
 2187 {
 2188         return (AAC_GETREG2(sc, AAC_SA_DOORBELL0));
 2189 }
 2190 
 2191 int
 2192 aac_rx_get_istatus(struct aac_softc *sc)
 2193 {
 2194         return (AAC_GETREG4(sc, AAC_RX_ODBR));
 2195 }
 2196 
 2197 int
 2198 aac_fa_get_istatus(struct aac_softc *sc)
 2199 {
 2200         return (AAC_GETREG2(sc, AAC_FA_DOORBELL0));
 2201 }
 2202 
 2203 int
 2204 aac_rkt_get_istatus(struct aac_softc *sc)
 2205 {
 2206         return(AAC_GETREG4(sc, AAC_RKT_ODBR));
 2207 }
 2208 
 2209 /*
 2210  * Clear some interrupt reason bits
 2211  */
 2212 void
 2213 aac_sa_clear_istatus(struct aac_softc *sc, int mask)
 2214 {
 2215         AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask);
 2216 }
 2217 
 2218 void
 2219 aac_rx_clear_istatus(struct aac_softc *sc, int mask)
 2220 {
 2221         AAC_SETREG4(sc, AAC_RX_ODBR, mask);
 2222 }
 2223 
 2224 void
 2225 aac_fa_clear_istatus(struct aac_softc *sc, int mask)
 2226 {
 2227         AAC_SETREG2(sc, AAC_FA_DOORBELL0_CLEAR, mask);
 2228         AAC_FA_HACK(sc);
 2229 }
 2230 
 2231 void
 2232 aac_rkt_clear_istatus(struct aac_softc *sc, int mask)
 2233 {
 2234         AAC_SETREG4(sc, AAC_RKT_ODBR, mask);
 2235 }
 2236 
 2237 /*
 2238  * Populate the mailbox and set the command word
 2239  */
 2240 void
 2241 aac_sa_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
 2242                    u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
 2243 {
 2244         AAC_SETREG4(sc, AAC_SA_MAILBOX, command);
 2245         AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0);
 2246         AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1);
 2247         AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2);
 2248         AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3);
 2249 }
 2250 
 2251 void
 2252 aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
 2253                    u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
 2254 {
 2255         AAC_SETREG4(sc, AAC_RX_MAILBOX, command);
 2256         AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0);
 2257         AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1);
 2258         AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2);
 2259         AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3);
 2260 }
 2261 
 2262 void
 2263 aac_fa_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
 2264                    u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
 2265 {
 2266         AAC_SETREG4(sc, AAC_FA_MAILBOX, command);
 2267         AAC_FA_HACK(sc);
 2268         AAC_SETREG4(sc, AAC_FA_MAILBOX + 4, arg0);
 2269         AAC_FA_HACK(sc);
 2270         AAC_SETREG4(sc, AAC_FA_MAILBOX + 8, arg1);
 2271         AAC_FA_HACK(sc);
 2272         AAC_SETREG4(sc, AAC_FA_MAILBOX + 12, arg2);
 2273         AAC_FA_HACK(sc);
 2274         AAC_SETREG4(sc, AAC_FA_MAILBOX + 16, arg3);
 2275         AAC_FA_HACK(sc);
 2276 }
 2277 
 2278 void
 2279 aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
 2280                     u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
 2281 {
 2282         AAC_SETREG4(sc, AAC_RKT_MAILBOX, command);
 2283         AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0);
 2284         AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1);
 2285         AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2);
 2286         AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3);
 2287 }
 2288 
 2289 /*
 2290  * Fetch the immediate command status word
 2291  */
 2292 int
 2293 aac_sa_get_mailbox(struct aac_softc *sc, int mb)
 2294 {
 2295         return (AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4)));
 2296 }
 2297 
 2298 int
 2299 aac_rx_get_mailbox(struct aac_softc *sc, int mb)
 2300 {
 2301         return (AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4)));
 2302 }
 2303 
 2304 int
 2305 aac_fa_get_mailbox(struct aac_softc *sc, int mb)
 2306 {
 2307         return (AAC_GETREG4(sc, AAC_FA_MAILBOX + (mb * 4)));
 2308 }
 2309 
 2310 int
 2311 aac_rkt_get_mailbox(struct aac_softc *sc, int mb)
 2312 {
 2313         return(AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4)));
 2314 }
 2315 
 2316 /*
 2317  * Set/clear interrupt masks
 2318  */
 2319 void
 2320 aac_sa_set_interrupts(struct aac_softc *sc, int enable)
 2321 {
 2322         AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts\n",
 2323                                  sc->aac_dev.dv_xname, enable ? "en" : "dis"));
 2324 
 2325         if (enable)
 2326                 AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
 2327         else
 2328                 AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0);
 2329 }
 2330 
 2331 void
 2332 aac_rx_set_interrupts(struct aac_softc *sc, int enable)
 2333 {
 2334         AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts",
 2335                                  sc->aac_dev.dv_xname, enable ? "en" : "dis"));
 2336 
 2337         if (enable)
 2338                 AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
 2339         else
 2340                 AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
 2341 }
 2342 
 2343 void
 2344 aac_fa_set_interrupts(struct aac_softc *sc, int enable)
 2345 {
 2346         AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts",
 2347                                  sc->aac_dev.dv_xname, enable ? "en" : "dis"));
 2348 
 2349         if (enable) {
 2350                 AAC_SETREG2((sc), AAC_FA_MASK0_CLEAR, AAC_DB_INTERRUPTS);
 2351                 AAC_FA_HACK(sc);
 2352         } else {
 2353                 AAC_SETREG2((sc), AAC_FA_MASK0, ~0);
 2354                 AAC_FA_HACK(sc);
 2355         }
 2356 }
 2357 
 2358 void
 2359 aac_rkt_set_interrupts(struct aac_softc *sc, int enable)
 2360 {
 2361         AAC_DPRINTF(AAC_D_INTR, ("%s: %sable interrupts",
 2362                                  sc->aac_dev.dv_xname, enable ? "en" : "dis"));
 2363 
 2364         if (enable)
 2365                 AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS);
 2366         else
 2367                 AAC_SETREG4(sc, AAC_RKT_OIMR, ~0);
 2368 }
 2369 
 2370 void
 2371 aac_eval_mapping(size, cyls, heads, secs)
 2372         u_int32_t size;
 2373         int *cyls, *heads, *secs;
 2374 {
 2375         *cyls = size / AAC_HEADS / AAC_SECS;
 2376         if (*cyls < AAC_MAXCYLS) {
 2377                 *heads = AAC_HEADS;
 2378                 *secs = AAC_SECS;
 2379         } else {
 2380                 /* Too high for 64 * 32 */
 2381                 *cyls = size / AAC_MEDHEADS / AAC_MEDSECS;
 2382                 if (*cyls < AAC_MAXCYLS) {
 2383                         *heads = AAC_MEDHEADS;
 2384                         *secs = AAC_MEDSECS;
 2385                 } else {
 2386                         /* Too high for 127 * 63 */
 2387                         *cyls = size / AAC_BIGHEADS / AAC_BIGSECS;
 2388                         *heads = AAC_BIGHEADS;
 2389                         *secs = AAC_BIGSECS;
 2390                 }
 2391         }
 2392 }
 2393 
 2394 void
 2395 aac_copy_internal_data(struct scsi_xfer *xs, u_int8_t *data, size_t size)
 2396 {
 2397         struct aac_softc *sc = xs->sc_link->adapter_softc;
 2398         size_t copy_cnt;
 2399 
 2400         AAC_DPRINTF(AAC_D_MISC, ("%s: aac_copy_internal_data\n",
 2401                                  sc->aac_dev.dv_xname));
 2402 
 2403         if (!xs->datalen)
 2404                 printf("%s: uio move not yet supported\n",
 2405                        sc->aac_dev.dv_xname);
 2406         else {
 2407                 copy_cnt = MIN(size, xs->datalen);
 2408                 bcopy(data, xs->data, copy_cnt);
 2409         }
 2410 }
 2411 
 2412 /* Emulated SCSI operation on cache device */
 2413 void
 2414 aac_internal_cache_cmd(struct scsi_xfer *xs)
 2415 {
 2416         struct scsi_link *link = xs->sc_link;
 2417         struct aac_softc *sc = link->adapter_softc;
 2418         struct scsi_inquiry_data inq;
 2419         struct scsi_sense_data sd;
 2420         struct scsi_read_cap_data rcd;
 2421         u_int8_t target = link->target;
 2422 
 2423         AAC_DPRINTF(AAC_D_CMD, ("aac_internal_cache_cmd: ",
 2424                                 sc->aac_dev.dv_xname));
 2425 
 2426         switch (xs->cmd->opcode) {
 2427         case TEST_UNIT_READY:
 2428         case START_STOP:
 2429 #if 0
 2430         case VERIFY:
 2431 #endif
 2432                 AAC_DPRINTF(AAC_D_CMD, ("opc %#x tgt %d ", xs->cmd->opcode,
 2433                     target));
 2434                 break;
 2435 
 2436         case REQUEST_SENSE:
 2437                 AAC_DPRINTF(AAC_D_CMD, ("REQUEST SENSE tgt %d ", target));
 2438                 bzero(&sd, sizeof sd);
 2439                 sd.error_code = 0x70;
 2440                 sd.segment = 0;
 2441                 sd.flags = SKEY_NO_SENSE;
 2442                 aac_enc32(sd.info, 0);
 2443                 sd.extra_len = 0;
 2444                 aac_copy_internal_data(xs, (u_int8_t *)&sd, sizeof sd);
 2445                 break;
 2446 
 2447         case INQUIRY:
 2448                 AAC_DPRINTF(AAC_D_CMD, ("INQUIRY tgt %d devtype %x ", target,
 2449                     sc->aac_hdr[target].hd_devtype));
 2450                 bzero(&inq, sizeof inq);
 2451                 /* XXX How do we detect removable/CD-ROM devices?  */
 2452                 inq.device = T_DIRECT;
 2453                 inq.dev_qual2 = 0;
 2454                 inq.version = 2;
 2455                 inq.response_format = 2;
 2456                 inq.additional_length = 32;
 2457                 strlcpy(inq.vendor, "Adaptec", sizeof inq.vendor);
 2458                 snprintf(inq.product, sizeof inq.product, "Container #%02d",
 2459                     target);
 2460                 strlcpy(inq.revision, "   ", sizeof inq.revision);
 2461                 aac_copy_internal_data(xs, (u_int8_t *)&inq, sizeof inq);
 2462                 break;
 2463 
 2464         case READ_CAPACITY:
 2465                 AAC_DPRINTF(AAC_D_CMD, ("READ CAPACITY tgt %d ", target));
 2466                 bzero(&rcd, sizeof rcd);
 2467                 _lto4b(sc->aac_hdr[target].hd_size - 1, rcd.addr);
 2468                 _lto4b(AAC_BLOCK_SIZE, rcd.length);
 2469                 aac_copy_internal_data(xs, (u_int8_t *)&rcd, sizeof rcd);
 2470                 break;
 2471 
 2472         default:
 2473                 AAC_DPRINTF(AAC_D_CMD, ("\n"));
 2474                 printf("aac_internal_cache_cmd got bad opcode: %#x\n",
 2475                     xs->cmd->opcode);
 2476                 xs->error = XS_DRIVER_STUFFUP;
 2477                 return;
 2478         }
 2479 
 2480         xs->error = XS_NOERROR;
 2481 }
 2482 
 2483 void
 2484 aacminphys(struct buf *bp)
 2485 {
 2486 #if 0
 2487         u_int8_t *buf = bp->b_data;
 2488         paddr_t pa;
 2489         long off;
 2490 #endif
 2491 
 2492         AAC_DPRINTF(AAC_D_MISC, ("aacminphys(0x%x)\n", bp));
 2493 
 2494 #if 0   /* As this is way more than MAXPHYS it's really not necessary. */
 2495         if (bp->b_bcount > ((AAC_MAXOFFSETS - 1) * PAGE_SIZE))
 2496                 bp->b_bcount = ((AAC_MAXOFFSETS - 1) * PAGE_SIZE);
 2497 #endif
 2498 
 2499 #if 0
 2500         for (off = PAGE_SIZE, pa = vtophys(buf); off < bp->b_bcount;
 2501             off += PAGE_SIZE)
 2502                 if (pa + off != vtophys(buf + off)) {
 2503                         bp->b_bcount = off;
 2504                         break;
 2505                 }
 2506 #endif
 2507         minphys(bp);
 2508 }
 2509 
 2510 int
 2511 aac_raw_scsi_cmd(struct scsi_xfer *xs)
 2512 {
 2513 #ifdef AAC_DEBUG
 2514         struct aac_softc *sc = xs->sc_link->adapter_softc;
 2515 #endif
 2516         AAC_DPRINTF(AAC_D_CMD, ("%s: aac_raw_scsi_cmd\n",
 2517                                 sc->aac_dev.dv_xname));
 2518 
 2519         /* XXX Not yet implemented */
 2520         xs->error = XS_DRIVER_STUFFUP;
 2521         return (COMPLETE);
 2522 }
 2523 
 2524 int
 2525 aac_scsi_cmd(struct scsi_xfer *xs)
 2526 {
 2527         struct scsi_link *link = xs->sc_link;
 2528         struct aac_softc *sc = link->adapter_softc;
 2529         u_int8_t target = link->target;
 2530         struct aac_command *cm;
 2531         u_int32_t blockno, blockcnt;
 2532         struct scsi_rw *rw;
 2533         struct scsi_rw_big *rwb;
 2534         int retval = SUCCESSFULLY_QUEUED;
 2535         int s = splbio();
 2536 
 2537         xs->error = XS_NOERROR;
 2538 
 2539         if (target >= AAC_MAX_CONTAINERS || !sc->aac_hdr[target].hd_present ||
 2540             link->lun != 0) {
 2541                 /*
 2542                  * XXX Should be XS_SENSE but that would require setting up a
 2543                  * faked sense too.
 2544                  */
 2545                 xs->error = XS_DRIVER_STUFFUP;
 2546                 xs->flags |= ITSDONE;
 2547                 scsi_done(xs);
 2548                 splx(s);
 2549                 return (COMPLETE);
 2550         }
 2551 
 2552         AAC_DPRINTF(AAC_D_CMD, ("%s: aac_scsi_cmd: ", sc->aac_dev.dv_xname));
 2553 
 2554         xs->error = XS_NOERROR;
 2555         cm = NULL;
 2556         link = xs->sc_link;
 2557         target = link->target;
 2558 
 2559         switch (xs->cmd->opcode) {
 2560         case TEST_UNIT_READY:
 2561         case REQUEST_SENSE:
 2562         case INQUIRY:
 2563         case START_STOP:
 2564         case READ_CAPACITY:
 2565 #if 0
 2566         case VERIFY:
 2567 #endif
 2568                 aac_internal_cache_cmd(xs);
 2569                 xs->flags |= ITSDONE;
 2570                 scsi_done(xs);
 2571                 goto ready;
 2572 
 2573         case PREVENT_ALLOW:
 2574                 AAC_DPRINTF(AAC_D_CMD, ("PREVENT/ALLOW "));
 2575                 /* XXX Not yet implemented */
 2576                 xs->error = XS_NOERROR;
 2577                 xs->flags |= ITSDONE;
 2578                 scsi_done(xs);
 2579                 goto ready;
 2580 
 2581         case SYNCHRONIZE_CACHE:
 2582                 AAC_DPRINTF(AAC_D_CMD, ("SYNCHRONIZE_CACHE "));
 2583                 /* XXX Not yet implemented */
 2584                 xs->error = XS_NOERROR;
 2585                 xs->flags |= ITSDONE;
 2586                 scsi_done(xs);
 2587                 goto ready;
 2588 
 2589         default:
 2590                 AAC_DPRINTF(AAC_D_CMD, ("unknown opc %#x ", xs->cmd->opcode));
 2591                 /* XXX Not yet implemented */
 2592                 xs->error = XS_DRIVER_STUFFUP;
 2593                 xs->flags |= ITSDONE;
 2594                 scsi_done(xs);
 2595                 goto ready;
 2596 
 2597         case READ_COMMAND:
 2598         case READ_BIG:
 2599         case WRITE_COMMAND:
 2600         case WRITE_BIG:
 2601                 AAC_DPRINTF(AAC_D_CMD, ("rw opc %#x ", xs->cmd->opcode));
 2602                         
 2603                 /* A read or write operation. */
 2604                 if (xs->cmdlen == 6) {
 2605                         rw = (struct scsi_rw *)xs->cmd;
 2606                         blockno = _3btol(rw->addr) & 
 2607                                 (SRW_TOPADDR << 16 | 0xffff);
 2608                         blockcnt = rw->length ? rw->length : 0x100;
 2609                 } else {
 2610                         rwb = (struct scsi_rw_big *)xs->cmd;
 2611                         blockno = _4btol(rwb->addr);
 2612                         blockcnt = _2btol(rwb->length);
 2613                 }
 2614 
 2615                 AAC_DPRINTF(AAC_D_CMD, ("blkno=%d bcount=%d ",
 2616                                         xs->cmd->opcode, blockno, blockcnt));
 2617 
 2618                 if (blockno >= sc->aac_hdr[target].hd_size ||
 2619                     blockno + blockcnt > sc->aac_hdr[target].hd_size) {
 2620                         AAC_DPRINTF(AAC_D_CMD, ("\n"));
 2621                         printf("%s: out of bounds %u-%u >= %u\n",
 2622                                sc->aac_dev.dv_xname, blockno,
 2623                                blockcnt, sc->aac_hdr[target].hd_size);
 2624                         /*
 2625                          * XXX Should be XS_SENSE but that
 2626                          * would require setting up a faked
 2627                          * sense too.
 2628                          */
 2629                         xs->error = XS_DRIVER_STUFFUP;
 2630                         xs->flags |= ITSDONE;
 2631                         scsi_done(xs);
 2632                         goto ready;
 2633                 }
 2634 
 2635                 if (aac_alloc_command(sc, &cm)) {
 2636                         AAC_DPRINTF(AAC_D_CMD,
 2637                                     (": out of commands, try later\n"));
 2638                         /*
 2639                          * We are out of commands, try again
 2640                          * in a little while.
 2641                          */
 2642                         splx(s);
 2643                         return (TRY_AGAIN_LATER);
 2644                 }
 2645 
 2646                 /* fill out the command */
 2647                 cm->cm_data = (void *)xs->data;
 2648                 cm->cm_datalen = xs->datalen;
 2649                 cm->cm_complete = aac_bio_complete;
 2650                 cm->cm_private = xs;
 2651                 cm->cm_timestamp = time_uptime;
 2652                 cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
 2653                 cm->cm_blkno = blockno;
 2654                 cm->cm_bcount = blockcnt;
 2655 
 2656                 AAC_DPRINTF(AAC_D_CMD, ("\n"));
 2657                 aac_enqueue_bio(cm);
 2658                 aac_startio(sc);
 2659 
 2660                 /* XXX what if enqueue did not start a transfer? */
 2661                 if (xs->flags & SCSI_POLL) {
 2662                         if (!aac_wait_command(cm, xs->timeout))
 2663                         {
 2664                                 printf("%s: command timed out\n",
 2665                                        sc->aac_dev.dv_xname);
 2666                                 splx(s);
 2667                                 return (TRY_AGAIN_LATER);
 2668                         }
 2669                         xs->flags |= ITSDONE;
 2670                         scsi_done(xs);
 2671                 }
 2672         }
 2673 
 2674  ready:
 2675         /*
 2676          * Don't process the queue if we are polling.
 2677          */
 2678         if (xs->flags & SCSI_POLL)
 2679                 retval = COMPLETE;
 2680 
 2681         splx(s);
 2682         AAC_DPRINTF(AAC_D_CMD, ("%s: scsi_cmd complete\n",
 2683                                 sc->aac_dev.dv_xname));
 2684         return (retval);
 2685 }
 2686 
 2687 /*
 2688  * Debugging and Diagnostics
 2689  */
 2690 
 2691 /*
 2692  * Print some information about the controller.
 2693  */
 2694 void
 2695 aac_describe_controller(struct aac_softc *sc)
 2696 {
 2697         struct aac_fib *fib;
 2698         struct aac_adapter_info *info;
 2699 
 2700         aac_alloc_sync_fib(sc, &fib, 0);
 2701 
 2702         fib->data[0] = 0;
 2703         if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
 2704                 printf("%s: RequestAdapterInfo failed 2\n",
 2705                        sc->aac_dev.dv_xname);
 2706                 aac_release_sync_fib(sc);
 2707                 return;
 2708         }
 2709         info = (struct aac_adapter_info *)&fib->data[0];   
 2710 
 2711         printf("%s: %s %dMHz, %dMB cache memory, %s\n", sc->aac_dev.dv_xname,
 2712                aac_describe_code(aac_cpu_variant, info->CpuVariant),
 2713                info->ClockSpeed, info->BufferMem / (1024 * 1024), 
 2714                aac_describe_code(aac_battery_platform, info->batteryPlatform));
 2715 
 2716         /* save the kernel revision structure for later use */
 2717         sc->aac_revision = info->KernelRevision;
 2718         printf("%s: Kernel %d.%d-%d, Build %d, S/N %6X\n",
 2719                sc->aac_dev.dv_xname,
 2720                info->KernelRevision.external.comp.major,
 2721                info->KernelRevision.external.comp.minor,
 2722                info->KernelRevision.external.comp.dash,
 2723                info->KernelRevision.buildNumber,
 2724                (u_int32_t)(info->SerialNumber & 0xffffff));
 2725 
 2726         aac_release_sync_fib(sc);
 2727 
 2728 #if 0
 2729         if (1 || bootverbose) {
 2730                 device_printf(sc->aac_dev, "Supported Options=%b\n",
 2731                               sc->supported_options,
 2732                               "\20"
 2733                               "\1SNAPSHOT"
 2734                               "\2CLUSTERS"
 2735                               "\3WCACHE"
 2736                               "\4DATA64"
 2737                               "\5HOSTTIME"
 2738                               "\6RAID50"
 2739                               "\7WINDOW4GB"
 2740                               "\10SCSIUPGD"
 2741                               "\11SOFTERR"
 2742                               "\12NORECOND"
 2743                               "\13SGMAP64"
 2744                               "\14ALARM"
 2745                               "\15NONDASD");
 2746         }
 2747 #endif
 2748 }
 2749 
 2750 /*
 2751  * Look up a text description of a numeric error code and return a pointer to
 2752  * same.
 2753  */
 2754 char *
 2755 aac_describe_code(struct aac_code_lookup *table, u_int32_t code)
 2756 {
 2757         int i;
 2758 
 2759         for (i = 0; table[i].string != NULL; i++)
 2760                 if (table[i].code == code)
 2761                         return(table[i].string);
 2762         return(table[i + 1].string);
 2763 }
 2764 
 2765 #ifdef AAC_DEBUG
 2766 /*
 2767  * Print a FIB
 2768  */
 2769 void
 2770 aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller)
 2771 {
 2772         printf("%s: FIB @ %p\n", caller, fib);
 2773         printf("  XferState %b\n", fib->Header.XferState, "\20"
 2774             "\1HOSTOWNED"
 2775             "\2ADAPTEROWNED"
 2776             "\3INITIALISED"
 2777             "\4EMPTY"
 2778             "\5FROMPOOL"
 2779             "\6FROMHOST"
 2780             "\7FROMADAP"
 2781             "\10REXPECTED"
 2782             "\11RNOTEXPECTED"
 2783             "\12DONEADAP"
 2784             "\13DONEHOST"
 2785             "\14HIGH"
 2786             "\15NORM"
 2787             "\16ASYNC"
 2788             "\17PAGEFILEIO"
 2789             "\20SHUTDOWN"
 2790             "\21LAZYWRITE"
 2791             "\22ADAPMICROFIB"
 2792             "\23BIOSFIB"
 2793             "\24FAST_RESPONSE"
 2794             "\25APIFIB\n");
 2795         printf("  Command         %d\n", fib->Header.Command);
 2796         printf("  StructType      %d\n", fib->Header.StructType);
 2797         printf("  Flags           0x%x\n", fib->Header.Flags);
 2798         printf("  Size            %d\n", fib->Header.Size);
 2799         printf("  SenderSize      %d\n", fib->Header.SenderSize);
 2800         printf("  SenderAddress   0x%x\n", fib->Header.SenderFibAddress);
 2801         printf("  ReceiverAddress 0x%x\n", fib->Header.ReceiverFibAddress);
 2802         printf("  SenderData      0x%x\n", fib->Header.SenderData);
 2803         switch(fib->Header.Command) {
 2804         case ContainerCommand: {
 2805                 struct aac_blockread *br = (struct aac_blockread *)fib->data;
 2806                 struct aac_blockwrite *bw = (struct aac_blockwrite *)fib->data;
 2807                 struct aac_sg_table *sg = NULL;
 2808                 int i;
 2809 
 2810                 if (br->Command == VM_CtBlockRead) {
 2811                         printf("  BlockRead: container %d  0x%x/%d\n", 
 2812                             br->ContainerId, br->BlockNumber, br->ByteCount);
 2813                             sg = &br->SgMap;
 2814                 }
 2815                 if (bw->Command == VM_CtBlockWrite) {
 2816                         printf("  BlockWrite: container %d  0x%x/%d (%s)\n", 
 2817                             bw->ContainerId, bw->BlockNumber, bw->ByteCount,
 2818                             bw->Stable == CSTABLE ? "stable" : "unstable");
 2819                         sg = &bw->SgMap;
 2820                 }
 2821                 if (sg != NULL) {
 2822                         printf("  %d s/g entries\n", sg->SgCount);
 2823                         for (i = 0; i < sg->SgCount; i++)
 2824                                 printf("  0x%08x/%d\n",
 2825                                        sg->SgEntry[i].SgAddress,
 2826                                        sg->SgEntry[i].SgByteCount);
 2827                 }
 2828                 break;
 2829         }
 2830         default:
 2831                 printf("   %16D\n", fib->data, " ");
 2832                 printf("   %16D\n", fib->data + 16, " ");
 2833         break;
 2834         }
 2835 }
 2836 
 2837 /*
 2838  * Describe an AIF we have received.
 2839  */
 2840 void
 2841 aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
 2842 {
 2843         printf("%s: print_aif: ", sc->aac_dev.dv_xname);
 2844 
 2845         switch(aif->command) {
 2846         case AifCmdEventNotify:
 2847                 printf("EventNotify(%d)\n", aif->seqNumber);
 2848 
 2849                 switch(aif->data.EN.type) {
 2850                 case AifEnGeneric:
 2851                         /* Generic notification */
 2852                         printf("\t(Generic) %.*s\n", 
 2853                                (int)sizeof(aif->data.EN.data.EG),
 2854                                aif->data.EN.data.EG.text);
 2855                         break;
 2856                 case AifEnTaskComplete:
 2857                         /* Task has completed */
 2858                         printf("\t(TaskComplete)\n");
 2859                         break;
 2860                 case AifEnConfigChange:
 2861                         /* Adapter configuration change occurred */
 2862                         printf("\t(ConfigChange)\n");
 2863                         break;
 2864                 case AifEnContainerChange:
 2865                         /* Adapter specific container configuration change */
 2866                         printf("\t(ContainerChange) container %d,%d\n", 
 2867                                aif->data.EN.data.ECC.container[0], 
 2868                                aif->data.EN.data.ECC.container[1]);
 2869                         break;
 2870                 case AifEnDeviceFailure:
 2871                         /* SCSI device failed */
 2872                         printf("\t(DeviceFailure) handle %d\n", 
 2873                                aif->data.EN.data.EDF.deviceHandle);
 2874                         break;
 2875                 case AifEnMirrorFailover:
 2876                         /* Mirror failover started */
 2877                         printf("\t(MirrorFailover) container %d failed, "
 2878                                "migrating from slice %d to %d\n",
 2879                                aif->data.EN.data.EMF.container, 
 2880                                aif->data.EN.data.EMF.failedSlice, 
 2881                                aif->data.EN.data.EMF.creatingSlice);
 2882                         break;
 2883                 case AifEnContainerEvent:
 2884                         /* Significant container event */
 2885                         printf("\t(ContainerEvent) container %d event %d\n",
 2886                                aif->data.EN.data.ECE.container,
 2887                                aif->data.EN.data.ECE.eventType);        
 2888                         break;
 2889                 case AifEnFileSystemChange:
 2890                         /* File system changed */
 2891                         printf("\t(FileSystemChange)\n");
 2892                         break;
 2893                 case AifEnConfigPause:
 2894                         /* Container pause event */
 2895                         printf("\t(ConfigPause)\n");
 2896                         break;
 2897                 case AifEnConfigResume:
 2898                         /* Container resume event */
 2899                         printf("\t(ConfigResume)\n");
 2900                         break;
 2901                 case AifEnFailoverChange:
 2902                         /* Failover space assignment changed */
 2903                         printf("\t(FailoverChange)\n");
 2904                         break;
 2905                 case AifEnRAID5RebuildDone:
 2906                         /* RAID5 rebuild finished */
 2907                         printf("\t(RAID5RebuildDone)\n");
 2908                         break;
 2909                 case AifEnEnclosureManagement:
 2910                         /* Enclosure management event */
 2911                         printf("\t(EnclosureManagement) EMPID %d unit %d "
 2912                                "event %d\n",
 2913                                aif->data.EN.data.EEE.empID,
 2914                                aif->data.EN.data.EEE.unitID, 
 2915                                aif->data.EN.data.EEE.eventType);
 2916                         break;
 2917                 case AifEnBatteryEvent:
 2918                         /* Significant NV battery event */
 2919                         printf("\t(BatteryEvent) %d (state was %d, is %d\n",
 2920                                aif->data.EN.data.EBE.transition_type,
 2921                                aif->data.EN.data.EBE.current_state,
 2922                                aif->data.EN.data.EBE.prior_state);
 2923                         break;
 2924                 case AifEnAddContainer:
 2925                         /* A new container was created. */
 2926                         printf("\t(AddContainer)\n");
 2927                         break;          
 2928                 case AifEnDeleteContainer:
 2929                         /* A container was deleted. */
 2930                         printf("\t(DeleteContainer)\n");
 2931                         break;
 2932                 case AifEnBatteryNeedsRecond:
 2933                         /* The battery needs reconditioning */
 2934                         printf("\t(BatteryNeedsRecond)\n");
 2935                         break;
 2936                 case AifEnClusterEvent:
 2937                         /* Some cluster event */
 2938                         printf("\t(ClusterEvent) event %d\n", 
 2939                                aif->data.EN.data.ECLE.eventType);
 2940                         break;
 2941                 case AifEnDiskSetEvent:
 2942                         /* A disk set event occured. */
 2943                         printf("(DiskSetEvent) event %d "
 2944                                "diskset %lld creator %lld\n",
 2945                                aif->data.EN.data.EDS.eventType, 
 2946                                aif->data.EN.data.EDS.DsNum, 
 2947                                aif->data.EN.data.EDS.CreatorId);
 2948                         break;
 2949                 case AifDenMorphComplete:
 2950                         /* A morph operation completed */
 2951                         printf("\t(MorphComplete)\n");
 2952                         break;
 2953                 case AifDenVolumeExtendComplete:
 2954                         /* A volume expand operation completed */
 2955                         printf("\t(VolumeExtendComplete)\n");
 2956                         break;
 2957                 default:
 2958                         printf("\t(%d)\n", aif->data.EN.type);
 2959                         break;
 2960                 }
 2961                 break;
 2962         case AifCmdJobProgress:
 2963         {
 2964                 char    *status;
 2965                 switch(aif->data.PR[0].status) {
 2966                 case AifJobStsSuccess:
 2967                         status = "success"; break;
 2968                 case AifJobStsFinished:
 2969                         status = "finished"; break;
 2970                 case AifJobStsAborted:
 2971                         status = "aborted"; break;
 2972                 case AifJobStsFailed:
 2973                         status = "failed"; break;
 2974                 case AifJobStsSuspended:
 2975                         status = "suspended"; break;
 2976                 case AifJobStsRunning:
 2977                         status = "running"; break;
 2978                 default:
 2979                         status = "unknown status"; break;
 2980                 }               
 2981         
 2982                 printf("JobProgress (%d) - %s (%d, %d)\n",
 2983                        aif->seqNumber, status, 
 2984                        aif->data.PR[0].currentTick,
 2985                        aif->data.PR[0].finalTick);
 2986 
 2987                 switch(aif->data.PR[0].jd.type) {
 2988                 case AifJobScsiZero:
 2989                         /* SCSI dev clear operation */
 2990                         printf("\t(ScsiZero) handle %d\n",
 2991                                       aif->data.PR[0].jd.client.scsi_dh);
 2992                         break;
 2993                 case AifJobScsiVerify:
 2994                         /* SCSI device Verify operation NO REPAIR */
 2995                         printf("\t(ScsiVerify) handle %d\n",
 2996                                       aif->data.PR[0].jd.client.scsi_dh);
 2997                         break;
 2998                 case AifJobScsiExercise:
 2999                         /* SCSI device Exercise operation */
 3000                         printf("\t(ScsiExercise) handle %d\n",
 3001                                aif->data.PR[0].jd.client.scsi_dh);
 3002                         break;
 3003                 case AifJobScsiVerifyRepair:
 3004                         /* SCSI device Verify operation WITH repair */
 3005                         printf("\t(ScsiVerifyRepair) handle %d\n",
 3006                                aif->data.PR[0].jd.client.scsi_dh);
 3007                         break;
 3008                 case AifJobCtrZero:
 3009                         /* Container clear operation */
 3010                         printf("\t(ContainerZero) container %d\n", 
 3011                                aif->data.PR[0].jd.client.container.src);
 3012                         break;
 3013                 case AifJobCtrCopy:
 3014                         /* Container copy operation */
 3015                         printf("\t(ContainerCopy) container %d to %d\n", 
 3016                                aif->data.PR[0].jd.client.container.src,
 3017                                aif->data.PR[0].jd.client.container.dst);
 3018                         break;
 3019                 case AifJobCtrCreateMirror:
 3020                         /* Container Create Mirror operation */
 3021                         printf("\t(ContainerCreateMirror) container %d\n",
 3022                                aif->data.PR[0].jd.client.container.src);
 3023                         /* XXX two containers? */
 3024                         break;
 3025                 case AifJobCtrMergeMirror:
 3026                         /* Container Merge Mirror operation */
 3027                         printf("\t(ContainerMergeMirror) container %d\n",
 3028                                aif->data.PR[0].jd.client.container.src);
 3029                         /* XXX two containers? */
 3030                         break;
 3031                 case AifJobCtrScrubMirror:
 3032                         /* Container Scrub Mirror operation */
 3033                         printf("\t(ContainerScrubMirror) container %d\n",
 3034                                aif->data.PR[0].jd.client.container.src);
 3035                         break;
 3036                 case AifJobCtrRebuildRaid5:
 3037                         /* Container Rebuild Raid5 operation */
 3038                         printf("\t(ContainerRebuildRaid5) container %d\n",
 3039                                aif->data.PR[0].jd.client.container.src);
 3040                         break;
 3041                 case AifJobCtrScrubRaid5:
 3042                         /* Container Scrub Raid5 operation */
 3043                         printf("\t(ContainerScrubRaid5) container %d\n", 
 3044                                aif->data.PR[0].jd.client.container.src);
 3045                         break;
 3046                 case AifJobCtrMorph:
 3047                         /* Container morph operation */
 3048                         printf("\t(ContainerMorph) container %d\n",
 3049                                aif->data.PR[0].jd.client.container.src);
 3050                         /* XXX two containers? */
 3051                         break;
 3052                 case AifJobCtrPartCopy:
 3053                         /* Container Partition copy operation */
 3054                         printf("\t(ContainerPartCopy) container %d to %d\n",
 3055                                aif->data.PR[0].jd.client.container.src,
 3056                                aif->data.PR[0].jd.client.container.dst);
 3057                         break;
 3058                 case AifJobCtrRebuildMirror:
 3059                         /* Container Rebuild Mirror operation */
 3060                         printf("\t(ContainerRebuildMirror) container %d\n",
 3061                                aif->data.PR[0].jd.client.container.src);
 3062                         break;
 3063                 case AifJobCtrCrazyCache:
 3064                         /* crazy cache */
 3065                         printf("\t(ContainerCrazyCache) container %d\n", 
 3066                                aif->data.PR[0].jd.client.container.src);
 3067                         /* XXX two containers? */
 3068                         break;
 3069                 case AifJobFsCreate:
 3070                         /* File System Create operation */
 3071                         printf("\t(FsCreate)\n");
 3072                         break;
 3073                 case AifJobFsVerify:
 3074                         /* File System Verify operation */
 3075                         printf("\t(FsVerivy)\n");
 3076                         break;
 3077                 case AifJobFsExtend:
 3078                         /* File System Extend operation */
 3079                         printf("\t(FsExtend)\n");
 3080                         break;
 3081                 case AifJobApiFormatNTFS:
 3082                         /* Format a drive to NTFS */
 3083                         printf("\t(FormatNTFS)\n");
 3084                         break;
 3085                 case AifJobApiFormatFAT:
 3086                         /* Format a drive to FAT */
 3087                         printf("\t(FormatFAT)\n");
 3088                         break;
 3089                 case AifJobApiUpdateSnapshot:
 3090                         /* update the read/write half of a snapshot */
 3091                         printf("\t(UpdateSnapshot)\n");
 3092                         break;
 3093                 case AifJobApiFormatFAT32:
 3094                         /* Format a drive to FAT32 */
 3095                         printf("\t(FormatFAT32)\n");
 3096                         break;
 3097                 case AifJobCtlContinuousCtrVerify:
 3098                         /* Adapter operation */
 3099                         printf("\t(ContinuousCtrVerify)\n");
 3100                         break;
 3101                 default:
 3102                         printf("\t(%d)\n", aif->data.PR[0].jd.type);
 3103                         break;
 3104                 }
 3105                 break;
 3106         }
 3107         case AifCmdAPIReport:
 3108                 printf("APIReport (%d)\n", aif->seqNumber);
 3109                 break;
 3110         case AifCmdDriverNotify:
 3111                 printf("DriverNotify (%d)\n", aif->seqNumber);
 3112                 break;
 3113         default:
 3114                 printf("AIF %d (%d)\n", aif->command, aif->seqNumber);
 3115                 break;
 3116         }
 3117 }
 3118 #endif

/* [<][>][^][v][top][bottom][index][help] */