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

Cache object: 4bdd8f1332fa9aa136879764272f906f


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