The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/twe/twe.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2000 Michael Smith
    3  * Copyright (c) 2003 Paul Saab
    4  * Copyright (c) 2003 Vinod Kashyap
    5  * Copyright (c) 2000 BSDi
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   11  * 1. Redistributions of source code must retain the above copyright
   12  *    notice, this list of conditions and the following disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  *      $FreeBSD: releng/6.4/sys/dev/twe/twe.c 176292 2008-02-14 20:20:06Z brueffer $
   30  */
   31 
   32 /*
   33  * Driver for the 3ware Escalade family of IDE RAID controllers.
   34  */
   35 
   36 #include <dev/twe/twe_compat.h>
   37 #include <dev/twe/twereg.h>
   38 #include <dev/twe/tweio.h>
   39 #include <dev/twe/twevar.h>
   40 #define TWE_DEFINE_TABLES
   41 #include <dev/twe/twe_tables.h>
   42 
   43 /*
   44  * Command submission.
   45  */
   46 static int      twe_get_param_1(struct twe_softc *sc, int table_id, int param_id, u_int8_t *result);
   47 static int      twe_get_param_2(struct twe_softc *sc, int table_id, int param_id, u_int16_t *result);
   48 static int      twe_get_param_4(struct twe_softc *sc, int table_id, int param_id, u_int32_t *result);
   49 static void     *twe_get_param(struct twe_softc *sc, int table_id, int parameter_id, size_t size, 
   50                                                void (* func)(struct twe_request *tr));
   51 #ifdef TWE_SHUTDOWN_NOTIFICATION
   52 static int      twe_set_param_1(struct twe_softc *sc, int table_id, int param_id, u_int8_t value);
   53 #endif
   54 #if 0
   55 static int      twe_set_param_2(struct twe_softc *sc, int table_id, int param_id, u_int16_t value);
   56 static int      twe_set_param_4(struct twe_softc *sc, int table_id, int param_id, u_int32_t value);
   57 #endif
   58 static int      twe_set_param(struct twe_softc *sc, int table_id, int param_id, int param_size, 
   59                                               void *data);
   60 static int      twe_init_connection(struct twe_softc *sc, int mode);
   61 static int      twe_wait_request(struct twe_request *tr);
   62 static int      twe_immediate_request(struct twe_request *tr, int usetmp);
   63 static void     twe_completeio(struct twe_request *tr);
   64 static void     twe_reset(struct twe_softc *sc);
   65 static int      twe_add_unit(struct twe_softc *sc, int unit);
   66 static int      twe_del_unit(struct twe_softc *sc, int unit);
   67 
   68 /*
   69  * Command I/O to controller.
   70  */
   71 static void     twe_done(struct twe_softc *sc);
   72 static void     twe_complete(struct twe_softc *sc);
   73 static int      twe_wait_status(struct twe_softc *sc, u_int32_t status, int timeout);
   74 static int      twe_drain_response_queue(struct twe_softc *sc);
   75 static int      twe_check_bits(struct twe_softc *sc, u_int32_t status_reg);
   76 static int      twe_soft_reset(struct twe_softc *sc);
   77 
   78 /*
   79  * Interrupt handling.
   80  */
   81 static void     twe_host_intr(struct twe_softc *sc);
   82 static void     twe_attention_intr(struct twe_softc *sc);
   83 static void     twe_command_intr(struct twe_softc *sc);
   84 
   85 /*
   86  * Asynchronous event handling.
   87  */
   88 static int      twe_fetch_aen(struct twe_softc *sc);
   89 static void     twe_handle_aen(struct twe_request *tr);
   90 static void     twe_enqueue_aen(struct twe_softc *sc, u_int16_t aen);
   91 static u_int16_t        twe_dequeue_aen(struct twe_softc *sc);
   92 static int      twe_drain_aen_queue(struct twe_softc *sc);
   93 static int      twe_find_aen(struct twe_softc *sc, u_int16_t aen);
   94 
   95 /*
   96  * Command buffer management.
   97  */
   98 static int      twe_get_request(struct twe_softc *sc, struct twe_request **tr);
   99 static void     twe_release_request(struct twe_request *tr);
  100 
  101 /*
  102  * Debugging.
  103  */
  104 static char     *twe_format_aen(struct twe_softc *sc, u_int16_t aen);
  105 static int      twe_report_request(struct twe_request *tr);
  106 static void     twe_panic(struct twe_softc *sc, char *reason);
  107 
  108 /********************************************************************************
  109  ********************************************************************************
  110                                                                 Public Interfaces
  111  ********************************************************************************
  112  ********************************************************************************/
  113 
  114 /********************************************************************************
  115  * Initialise the controller, set up driver data structures.
  116  */
  117 int
  118 twe_setup(struct twe_softc *sc)
  119 {
  120     struct twe_request  *tr;
  121     TWE_Command         *cmd;
  122     u_int32_t           status_reg;
  123     int                 i;
  124 
  125     debug_called(4);
  126 
  127     /*
  128      * Initialise request queues.
  129      */
  130     twe_initq_free(sc);
  131     twe_initq_bio(sc);
  132     twe_initq_ready(sc);
  133     twe_initq_busy(sc);
  134     twe_initq_complete(sc);
  135     sc->twe_wait_aen = -1;
  136 
  137     /*
  138      * Allocate request structures up front.
  139      */
  140     for (i = 0; i < TWE_Q_LENGTH; i++) {
  141         if ((tr = twe_allocate_request(sc, i)) == NULL)
  142             return(ENOMEM);
  143         /*
  144          * Set global defaults that won't change.
  145          */
  146         cmd = TWE_FIND_COMMAND(tr);
  147         cmd->generic.host_id = sc->twe_host_id;         /* controller-assigned host ID */
  148         cmd->generic.request_id = i;                    /* our index number */
  149         sc->twe_lookup[i] = tr;
  150 
  151         /*
  152          * Put command onto the freelist.
  153          */
  154         twe_release_request(tr);
  155     }
  156 
  157     /*
  158      * Check status register for errors, clear them.
  159      */
  160     status_reg = TWE_STATUS(sc);
  161     twe_check_bits(sc, status_reg);
  162 
  163     /*
  164      * Wait for the controller to come ready.
  165      */
  166     if (twe_wait_status(sc, TWE_STATUS_MICROCONTROLLER_READY, 60)) {
  167         twe_printf(sc, "microcontroller not ready\n");
  168         return(ENXIO);
  169     }
  170 
  171     /*
  172      * Disable interrupts from the card.
  173      */
  174     twe_disable_interrupts(sc);
  175 
  176     /*
  177      * Soft reset the controller, look for the AEN acknowledging the reset,
  178      * check for errors, drain the response queue.
  179      */
  180     for (i = 0; i < TWE_MAX_RESET_TRIES; i++) {
  181 
  182         if (i > 0)
  183             twe_printf(sc, "reset %d failed, trying again\n", i);
  184         
  185         if (!twe_soft_reset(sc))
  186             break;                      /* reset process complete */
  187     }
  188     /* did we give up? */
  189     if (i >= TWE_MAX_RESET_TRIES) {
  190         twe_printf(sc, "can't initialise controller, giving up\n");
  191         return(ENXIO);
  192     }
  193 
  194     return(0);
  195 }
  196 
  197 static int
  198 twe_add_unit(struct twe_softc *sc, int unit)
  199 {
  200     struct twe_drive            *dr;
  201     int                         table, error = 0;
  202     u_int16_t                   dsize;
  203     TWE_Param                   *drives = NULL, *param = NULL;
  204     TWE_Unit_Descriptor         *ud;
  205 
  206     if (unit < 0 || unit > TWE_MAX_UNITS)
  207         return (EINVAL);
  208 
  209     /*
  210      * The controller is in a safe state, so try to find drives attached to it.
  211      */
  212     if ((drives = twe_get_param(sc, TWE_PARAM_UNITSUMMARY, TWE_PARAM_UNITSUMMARY_Status,
  213                                 TWE_MAX_UNITS, NULL)) == NULL) {
  214         twe_printf(sc, "can't detect attached units\n");
  215         return (EIO);
  216     }
  217 
  218     dr = &sc->twe_drive[unit];
  219     /* check that the drive is online */
  220     if (!(drives->data[unit] & TWE_PARAM_UNITSTATUS_Online)) {
  221         error = ENXIO;
  222         goto out;
  223     }
  224 
  225     table = TWE_PARAM_UNITINFO + unit;
  226 
  227     if (twe_get_param_4(sc, table, TWE_PARAM_UNITINFO_Capacity, &dr->td_size)) {
  228         twe_printf(sc, "error fetching capacity for unit %d\n", unit);
  229         error = EIO;
  230         goto out;
  231     }
  232     if (twe_get_param_1(sc, table, TWE_PARAM_UNITINFO_Status, &dr->td_state)) {
  233         twe_printf(sc, "error fetching state for unit %d\n", unit);
  234         error = EIO;
  235         goto out;
  236     }
  237     if (twe_get_param_2(sc, table, TWE_PARAM_UNITINFO_DescriptorSize, &dsize)) {
  238         twe_printf(sc, "error fetching descriptor size for unit %d\n", unit);
  239         error = EIO;
  240         goto out;
  241     }
  242     if ((param = twe_get_param(sc, table, TWE_PARAM_UNITINFO_Descriptor, dsize - 3, NULL)) == NULL) {
  243         twe_printf(sc, "error fetching descriptor for unit %d\n", unit);
  244         error = EIO;
  245         goto out;
  246     }
  247     ud = (TWE_Unit_Descriptor *)param->data;
  248     dr->td_type = ud->configuration;
  249 
  250     /* build synthetic geometry as per controller internal rules */
  251     if (dr->td_size > 0x200000) {
  252         dr->td_heads = 255;
  253         dr->td_sectors = 63;
  254     } else {
  255         dr->td_heads = 64;
  256         dr->td_sectors = 32;
  257     }
  258     dr->td_cylinders = dr->td_size / (dr->td_heads * dr->td_sectors);
  259     dr->td_twe_unit = unit;
  260 
  261     error = twe_attach_drive(sc, dr);
  262 
  263 out:
  264     if (param != NULL)
  265         free(param, M_DEVBUF);
  266     if (drives != NULL)
  267         free(drives, M_DEVBUF);
  268     return (error);
  269 }
  270 
  271 static int
  272 twe_del_unit(struct twe_softc *sc, int unit)
  273 {
  274     int error;
  275 
  276     if (unit < 0 || unit >= TWE_MAX_UNITS)
  277         return (ENXIO);
  278 
  279     if (sc->twe_drive[unit].td_disk == NULL)
  280         return (ENXIO);
  281 
  282     error = twe_detach_drive(sc, unit);
  283     return (error);
  284 }
  285 
  286 /********************************************************************************
  287  * Locate disk devices and attach children to them.
  288  */
  289 void
  290 twe_init(struct twe_softc *sc)
  291 {
  292     int                 i;
  293 
  294     /*
  295      * Scan for drives
  296      */
  297     for (i = 0; i < TWE_MAX_UNITS; i++)
  298         twe_add_unit(sc, i);
  299 
  300     /*
  301      * Initialise connection with controller.
  302      */
  303     twe_init_connection(sc, TWE_INIT_MESSAGE_CREDITS);
  304 
  305 #ifdef TWE_SHUTDOWN_NOTIFICATION
  306     /*
  307      * Tell the controller we support shutdown notification.
  308      */
  309     twe_set_param_1(sc, TWE_PARAM_FEATURES, TWE_PARAM_FEATURES_DriverShutdown, 1);
  310 #endif
  311 
  312     /* 
  313      * Mark controller up and ready to run.
  314      */
  315     sc->twe_state &= ~TWE_STATE_SHUTDOWN;
  316 
  317     /*
  318      * Finally enable interrupts.
  319      */
  320     twe_enable_interrupts(sc);
  321 }
  322 
  323 /********************************************************************************
  324  * Stop the controller
  325  */
  326 void
  327 twe_deinit(struct twe_softc *sc)
  328 {
  329     /*
  330      * Mark the controller as shutting down, and disable any further interrupts.
  331      */
  332     sc->twe_state |= TWE_STATE_SHUTDOWN;
  333     twe_disable_interrupts(sc);
  334 
  335 #ifdef TWE_SHUTDOWN_NOTIFICATION
  336     /*
  337      * Disconnect from the controller
  338      */
  339     twe_init_connection(sc, TWE_SHUTDOWN_MESSAGE_CREDITS);
  340 #endif
  341 }
  342 
  343 /*******************************************************************************
  344  * Take an interrupt, or be poked by other code to look for interrupt-worthy
  345  * status.
  346  */
  347 void
  348 twe_intr(struct twe_softc *sc)
  349 {
  350     u_int32_t           status_reg;
  351 
  352     debug_called(4);
  353 
  354     /*
  355      * Collect current interrupt status.
  356      */
  357     status_reg = TWE_STATUS(sc);
  358     twe_check_bits(sc, status_reg);
  359 
  360     /*
  361      * Dispatch based on interrupt status
  362      */
  363     if (status_reg & TWE_STATUS_HOST_INTERRUPT)
  364         twe_host_intr(sc);
  365     if (status_reg & TWE_STATUS_ATTENTION_INTERRUPT)
  366         twe_attention_intr(sc);
  367     if (status_reg & TWE_STATUS_COMMAND_INTERRUPT)
  368         twe_command_intr(sc);
  369     if (status_reg & TWE_STATUS_RESPONSE_INTERRUPT)
  370         twe_done(sc);
  371 };
  372 
  373 /********************************************************************************
  374  * Pull as much work off the softc's work queue as possible and give it to the
  375  * controller.
  376  */
  377 void
  378 twe_startio(struct twe_softc *sc)
  379 {
  380     struct twe_request  *tr;
  381     TWE_Command         *cmd;
  382     twe_bio             *bp;
  383     int                 error;
  384 
  385     debug_called(4);
  386 
  387     if (sc->twe_state & (TWE_STATE_CTLR_BUSY | TWE_STATE_FRZN))
  388         return;
  389 
  390     /* spin until something prevents us from doing any work */
  391     for (;;) {
  392 
  393         /* try to get a command that's already ready to go */
  394         tr = twe_dequeue_ready(sc);
  395 
  396         /* build a command from an outstanding bio */
  397         if (tr == NULL) {
  398             
  399             /* get a command to handle the bio with */
  400             if (twe_get_request(sc, &tr))
  401                 break;
  402 
  403             /* see if there's work to be done */
  404             if ((bp = twe_dequeue_bio(sc)) == NULL) {
  405                 twe_release_request(tr);
  406                 break;
  407             }
  408 
  409             /* connect the bio to the command */
  410             tr->tr_complete = twe_completeio;
  411             tr->tr_private = bp;
  412             tr->tr_data = TWE_BIO_DATA(bp);
  413             tr->tr_length = TWE_BIO_LENGTH(bp);
  414             cmd = TWE_FIND_COMMAND(tr);
  415             if (TWE_BIO_IS_READ(bp)) {
  416                 tr->tr_flags |= TWE_CMD_DATAIN;
  417                 cmd->io.opcode = TWE_OP_READ;
  418             } else {
  419                 tr->tr_flags |= TWE_CMD_DATAOUT;
  420                 cmd->io.opcode = TWE_OP_WRITE;
  421             }
  422         
  423             /* build a suitable I/O command (assumes 512-byte rounded transfers) */
  424             cmd->io.size = 3;
  425             cmd->io.unit = TWE_BIO_UNIT(bp);
  426             cmd->io.block_count = (tr->tr_length + TWE_BLOCK_SIZE - 1) / TWE_BLOCK_SIZE;
  427             cmd->io.lba = TWE_BIO_LBA(bp);
  428         }
  429         
  430         /* did we find something to do? */
  431         if (tr == NULL)
  432             break;
  433         
  434         /* try to map and submit the command to controller */
  435         error = twe_map_request(tr);
  436 
  437         if (error != 0) {
  438             if (error == EBUSY)
  439                 break;
  440             tr->tr_status = TWE_CMD_ERROR;
  441             if (tr->tr_private != NULL) {
  442                 bp = (twe_bio *)(tr->tr_private);
  443                 TWE_BIO_SET_ERROR(bp, error);
  444                 tr->tr_private = NULL;
  445                 twed_intr(bp);
  446                 twe_release_request(tr);
  447             } else if (tr->tr_flags & TWE_CMD_SLEEPER)
  448                 wakeup_one(tr); /* wakeup the sleeping owner */
  449         }
  450     }
  451 }
  452 
  453 /********************************************************************************
  454  * Write blocks from memory to disk, for system crash dumps.
  455  */
  456 int
  457 twe_dump_blocks(struct twe_softc *sc, int unit, u_int32_t lba, void *data, int nblks)
  458 {
  459     struct twe_request  *tr;
  460     TWE_Command         *cmd;
  461     int                 error;
  462 
  463     if (twe_get_request(sc, &tr))
  464         return(ENOMEM);
  465 
  466     tr->tr_data = data;
  467     tr->tr_status = TWE_CMD_SETUP;
  468     tr->tr_length = nblks * TWE_BLOCK_SIZE;
  469     tr->tr_flags = TWE_CMD_DATAOUT;
  470 
  471     cmd = TWE_FIND_COMMAND(tr);
  472     cmd->io.opcode = TWE_OP_WRITE;
  473     cmd->io.size = 3;
  474     cmd->io.unit = unit;
  475     cmd->io.block_count = nblks;
  476     cmd->io.lba = lba;
  477 
  478     error = twe_immediate_request(tr, 0);
  479     if (error == 0)
  480         if (twe_report_request(tr))
  481             error = EIO;
  482     twe_release_request(tr);
  483     return(error);
  484 }
  485 
  486 /********************************************************************************
  487  * Handle controller-specific control operations.
  488  */
  489 int
  490 twe_ioctl(struct twe_softc *sc, int ioctlcmd, void *addr)
  491 {
  492     struct twe_usercommand      *tu = (struct twe_usercommand *)addr;
  493     struct twe_paramcommand     *tp = (struct twe_paramcommand *)addr;
  494     struct twe_drivecommand     *td = (struct twe_drivecommand *)addr;
  495     union twe_statrequest       *ts = (union twe_statrequest *)addr;
  496     TWE_Param                   *param;
  497     TWE_Command                 *cmd;
  498     void                        *data;
  499     u_int16_t                   *aen_code = (u_int16_t *)addr;
  500     struct twe_request          *tr;
  501     u_int8_t                    srid;
  502     int                         s, error;
  503 
  504     error = 0;
  505     switch(ioctlcmd) {
  506         /* handle a command from userspace */
  507     case TWEIO_COMMAND:
  508         /* get a request */
  509         while (twe_get_request(sc, &tr))
  510             tsleep(sc, PPAUSE, "twioctl", hz);
  511 
  512         /*
  513          * Save the command's request ID, copy the user-supplied command in,
  514          * restore the request ID.
  515          */
  516         cmd = TWE_FIND_COMMAND(tr);
  517         srid = cmd->generic.request_id;
  518         bcopy(&tu->tu_command, cmd, sizeof(TWE_Command));
  519         cmd->generic.request_id = srid;
  520 
  521         /*
  522          * if there's a data buffer, allocate and copy it in.
  523          * Must be in multipled of 512 bytes.
  524          */
  525         tr->tr_length = (tu->tu_size + 511) & ~511;
  526         if (tr->tr_length > 0) {
  527             if ((tr->tr_data = malloc(tr->tr_length, M_DEVBUF, M_WAITOK)) == NULL) {
  528                 error = ENOMEM;
  529                 goto cmd_done;
  530             }
  531             if ((error = copyin(tu->tu_data, tr->tr_data, tu->tu_size)) != 0)
  532                 goto cmd_done;
  533             tr->tr_flags |= TWE_CMD_DATAIN | TWE_CMD_DATAOUT;
  534         }
  535 
  536         /* run the command */
  537         error = twe_wait_request(tr);
  538         if (error)
  539             goto cmd_done;
  540 
  541         /* copy the command out again */
  542         bcopy(cmd, &tu->tu_command, sizeof(TWE_Command));
  543         
  544         /* if there was a data buffer, copy it out */
  545         if (tr->tr_length > 0)
  546             error = copyout(tr->tr_data, tu->tu_data, tu->tu_size);
  547 
  548     cmd_done:
  549         /* free resources */
  550         if (tr->tr_data != NULL)
  551             free(tr->tr_data, M_DEVBUF);
  552         if (tr != NULL)
  553             twe_release_request(tr);
  554 
  555         break;
  556 
  557         /* fetch statistics counter */
  558     case TWEIO_STATS:
  559         switch (ts->ts_item) {
  560 #ifdef TWE_PERFORMANCE_MONITOR
  561         case TWEQ_FREE:
  562         case TWEQ_BIO:
  563         case TWEQ_READY:
  564         case TWEQ_BUSY:
  565         case TWEQ_COMPLETE:
  566             bcopy(&sc->twe_qstat[ts->ts_item], &ts->ts_qstat, sizeof(struct twe_qstat));
  567             break;
  568 #endif
  569         default:
  570             error = ENOENT;
  571             break;
  572         }
  573         break;
  574 
  575         /* poll for an AEN */
  576     case TWEIO_AEN_POLL:
  577         *aen_code = twe_dequeue_aen(sc);
  578         break;
  579 
  580         /* wait for another AEN to show up */
  581     case TWEIO_AEN_WAIT:
  582         s = splbio();
  583         while ((*aen_code = twe_dequeue_aen(sc)) == TWE_AEN_QUEUE_EMPTY) {
  584             error = tsleep(&sc->twe_aen_queue, PRIBIO | PCATCH, "tweaen", 0);
  585             if (error == EINTR)
  586                 break;
  587         }
  588         splx(s);
  589         break;
  590 
  591     case TWEIO_GET_PARAM:
  592         if ((param = twe_get_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, NULL)) == NULL) {
  593             twe_printf(sc, "TWEIO_GET_PARAM failed for 0x%x/0x%x/%d\n", 
  594                        tp->tp_table_id, tp->tp_param_id, tp->tp_size);
  595             error = EINVAL;
  596         } else {
  597             if (param->parameter_size_bytes > tp->tp_size) {
  598                 twe_printf(sc, "TWEIO_GET_PARAM parameter too large (%d > %d)\n",       
  599                            param->parameter_size_bytes, tp->tp_size);
  600                 error = EFAULT;
  601             } else {
  602                 error = copyout(param->data, tp->tp_data, param->parameter_size_bytes);
  603             }
  604             free(param, M_DEVBUF);
  605         }
  606         break;
  607 
  608     case TWEIO_SET_PARAM:
  609         if ((data = malloc(tp->tp_size, M_DEVBUF, M_WAITOK)) == NULL) {
  610             error = ENOMEM;
  611         } else {
  612             error = copyin(tp->tp_data, data, tp->tp_size);
  613             if (error == 0)
  614                 error = twe_set_param(sc, tp->tp_table_id, tp->tp_param_id, tp->tp_size, data);
  615             free(data, M_DEVBUF);
  616         }
  617         break;
  618 
  619     case TWEIO_RESET:
  620         twe_reset(sc);
  621         break;
  622 
  623     case TWEIO_ADD_UNIT:
  624         error = twe_add_unit(sc, td->td_unit);
  625         break;
  626 
  627     case TWEIO_DEL_UNIT:
  628         error = twe_del_unit(sc, td->td_unit);
  629         break;
  630 
  631         /* XXX implement ATA PASSTHROUGH */
  632 
  633         /* nothing we understand */
  634     default:    
  635         error = ENOTTY;
  636     }
  637 
  638     return(error);
  639 }
  640 
  641 /********************************************************************************
  642  * Enable the useful interrupts from the controller.
  643  */
  644 void
  645 twe_enable_interrupts(struct twe_softc *sc)
  646 {
  647     sc->twe_state |= TWE_STATE_INTEN;
  648     TWE_CONTROL(sc, 
  649                TWE_CONTROL_CLEAR_ATTENTION_INTERRUPT |
  650                TWE_CONTROL_UNMASK_RESPONSE_INTERRUPT |
  651                TWE_CONTROL_ENABLE_INTERRUPTS);
  652 }
  653 
  654 /********************************************************************************
  655  * Disable interrupts from the controller.
  656  */
  657 void
  658 twe_disable_interrupts(struct twe_softc *sc)
  659 {
  660     TWE_CONTROL(sc, TWE_CONTROL_DISABLE_INTERRUPTS);
  661     sc->twe_state &= ~TWE_STATE_INTEN;
  662 }
  663 
  664 /********************************************************************************
  665  ********************************************************************************
  666                                                                Command Submission
  667  ********************************************************************************
  668  ********************************************************************************/
  669 
  670 /********************************************************************************
  671  * Read integer parameter table entries.
  672  */
  673 static int
  674 twe_get_param_1(struct twe_softc *sc, int table_id, int param_id, u_int8_t *result)
  675 {
  676     TWE_Param   *param;
  677 
  678     if ((param = twe_get_param(sc, table_id, param_id, 1, NULL)) == NULL)
  679         return(ENOENT);
  680     *result = *(u_int8_t *)param->data;
  681     free(param, M_DEVBUF);
  682     return(0);
  683 }
  684 
  685 static int
  686 twe_get_param_2(struct twe_softc *sc, int table_id, int param_id, u_int16_t *result)
  687 {
  688     TWE_Param   *param;
  689 
  690     if ((param = twe_get_param(sc, table_id, param_id, 2, NULL)) == NULL)
  691         return(ENOENT);
  692     *result = *(u_int16_t *)param->data;
  693     free(param, M_DEVBUF);
  694     return(0);
  695 }
  696 
  697 static int
  698 twe_get_param_4(struct twe_softc *sc, int table_id, int param_id, u_int32_t *result)
  699 {
  700     TWE_Param   *param;
  701 
  702     if ((param = twe_get_param(sc, table_id, param_id, 4, NULL)) == NULL)
  703         return(ENOENT);
  704     *result = *(u_int32_t *)param->data;
  705     free(param, M_DEVBUF);
  706     return(0);
  707 }
  708 
  709 /********************************************************************************
  710  * Perform a TWE_OP_GET_PARAM command.  If a callback function is provided, it
  711  * will be called with the command when it's completed.  If no callback is 
  712  * provided, we will wait for the command to complete and then return just the data.
  713  * The caller is responsible for freeing the data when done with it.
  714  */
  715 static void *
  716 twe_get_param(struct twe_softc *sc, int table_id, int param_id, size_t param_size, 
  717               void (* func)(struct twe_request *tr))
  718 {
  719     struct twe_request  *tr;
  720     TWE_Command         *cmd;
  721     TWE_Param           *param;
  722     int                 error;
  723 
  724     debug_called(4);
  725 
  726     tr = NULL;
  727     param = NULL;
  728 
  729     /* get a command */
  730     if (twe_get_request(sc, &tr))
  731         goto err;
  732 
  733     /* get a buffer */
  734     if ((param = (TWE_Param *)malloc(TWE_SECTOR_SIZE, M_DEVBUF, M_NOWAIT)) == NULL)
  735         goto err;
  736     tr->tr_data = param;
  737     tr->tr_length = TWE_SECTOR_SIZE;
  738     tr->tr_flags = TWE_CMD_DATAIN | TWE_CMD_DATAOUT;
  739 
  740     /* build the command for the controller */
  741     cmd = TWE_FIND_COMMAND(tr);
  742     cmd->param.opcode = TWE_OP_GET_PARAM;
  743     cmd->param.size = 2;
  744     cmd->param.unit = 0;
  745     cmd->param.param_count = 1;
  746 
  747     /* fill in the outbound parameter data */
  748     param->table_id = table_id;
  749     param->parameter_id = param_id;
  750     param->parameter_size_bytes = param_size;
  751 
  752     /* submit the command and either wait or let the callback handle it */
  753     if (func == NULL) {
  754         /* XXX could use twe_wait_request here if interrupts were enabled? */
  755         error = twe_immediate_request(tr, 1 /* usetmp */);
  756         if (error == 0) {
  757             if (twe_report_request(tr))
  758                 goto err;
  759         } else {
  760             goto err;
  761         }
  762         twe_release_request(tr);
  763         return(param);
  764     } else {
  765         tr->tr_complete = func;
  766         error = twe_map_request(tr);
  767         if ((error == 0) || (error == EBUSY))
  768             return(func);
  769     }
  770 
  771     /* something failed */
  772 err:
  773     debug(1, "failed");
  774     if (tr != NULL)
  775         twe_release_request(tr);
  776     if (param != NULL)
  777         free(param, M_DEVBUF);
  778     return(NULL);
  779 }
  780 
  781 /********************************************************************************
  782  * Set integer parameter table entries.
  783  */
  784 #ifdef TWE_SHUTDOWN_NOTIFICATION
  785 static int
  786 twe_set_param_1(struct twe_softc *sc, int table_id, int param_id, u_int8_t value)
  787 {
  788     return(twe_set_param(sc, table_id, param_id, sizeof(value), &value));
  789 }
  790 #endif
  791 
  792 #if 0
  793 static int
  794 twe_set_param_2(struct twe_softc *sc, int table_id, int param_id, u_int16_t value)
  795 {
  796     return(twe_set_param(sc, table_id, param_id, sizeof(value), &value));
  797 }
  798 
  799 static int
  800 twe_set_param_4(struct twe_softc *sc, int table_id, int param_id, u_int32_t value)
  801 {
  802     return(twe_set_param(sc, table_id, param_id, sizeof(value), &value));
  803 }
  804 #endif
  805 
  806 /********************************************************************************
  807  * Perform a TWE_OP_SET_PARAM command, returns nonzero on error.
  808  */
  809 static int
  810 twe_set_param(struct twe_softc *sc, int table_id, int param_id, int param_size, void *data)
  811 {
  812     struct twe_request  *tr;
  813     TWE_Command         *cmd;
  814     TWE_Param           *param;
  815     int                 error;
  816 
  817     debug_called(4);
  818 
  819     tr = NULL;
  820     param = NULL;
  821     error = ENOMEM;
  822 
  823     /* get a command */
  824     if (twe_get_request(sc, &tr))
  825         goto out;
  826 
  827     /* get a buffer */
  828     if ((param = (TWE_Param *)malloc(TWE_SECTOR_SIZE, M_DEVBUF, M_NOWAIT)) == NULL)
  829         goto out;
  830     tr->tr_data = param;
  831     tr->tr_length = TWE_SECTOR_SIZE;
  832     tr->tr_flags = TWE_CMD_DATAIN | TWE_CMD_DATAOUT;
  833 
  834     /* build the command for the controller */
  835     cmd = TWE_FIND_COMMAND(tr);
  836     cmd->param.opcode = TWE_OP_SET_PARAM;
  837     cmd->param.size = 2;
  838     cmd->param.unit = 0;
  839     cmd->param.param_count = 1;
  840 
  841     /* fill in the outbound parameter data */
  842     param->table_id = table_id;
  843     param->parameter_id = param_id;
  844     param->parameter_size_bytes = param_size;
  845     bcopy(data, param->data, param_size);
  846 
  847     /* XXX could use twe_wait_request here if interrupts were enabled? */
  848     error = twe_immediate_request(tr, 1 /* usetmp */);
  849     if (error == 0) {
  850         if (twe_report_request(tr))
  851             error = EIO;
  852     }
  853 
  854 out:
  855     if (tr != NULL)
  856         twe_release_request(tr);
  857     if (param != NULL)
  858         free(param, M_DEVBUF);
  859     return(error);
  860 }
  861 
  862 /********************************************************************************
  863  * Perform a TWE_OP_INIT_CONNECTION command, returns nonzero on error.
  864  *
  865  * Typically called with interrupts disabled.
  866  */
  867 static int
  868 twe_init_connection(struct twe_softc *sc, int mode)
  869 {
  870     struct twe_request  *tr;
  871     TWE_Command         *cmd;
  872     int                 error;
  873     
  874     debug_called(4);
  875 
  876     /* get a command */
  877     if (twe_get_request(sc, &tr))
  878         return(0);
  879 
  880     /* build the command */
  881     cmd = TWE_FIND_COMMAND(tr);
  882     cmd->initconnection.opcode = TWE_OP_INIT_CONNECTION;
  883     cmd->initconnection.size = 3;
  884     cmd->initconnection.host_id = 0;
  885     cmd->initconnection.message_credits = mode;
  886     cmd->initconnection.response_queue_pointer = 0;
  887 
  888     /* submit the command */
  889     error = twe_immediate_request(tr, 0 /* usetmp */);
  890     twe_release_request(tr);
  891 
  892     if (mode == TWE_INIT_MESSAGE_CREDITS)
  893         sc->twe_host_id = cmd->initconnection.host_id;
  894     return(error);
  895 }
  896 
  897 /********************************************************************************
  898  * Start the command (tr) and sleep waiting for it to complete.
  899  *
  900  * Successfully completed commands are dequeued.
  901  */
  902 static int
  903 twe_wait_request(struct twe_request *tr)
  904 {
  905     int         s;
  906 
  907     debug_called(4);
  908 
  909     tr->tr_flags |= TWE_CMD_SLEEPER;
  910     tr->tr_status = TWE_CMD_BUSY;
  911     twe_enqueue_ready(tr);
  912     twe_startio(tr->tr_sc);
  913     s = splbio();
  914     while (tr->tr_status == TWE_CMD_BUSY)
  915         tsleep(tr, PRIBIO, "twewait", 0);
  916     splx(s);
  917     
  918     return(tr->tr_status != TWE_CMD_COMPLETE);
  919 }
  920 
  921 /********************************************************************************
  922  * Start the command (tr) and busy-wait for it to complete.
  923  * This should only be used when interrupts are actually disabled (although it
  924  * will work if they are not).
  925  */
  926 static int
  927 twe_immediate_request(struct twe_request *tr, int usetmp)
  928 {
  929     struct twe_softc *sc;
  930     int         error;
  931     int         count = 0;
  932 
  933     debug_called(4);
  934 
  935     sc = tr->tr_sc;
  936 
  937     if (usetmp && (tr->tr_data != NULL)) {
  938         tr->tr_flags |= TWE_CMD_IMMEDIATE;
  939         if (tr->tr_length > MAXBSIZE)
  940             return (EINVAL);
  941         bcopy(tr->tr_data, sc->twe_immediate, tr->tr_length);
  942     }
  943     tr->tr_status = TWE_CMD_BUSY;
  944     if ((error = twe_map_request(tr)) != 0)
  945         if (error != EBUSY)
  946             return(error);
  947 
  948     /* Wait up to 5 seconds for the command to complete */
  949     while ((count++ < 5000) && (tr->tr_status == TWE_CMD_BUSY)){
  950         DELAY(1000);
  951         twe_done(sc);
  952     }
  953     if (usetmp && (tr->tr_data != NULL))
  954         bcopy(sc->twe_immediate, tr->tr_data, tr->tr_length);
  955 
  956     return(tr->tr_status != TWE_CMD_COMPLETE);
  957 }
  958 
  959 /********************************************************************************
  960  * Handle completion of an I/O command.
  961  */
  962 static void
  963 twe_completeio(struct twe_request *tr)
  964 {
  965     TWE_Command         *cmd = TWE_FIND_COMMAND(tr);
  966     struct twe_softc    *sc = tr->tr_sc;
  967     twe_bio             *bp = (twe_bio *)tr->tr_private;
  968 
  969     debug_called(4);
  970 
  971     if (tr->tr_status == TWE_CMD_COMPLETE) {
  972 
  973         if (cmd->generic.status)
  974             if (twe_report_request(tr))
  975                 TWE_BIO_SET_ERROR(bp, EIO);
  976 
  977     } else {
  978         twe_panic(sc, "twe_completeio on incomplete command");
  979     }
  980     tr->tr_private = NULL;
  981     twed_intr(bp);
  982     twe_release_request(tr);
  983 }
  984 
  985 /********************************************************************************
  986  * Reset the controller and pull all the active commands back onto the ready
  987  * queue.  Used to restart a controller that's exhibiting bad behaviour.
  988  */
  989 static void
  990 twe_reset(struct twe_softc *sc)
  991 {
  992     struct twe_request  *tr;
  993     int                 i, s;
  994 
  995     /*
  996      * Sleep for a short period to allow AENs to be signalled.
  997      */
  998     tsleep(sc, PRIBIO, "twereset", hz);
  999 
 1000     /*
 1001      * Disable interrupts from the controller, and mask any accidental entry
 1002      * into our interrupt handler.
 1003      */
 1004     twe_printf(sc, "controller reset in progress...\n");
 1005     twe_disable_interrupts(sc);
 1006     s = splbio();
 1007 
 1008     /*
 1009      * Try to soft-reset the controller.
 1010      */
 1011     for (i = 0; i < TWE_MAX_RESET_TRIES; i++) {
 1012 
 1013         if (i > 0)
 1014             twe_printf(sc, "reset %d failed, trying again\n", i);
 1015         
 1016         if (!twe_soft_reset(sc))
 1017             break;                      /* reset process complete */
 1018     }
 1019     /* did we give up? */
 1020     if (i >= TWE_MAX_RESET_TRIES) {
 1021         twe_printf(sc, "can't reset controller, giving up\n");
 1022         goto out;
 1023     }
 1024 
 1025     /*
 1026      * Move all of the commands that were busy back to the ready queue.
 1027      */
 1028     i = 0;
 1029     while ((tr = twe_dequeue_busy(sc)) != NULL) {
 1030         twe_enqueue_ready(tr);
 1031         i++;
 1032     }
 1033 
 1034     /*
 1035      * Kick the controller to start things going again, then re-enable interrupts.
 1036      */
 1037     twe_startio(sc);
 1038     twe_enable_interrupts(sc);
 1039     twe_printf(sc, "controller reset done, %d commands restarted\n", i);
 1040 
 1041 out:
 1042     splx(s);
 1043     twe_enable_interrupts(sc);
 1044 }
 1045 
 1046 /********************************************************************************
 1047  ********************************************************************************
 1048                                                         Command I/O to Controller
 1049  ********************************************************************************
 1050  ********************************************************************************/
 1051 
 1052 /********************************************************************************
 1053  * Try to deliver (tr) to the controller.
 1054  *
 1055  * Can be called at any interrupt level, with or without interrupts enabled.
 1056  */
 1057 int
 1058 twe_start(struct twe_request *tr)
 1059 {
 1060     struct twe_softc    *sc = tr->tr_sc;
 1061     TWE_Command         *cmd;
 1062     int                 i, s, done;
 1063     u_int32_t           status_reg;
 1064 
 1065     debug_called(4);
 1066 
 1067     /* mark the command as currently being processed */
 1068     tr->tr_status = TWE_CMD_BUSY;
 1069     cmd = TWE_FIND_COMMAND(tr);
 1070 
 1071     /* 
 1072      * Spin briefly waiting for the controller to come ready 
 1073      *
 1074      * XXX it might be more efficient to return EBUSY immediately
 1075      *     and let the command be rescheduled.
 1076      */
 1077     for (i = 100000, done = 0; (i > 0) && !done; i--) {
 1078         s = splbio();
 1079         
 1080         /* check to see if we can post a command */
 1081         status_reg = TWE_STATUS(sc);
 1082         twe_check_bits(sc, status_reg);
 1083 
 1084         if (!(status_reg & TWE_STATUS_COMMAND_QUEUE_FULL)) {
 1085             twe_enqueue_busy(tr);
 1086 
 1087             TWE_COMMAND_QUEUE(sc, TWE_FIND_COMMANDPHYS(tr));
 1088             done = 1;
 1089             /* move command to work queue */
 1090 #ifdef TWE_DEBUG
 1091             if (tr->tr_complete != NULL) {
 1092                 debug(3, "queued request %d with callback %p", cmd->generic.request_id, tr->tr_complete);
 1093             } else if (tr->tr_flags & TWE_CMD_SLEEPER) {
 1094                 debug(3, "queued request %d with wait channel %p", cmd->generic.request_id, tr);
 1095             } else {
 1096                 debug(3, "queued request %d for polling caller", cmd->generic.request_id);
 1097             }
 1098 #endif
 1099         }
 1100         splx(s);        /* drop spl to allow completion interrupts */
 1101     }
 1102 
 1103     /* command is enqueued */
 1104     if (done)
 1105         return(0);
 1106 
 1107     /* 
 1108      * We couldn't get the controller to take the command; try submitting it again later.
 1109      * This should only happen if something is wrong with the controller, or if we have
 1110      * overestimated the number of commands it can accept.  (Should we actually reject
 1111      * the command at this point?)
 1112      */
 1113     return(EBUSY);
 1114 }
 1115 
 1116 /********************************************************************************
 1117  * Poll the controller (sc) for completed commands.
 1118  *
 1119  * Can be called at any interrupt level, with or without interrupts enabled.
 1120  */
 1121 static void
 1122 twe_done(struct twe_softc *sc)
 1123 {
 1124     TWE_Response_Queue  rq;
 1125     TWE_Command         *cmd;
 1126     struct twe_request  *tr;
 1127     int                 s, found;
 1128     u_int32_t           status_reg;
 1129     
 1130     debug_called(5);
 1131 
 1132     /* loop collecting completed commands */
 1133     found = 0;
 1134     s = splbio();
 1135     for (;;) {
 1136         status_reg = TWE_STATUS(sc);
 1137         twe_check_bits(sc, status_reg);         /* XXX should this fail? */
 1138 
 1139         if (!(status_reg & TWE_STATUS_RESPONSE_QUEUE_EMPTY)) {
 1140             found = 1;
 1141             rq = TWE_RESPONSE_QUEUE(sc);
 1142             tr = sc->twe_lookup[rq.u.response_id];      /* find command */
 1143             cmd = TWE_FIND_COMMAND(tr);
 1144             if (tr->tr_status != TWE_CMD_BUSY)
 1145                 twe_printf(sc, "completion event for nonbusy command\n");
 1146             tr->tr_status = TWE_CMD_COMPLETE;
 1147             debug(3, "completed request id %d with status %d", 
 1148                   cmd->generic.request_id, cmd->generic.status);
 1149             /* move to completed queue */
 1150             twe_remove_busy(tr);
 1151             twe_enqueue_complete(tr);
 1152             sc->twe_state &= ~TWE_STATE_CTLR_BUSY;
 1153         } else {
 1154             break;                                      /* no response ready */
 1155         }
 1156     }
 1157     splx(s);
 1158 
 1159     /* if we've completed any commands, try posting some more */
 1160     if (found)
 1161         twe_startio(sc);
 1162 
 1163     /* handle completion and timeouts */
 1164     twe_complete(sc);           /* XXX use deferred completion? */
 1165 }
 1166 
 1167 /********************************************************************************
 1168  * Perform post-completion processing for commands on (sc).
 1169  *
 1170  * This is split from twe_done as it can be safely deferred and run at a lower
 1171  * priority level should facilities for such a thing become available.
 1172  */
 1173 static void
 1174 twe_complete(struct twe_softc *sc) 
 1175 {
 1176     struct twe_request  *tr;
 1177     
 1178     debug_called(5);
 1179 
 1180     /*
 1181      * Pull commands off the completed list, dispatch them appropriately
 1182      */
 1183     while ((tr = twe_dequeue_complete(sc)) != NULL) {
 1184         /* unmap the command's data buffer */
 1185         twe_unmap_request(tr);
 1186 
 1187         /* dispatch to suit command originator */
 1188         if (tr->tr_complete != NULL) {          /* completion callback */
 1189             debug(2, "call completion handler %p", tr->tr_complete);
 1190             tr->tr_complete(tr);
 1191 
 1192         } else if (tr->tr_flags & TWE_CMD_SLEEPER) {    /* caller is asleep waiting */
 1193             debug(2, "wake up command owner on %p", tr);
 1194             wakeup_one(tr);
 1195 
 1196         } else {                                        /* caller is polling command */
 1197             debug(2, "command left for owner");
 1198         }
 1199     }   
 1200 }
 1201 
 1202 /********************************************************************************
 1203  * Wait for (status) to be set in the controller status register for up to
 1204  * (timeout) seconds.  Returns 0 if found, nonzero if we time out.
 1205  *
 1206  * Note: this busy-waits, rather than sleeping, since we may be called with
 1207  * eg. clock interrupts masked.
 1208  */
 1209 static int
 1210 twe_wait_status(struct twe_softc *sc, u_int32_t status, int timeout)
 1211 {
 1212     time_t      expiry;
 1213     u_int32_t   status_reg;
 1214 
 1215     debug_called(4);
 1216 
 1217     expiry = time_second + timeout;
 1218 
 1219     do {
 1220         status_reg = TWE_STATUS(sc);
 1221         if (status_reg & status)        /* got the required bit(s)? */
 1222             return(0);
 1223         DELAY(100000);
 1224     } while (time_second <= expiry);
 1225 
 1226     return(1);
 1227 }
 1228 
 1229 /********************************************************************************
 1230  * Drain the response queue, which may contain responses to commands we know
 1231  * nothing about.
 1232  */
 1233 static int
 1234 twe_drain_response_queue(struct twe_softc *sc)
 1235 {
 1236     TWE_Response_Queue  rq;
 1237     u_int32_t           status_reg;
 1238 
 1239     debug_called(4);
 1240 
 1241     for (;;) {                          /* XXX give up eventually? */
 1242         status_reg = TWE_STATUS(sc);
 1243         if (twe_check_bits(sc, status_reg))
 1244             return(1);
 1245         if (status_reg & TWE_STATUS_RESPONSE_QUEUE_EMPTY)
 1246             return(0);
 1247         rq = TWE_RESPONSE_QUEUE(sc);
 1248     }
 1249 }
 1250 
 1251 /********************************************************************************
 1252  * Soft-reset the controller
 1253  */
 1254 static int
 1255 twe_soft_reset(struct twe_softc *sc)
 1256 {
 1257     u_int32_t           status_reg;
 1258 
 1259     debug_called(2);
 1260 
 1261     TWE_SOFT_RESET(sc);
 1262 
 1263     if (twe_wait_status(sc, TWE_STATUS_ATTENTION_INTERRUPT, 30)) {
 1264         twe_printf(sc, "no attention interrupt\n");
 1265         return(1);
 1266     }
 1267     TWE_CONTROL(sc, TWE_CONTROL_CLEAR_ATTENTION_INTERRUPT);
 1268     if (twe_drain_aen_queue(sc)) {
 1269         twe_printf(sc, "can't drain AEN queue\n");
 1270         return(1);
 1271     }
 1272     if (twe_find_aen(sc, TWE_AEN_SOFT_RESET)) {
 1273         twe_printf(sc, "reset not reported\n");
 1274         return(1);
 1275     }
 1276     status_reg = TWE_STATUS(sc);
 1277     if (TWE_STATUS_ERRORS(status_reg) || twe_check_bits(sc, status_reg)) {
 1278         twe_printf(sc, "controller errors detected\n");
 1279         return(1);
 1280     }
 1281     if (twe_drain_response_queue(sc)) {
 1282         twe_printf(sc, "can't drain response queue\n");
 1283         return(1);
 1284     }
 1285     return(0);
 1286 }
 1287 
 1288 /********************************************************************************
 1289  ********************************************************************************
 1290                                                                Interrupt Handling
 1291  ********************************************************************************
 1292  ********************************************************************************/
 1293 
 1294 /********************************************************************************
 1295  * Host interrupt.
 1296  *
 1297  * XXX what does this mean?
 1298  */
 1299 static void
 1300 twe_host_intr(struct twe_softc *sc)
 1301 {
 1302     debug_called(4);
 1303 
 1304     twe_printf(sc, "host interrupt\n");
 1305     TWE_CONTROL(sc, TWE_CONTROL_CLEAR_HOST_INTERRUPT);
 1306 }
 1307 
 1308 /********************************************************************************
 1309  * Attention interrupt.
 1310  *
 1311  * Signalled when the controller has one or more AENs for us.
 1312  */
 1313 static void
 1314 twe_attention_intr(struct twe_softc *sc)
 1315 {
 1316     debug_called(4);
 1317 
 1318     /* instigate a poll for AENs */
 1319     if (twe_fetch_aen(sc)) {
 1320         twe_printf(sc, "error polling for signalled AEN\n");
 1321     } else {
 1322         TWE_CONTROL(sc, TWE_CONTROL_CLEAR_ATTENTION_INTERRUPT);
 1323     }
 1324 }
 1325 
 1326 /********************************************************************************
 1327  * Command interrupt.
 1328  *
 1329  * Signalled when the controller can handle more commands.
 1330  */
 1331 static void
 1332 twe_command_intr(struct twe_softc *sc)
 1333 {
 1334     debug_called(4);
 1335 
 1336     /*
 1337      * We don't use this, rather we try to submit commands when we receive
 1338      * them, and when other commands have completed.  Mask it so we don't get
 1339      * another one.
 1340      */
 1341     TWE_CONTROL(sc, TWE_CONTROL_MASK_COMMAND_INTERRUPT);
 1342 }
 1343 
 1344 /********************************************************************************
 1345  ********************************************************************************
 1346                                                       Asynchronous Event Handling
 1347  ********************************************************************************
 1348  ********************************************************************************/
 1349 
 1350 /********************************************************************************
 1351  * Request an AEN from the controller.
 1352  */
 1353 static int
 1354 twe_fetch_aen(struct twe_softc *sc)
 1355 {
 1356 
 1357     debug_called(4);
 1358 
 1359     if ((twe_get_param(sc, TWE_PARAM_AEN, TWE_PARAM_AEN_UnitCode, 2, twe_handle_aen)) == NULL)
 1360         return(EIO);
 1361     return(0);
 1362 }
 1363 
 1364 /********************************************************************************
 1365  * Handle an AEN returned by the controller.
 1366  */
 1367 static void
 1368 twe_handle_aen(struct twe_request *tr)
 1369 {
 1370     struct twe_softc    *sc = tr->tr_sc;
 1371     TWE_Param           *param;
 1372     u_int16_t           aen;
 1373 
 1374     debug_called(4);
 1375 
 1376     /* XXX check for command success somehow? */
 1377 
 1378     param = (TWE_Param *)tr->tr_data;
 1379     aen = *(u_int16_t *)(param->data);
 1380 
 1381     free(tr->tr_data, M_DEVBUF);
 1382     twe_release_request(tr);
 1383     twe_enqueue_aen(sc, aen);
 1384 
 1385     /* XXX poll for more AENs? */
 1386 }
 1387 
 1388 /********************************************************************************
 1389  * Pull AENs out of the controller and park them in the queue, in a context where
 1390  * interrupts aren't active.  Return nonzero if we encounter any errors in the
 1391  * process of obtaining all the available AENs.
 1392  */
 1393 static int
 1394 twe_drain_aen_queue(struct twe_softc *sc)
 1395 {
 1396     u_int16_t   aen;
 1397 
 1398     for (;;) {
 1399         if (twe_get_param_2(sc, TWE_PARAM_AEN, TWE_PARAM_AEN_UnitCode, &aen))
 1400             return(1);
 1401         if (aen == TWE_AEN_QUEUE_EMPTY)
 1402             return(0);
 1403         twe_enqueue_aen(sc, aen);
 1404     }
 1405 }
 1406 
 1407 /********************************************************************************
 1408  * Push an AEN that we've received onto the queue.
 1409  *
 1410  * Note that we have to lock this against reentrance, since it may be called
 1411  * from both interrupt and non-interrupt context.
 1412  *
 1413  * If someone is waiting for the AEN we have, wake them up.
 1414  */
 1415 static void
 1416 twe_enqueue_aen(struct twe_softc *sc, u_int16_t aen)
 1417 {
 1418     char        *msg;
 1419     int         s, next, nextnext;
 1420 
 1421     debug_called(4);
 1422 
 1423     if ((msg = twe_format_aen(sc, aen)) != NULL)
 1424         twe_printf(sc, "AEN: <%s>\n", msg);
 1425 
 1426     s = splbio();
 1427     /* enqueue the AEN */
 1428     next = ((sc->twe_aen_head + 1) % TWE_Q_LENGTH);
 1429     nextnext = ((sc->twe_aen_head + 2) % TWE_Q_LENGTH);
 1430     
 1431     /* check to see if this is the last free slot, and subvert the AEN if it is */
 1432     if (nextnext == sc->twe_aen_tail)
 1433         aen = TWE_AEN_QUEUE_FULL;
 1434 
 1435     /* look to see if there's room for this AEN */
 1436     if (next != sc->twe_aen_tail) {
 1437         sc->twe_aen_queue[sc->twe_aen_head] = aen;
 1438         sc->twe_aen_head = next;
 1439     }
 1440 
 1441     /* wake up anyone asleep on the queue */
 1442     wakeup(&sc->twe_aen_queue);
 1443 
 1444     /* anyone looking for this AEN? */
 1445     if (sc->twe_wait_aen == aen) {
 1446         sc->twe_wait_aen = -1;
 1447         wakeup(&sc->twe_wait_aen);
 1448     }
 1449     splx(s);
 1450 }
 1451 
 1452 /********************************************************************************
 1453  * Pop an AEN off the queue, or return -1 if there are none left.
 1454  *
 1455  * We are more or less interrupt-safe, so don't block interrupts.
 1456  */
 1457 static u_int16_t
 1458 twe_dequeue_aen(struct twe_softc *sc)
 1459 {
 1460     u_int16_t   result;
 1461     
 1462     debug_called(4);
 1463 
 1464     if (sc->twe_aen_tail == sc->twe_aen_head) {
 1465         result = TWE_AEN_QUEUE_EMPTY;
 1466     } else {
 1467         result = sc->twe_aen_queue[sc->twe_aen_tail];
 1468         sc->twe_aen_tail = ((sc->twe_aen_tail + 1) % TWE_Q_LENGTH);
 1469     }
 1470     return(result);
 1471 }
 1472 
 1473 /********************************************************************************
 1474  * Check to see if the requested AEN is in the queue.
 1475  *
 1476  * XXX we could probably avoid masking interrupts here
 1477  */
 1478 static int
 1479 twe_find_aen(struct twe_softc *sc, u_int16_t aen)
 1480 {
 1481     int         i, s, missing;
 1482 
 1483     missing = 1;
 1484     s = splbio();
 1485     for (i = sc->twe_aen_tail; (i != sc->twe_aen_head) && missing; i = (i + 1) % TWE_Q_LENGTH) {
 1486         if (sc->twe_aen_queue[i] == aen)
 1487             missing = 0;
 1488     }
 1489     splx(s);
 1490     return(missing);
 1491 }
 1492 
 1493 
 1494 #if 0   /* currently unused */
 1495 /********************************************************************************
 1496  * Sleep waiting for at least (timeout) seconds until we see (aen) as 
 1497  * requested.  Returns nonzero on timeout or failure.
 1498  *
 1499  * XXX: this should not be used in cases where there may be more than one sleeper
 1500  *      without a mechanism for registering multiple sleepers.
 1501  */
 1502 static int
 1503 twe_wait_aen(struct twe_softc *sc, int aen, int timeout)
 1504 {
 1505     time_t      expiry;
 1506     int         found, s;
 1507 
 1508     debug_called(4);
 1509 
 1510     expiry = time_second + timeout;
 1511     found = 0;
 1512 
 1513     s = splbio();
 1514     sc->twe_wait_aen = aen;
 1515     do {
 1516         twe_fetch_aen(sc);
 1517         tsleep(&sc->twe_wait_aen, PZERO, "twewaen", hz);
 1518         if (sc->twe_wait_aen == -1)
 1519             found = 1;
 1520     } while ((time_second <= expiry) && !found);
 1521     splx(s);
 1522     return(!found);
 1523 }
 1524 #endif
 1525 
 1526 /********************************************************************************
 1527  ********************************************************************************
 1528                                                         Command Buffer Management
 1529  ********************************************************************************
 1530  ********************************************************************************/
 1531 
 1532 /********************************************************************************
 1533  * Get a new command buffer.
 1534  *
 1535  * This will return NULL if all command buffers are in use.
 1536  */
 1537 static int
 1538 twe_get_request(struct twe_softc *sc, struct twe_request **tr)
 1539 {
 1540     TWE_Command         *cmd;
 1541     debug_called(4);
 1542 
 1543     /* try to reuse an old buffer */
 1544     *tr = twe_dequeue_free(sc);
 1545 
 1546     /* initialise some fields to their defaults */
 1547     if (*tr != NULL) {
 1548         cmd = TWE_FIND_COMMAND(*tr);
 1549         (*tr)->tr_data = NULL;
 1550         (*tr)->tr_private = NULL;
 1551         (*tr)->tr_status = TWE_CMD_SETUP;               /* command is in setup phase */
 1552         (*tr)->tr_flags = 0;
 1553         (*tr)->tr_complete = NULL;
 1554         cmd->generic.status = 0;                        /* before submission to controller */
 1555         cmd->generic.flags = 0;                         /* not used */
 1556     }
 1557     return(*tr == NULL);
 1558 }
 1559 
 1560 /********************************************************************************
 1561  * Release a command buffer for reuse.
 1562  *
 1563  */
 1564 static void
 1565 twe_release_request(struct twe_request *tr)
 1566 {
 1567     debug_called(4);
 1568 
 1569     if (tr->tr_private != NULL)
 1570         twe_panic(tr->tr_sc, "tr_private != NULL");
 1571     twe_enqueue_free(tr);
 1572 }
 1573 
 1574 /********************************************************************************
 1575  ********************************************************************************
 1576                                                                         Debugging
 1577  ********************************************************************************
 1578  ********************************************************************************/
 1579 
 1580 /********************************************************************************
 1581  * Print some information about the controller
 1582  */
 1583 void
 1584 twe_describe_controller(struct twe_softc *sc)
 1585 {
 1586     TWE_Param           *p[6];
 1587     u_int8_t            ports;
 1588     u_int32_t           size;
 1589     int                 i;
 1590 
 1591     debug_called(2);
 1592 
 1593     /* get the port count */
 1594     twe_get_param_1(sc, TWE_PARAM_CONTROLLER, TWE_PARAM_CONTROLLER_PortCount, &ports);
 1595 
 1596     /* get version strings */
 1597     p[0] = twe_get_param(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_FW,   16, NULL);
 1598     p[1] = twe_get_param(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_BIOS, 16, NULL);
 1599     if (p[0] && p[1])
 1600          twe_printf(sc, "%d ports, Firmware %.16s, BIOS %.16s\n", ports, p[0]->data, p[1]->data);
 1601 
 1602     if (bootverbose) {
 1603         p[2] = twe_get_param(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_Mon,  16, NULL);
 1604         p[3] = twe_get_param(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_PCB,  8, NULL);
 1605         p[4] = twe_get_param(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_ATA,  8, NULL);
 1606         p[5] = twe_get_param(sc, TWE_PARAM_VERSION, TWE_PARAM_VERSION_PCI,  8, NULL);
 1607 
 1608         if (p[2] && p[3] && p[4] && p[5])
 1609             twe_printf(sc, "Monitor %.16s, PCB %.8s, Achip %.8s, Pchip %.8s\n", p[2]->data, p[3]->data,
 1610                 p[4]->data, p[5]->data);
 1611         if (p[2])
 1612             free(p[2], M_DEVBUF);
 1613         if (p[3])
 1614             free(p[3], M_DEVBUF);
 1615         if (p[4])
 1616             free(p[4], M_DEVBUF);
 1617         if (p[5])
 1618             free(p[5], M_DEVBUF);
 1619     }
 1620     if (p[0])
 1621         free(p[0], M_DEVBUF);
 1622     if (p[1])
 1623         free(p[1], M_DEVBUF);
 1624 
 1625     /* print attached drives */
 1626     if (bootverbose) {
 1627         p[0] = twe_get_param(sc, TWE_PARAM_DRIVESUMMARY, TWE_PARAM_DRIVESUMMARY_Status, 16, NULL);
 1628         for (i = 0; i < ports; i++) {
 1629             if (p[0]->data[i] != TWE_PARAM_DRIVESTATUS_Present)
 1630                 continue;
 1631             twe_get_param_4(sc, TWE_PARAM_DRIVEINFO + i, TWE_PARAM_DRIVEINFO_Size, &size);
 1632             p[1] = twe_get_param(sc, TWE_PARAM_DRIVEINFO + i, TWE_PARAM_DRIVEINFO_Model, 40, NULL);
 1633             if (p[1] != NULL) {
 1634                 twe_printf(sc, "port %d: %.40s %dMB\n", i, p[1]->data, size / 2048);
 1635                 free(p[1], M_DEVBUF);
 1636             } else {
 1637                 twe_printf(sc, "port %d, drive status unavailable\n", i);
 1638             }
 1639         }
 1640         if (p[0])
 1641             free(p[0], M_DEVBUF);
 1642     }
 1643 }
 1644 
 1645 /********************************************************************************
 1646  * Look up a text description of a numeric code and return a pointer to same.
 1647  */
 1648 char *
 1649 twe_describe_code(struct twe_code_lookup *table, u_int32_t code)
 1650 {
 1651     int         i;
 1652 
 1653     for (i = 0; table[i].string != NULL; i++)
 1654         if (table[i].code == code)
 1655             return(table[i].string);
 1656     return(table[i+1].string);
 1657 }
 1658 
 1659 /********************************************************************************
 1660  * Complain if the status bits aren't what we're expecting.
 1661  *
 1662  * Rate-limit the complaints to at most one of each every five seconds, but
 1663  * always return the correct status.
 1664  */
 1665 static int
 1666 twe_check_bits(struct twe_softc *sc, u_int32_t status_reg)
 1667 {
 1668     int                 result;
 1669     static time_t       lastwarn[2] = {0, 0};
 1670 
 1671     /*
 1672      * This can be a little problematic, as twe_panic may call twe_reset if 
 1673      * TWE_DEBUG is not set, which will call us again as part of the soft reset.
 1674      */
 1675     if ((status_reg & TWE_STATUS_PANIC_BITS) != 0) {
 1676         twe_printf(sc, "FATAL STATUS BIT(S) %b\n", status_reg & TWE_STATUS_PANIC_BITS,
 1677                    TWE_STATUS_BITS_DESCRIPTION);
 1678         twe_panic(sc, "fatal status bits");
 1679     }
 1680 
 1681     result = 0;
 1682     if ((status_reg & TWE_STATUS_EXPECTED_BITS) != TWE_STATUS_EXPECTED_BITS) {
 1683         if (time_second > (lastwarn[0] + 5)) {
 1684             twe_printf(sc, "missing expected status bit(s) %b\n", ~status_reg & TWE_STATUS_EXPECTED_BITS, 
 1685                        TWE_STATUS_BITS_DESCRIPTION);
 1686             lastwarn[0] = time_second;
 1687         }
 1688         result = 1;
 1689     }
 1690 
 1691     if ((status_reg & TWE_STATUS_UNEXPECTED_BITS) != 0) {
 1692         if (time_second > (lastwarn[1] + 5)) {
 1693             twe_printf(sc, "unexpected status bit(s) %b\n", status_reg & TWE_STATUS_UNEXPECTED_BITS, 
 1694                        TWE_STATUS_BITS_DESCRIPTION);
 1695             lastwarn[1] = time_second;
 1696         }
 1697         result = 1;
 1698         if (status_reg & TWE_STATUS_PCI_PARITY_ERROR) {
 1699             twe_printf(sc, "PCI parity error: Reseat card, move card or buggy device present.\n");
 1700             twe_clear_pci_parity_error(sc);
 1701         }
 1702         if (status_reg & TWE_STATUS_PCI_ABORT) {
 1703             twe_printf(sc, "PCI abort, clearing.\n");
 1704             twe_clear_pci_abort(sc);
 1705         }
 1706     }
 1707 
 1708     return(result);
 1709 }       
 1710 
 1711 /********************************************************************************
 1712  * Return a string describing (aen).
 1713  *
 1714  * The low 8 bits of the aen are the code, the high 8 bits give the unit number
 1715  * where an AEN is specific to a unit.
 1716  *
 1717  * Note that we could expand this routine to handle eg. up/downgrading the status
 1718  * of a drive if we had some idea of what the drive's initial status was.
 1719  */
 1720 
 1721 static char *
 1722 twe_format_aen(struct twe_softc *sc, u_int16_t aen)
 1723 {
 1724     static char buf[80];
 1725     device_t    child;
 1726     char        *code, *msg;
 1727 
 1728     code = twe_describe_code(twe_table_aen, TWE_AEN_CODE(aen));
 1729     msg = code + 2;
 1730 
 1731     switch (*code) {
 1732     case 'q':
 1733         if (!bootverbose)
 1734             return(NULL);
 1735         /* FALLTHROUGH */
 1736     case 'a':
 1737         return(msg);
 1738 
 1739     case 'c':
 1740         if ((child = sc->twe_drive[TWE_AEN_UNIT(aen)].td_disk) != NULL) {
 1741             sprintf(buf, "twed%d: %s", device_get_unit(child), msg);
 1742         } else {
 1743             sprintf(buf, "twe%d: %s for unknown unit %d", device_get_unit(sc->twe_dev),
 1744                     msg, TWE_AEN_UNIT(aen));
 1745         }
 1746         return(buf);
 1747 
 1748     case 'p':
 1749         sprintf(buf, "twe%d: port %d: %s", device_get_unit(sc->twe_dev), TWE_AEN_UNIT(aen),
 1750                 msg);
 1751         return(buf);
 1752 
 1753         
 1754     case 'x':
 1755     default:
 1756         break;
 1757     }
 1758     sprintf(buf, "unknown AEN 0x%x", aen);
 1759     return(buf);
 1760 }
 1761 
 1762 /********************************************************************************
 1763  * Print a diagnostic if the status of the command warrants it, and return
 1764  * either zero (command was ok) or nonzero (command failed).
 1765  */
 1766 static int
 1767 twe_report_request(struct twe_request *tr)
 1768 {
 1769     struct twe_softc    *sc = tr->tr_sc;
 1770     TWE_Command         *cmd = TWE_FIND_COMMAND(tr);
 1771     int                 result = 0;
 1772 
 1773     /*
 1774      * Check the command status value and handle accordingly.
 1775      */
 1776     if (cmd->generic.status == TWE_STATUS_RESET) {
 1777         /*
 1778          * The status code 0xff requests a controller reset.
 1779          */
 1780         twe_printf(sc, "command returned with controller reset request\n");
 1781         twe_reset(sc);
 1782         result = 1;
 1783     } else if (cmd->generic.status > TWE_STATUS_FATAL) {
 1784         /*
 1785          * Fatal errors that don't require controller reset.
 1786          *
 1787          * We know a few special flags values.
 1788          */
 1789         switch (cmd->generic.flags) {
 1790         case 0x1b:
 1791             device_printf(sc->twe_drive[cmd->generic.unit].td_disk,
 1792                           "drive timeout");
 1793             break;
 1794         case 0x51:
 1795             device_printf(sc->twe_drive[cmd->generic.unit].td_disk,
 1796                           "unrecoverable drive error");
 1797             break;
 1798         default:
 1799             device_printf(sc->twe_drive[cmd->generic.unit].td_disk,
 1800                           "controller error - %s (flags = 0x%x)\n",
 1801                           twe_describe_code(twe_table_status, cmd->generic.status),
 1802                           cmd->generic.flags);
 1803             result = 1;
 1804         }
 1805     } else if (cmd->generic.status > TWE_STATUS_WARNING) {
 1806         /*
 1807          * Warning level status.
 1808          */
 1809         device_printf(sc->twe_drive[cmd->generic.unit].td_disk,
 1810                       "warning - %s (flags = 0x%x)\n",
 1811                       twe_describe_code(twe_table_status, cmd->generic.status),
 1812                       cmd->generic.flags);
 1813     } else if (cmd->generic.status > 0x40) {
 1814         /*
 1815          * Info level status.
 1816          */
 1817         device_printf(sc->twe_drive[cmd->generic.unit].td_disk,
 1818                       "attention - %s (flags = 0x%x)\n",
 1819                       twe_describe_code(twe_table_status, cmd->generic.status),
 1820                       cmd->generic.flags);
 1821     }
 1822     
 1823     return(result);
 1824 }
 1825 
 1826 /********************************************************************************
 1827  * Print some controller state to aid in debugging error/panic conditions
 1828  */
 1829 void
 1830 twe_print_controller(struct twe_softc *sc)
 1831 {
 1832     u_int32_t           status_reg;
 1833 
 1834     status_reg = TWE_STATUS(sc);
 1835     twe_printf(sc, "status   %b\n", status_reg, TWE_STATUS_BITS_DESCRIPTION);
 1836     twe_printf(sc, "          current  max    min\n");
 1837     twe_printf(sc, "free      %04d     %04d   %04d\n",
 1838         sc->twe_qstat[TWEQ_FREE].q_length, sc->twe_qstat[TWEQ_FREE].q_max, sc->twe_qstat[TWEQ_FREE].q_min);
 1839 
 1840     twe_printf(sc, "ready     %04d     %04d   %04d\n",
 1841         sc->twe_qstat[TWEQ_READY].q_length, sc->twe_qstat[TWEQ_READY].q_max, sc->twe_qstat[TWEQ_READY].q_min);
 1842 
 1843     twe_printf(sc, "busy      %04d     %04d   %04d\n",
 1844         sc->twe_qstat[TWEQ_BUSY].q_length, sc->twe_qstat[TWEQ_BUSY].q_max, sc->twe_qstat[TWEQ_BUSY].q_min);
 1845 
 1846     twe_printf(sc, "complete  %04d     %04d   %04d\n",
 1847         sc->twe_qstat[TWEQ_COMPLETE].q_length, sc->twe_qstat[TWEQ_COMPLETE].q_max, sc->twe_qstat[TWEQ_COMPLETE].q_min);
 1848 
 1849     twe_printf(sc, "bioq      %04d     %04d   %04d\n",
 1850         sc->twe_qstat[TWEQ_BIO].q_length, sc->twe_qstat[TWEQ_BIO].q_max, sc->twe_qstat[TWEQ_BIO].q_min);
 1851 
 1852     twe_printf(sc, "AEN queue head %d  tail %d\n", sc->twe_aen_head, sc->twe_aen_tail);
 1853 }       
 1854 
 1855 static void
 1856 twe_panic(struct twe_softc *sc, char *reason)
 1857 {
 1858     twe_print_controller(sc);
 1859 #ifdef TWE_DEBUG
 1860     panic(reason);
 1861 #else
 1862     twe_reset(sc);
 1863 #endif
 1864 }
 1865 
 1866 #if 0
 1867 /********************************************************************************
 1868  * Print a request/command in human-readable format.
 1869  */
 1870 static void
 1871 twe_print_request(struct twe_request *tr)
 1872 {
 1873     struct twe_softc    *sc = tr->tr_sc;
 1874     TWE_Command *cmd = TWE_FIND_COMMAND(tr);
 1875     int         i;
 1876 
 1877     twe_printf(sc, "CMD: request_id %d  opcode <%s>  size %d  unit %d  host_id %d\n", 
 1878                cmd->generic.request_id, twe_describe_code(twe_table_opcode, cmd->generic.opcode), cmd->generic.size, 
 1879                cmd->generic.unit, cmd->generic.host_id);
 1880     twe_printf(sc, " status %d  flags 0x%x  count %d  sgl_offset %d\n", 
 1881                cmd->generic.status, cmd->generic.flags, cmd->generic.count, cmd->generic.sgl_offset);
 1882 
 1883     switch(cmd->generic.opcode) {       /* XXX add more opcodes? */
 1884     case TWE_OP_READ:
 1885     case TWE_OP_WRITE:
 1886         twe_printf(sc, " lba %d\n", cmd->io.lba);
 1887         for (i = 0; (i < TWE_MAX_SGL_LENGTH) && (cmd->io.sgl[i].length != 0); i++)
 1888             twe_printf(sc, "  %d: 0x%x/%d\n", 
 1889                        i, cmd->io.sgl[i].address, cmd->io.sgl[i].length);
 1890         break;
 1891 
 1892     case TWE_OP_GET_PARAM:
 1893     case TWE_OP_SET_PARAM:
 1894         for (i = 0; (i < TWE_MAX_SGL_LENGTH) && (cmd->param.sgl[i].length != 0); i++)
 1895             twe_printf(sc, "  %d: 0x%x/%d\n", 
 1896                        i, cmd->param.sgl[i].address, cmd->param.sgl[i].length);
 1897         break;
 1898 
 1899     case TWE_OP_INIT_CONNECTION:
 1900         twe_printf(sc, " response queue pointer 0x%x\n", 
 1901                    cmd->initconnection.response_queue_pointer);
 1902         break;
 1903 
 1904     default:
 1905         break;
 1906     }
 1907     twe_printf(sc, " tr_command %p/0x%x  tr_data %p/0x%x,%d\n", 
 1908                tr, TWE_FIND_COMMANDPHYS(tr), tr->tr_data, tr->tr_dataphys, tr->tr_length);
 1909     twe_printf(sc, " tr_status %d  tr_flags 0x%x  tr_complete %p  tr_private %p\n", 
 1910                tr->tr_status, tr->tr_flags, tr->tr_complete, tr->tr_private);
 1911 }
 1912 
 1913 #endif

Cache object: 17860b6b4250545dd4a66a7acfe500ba


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.