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

Cache object: eace3199ef7daec8902b89773ac209ce


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