CTC++ Coverage Report - Execution Profile    #658/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/usb/image/microtek.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/187)

Start/ End/    
True False - Line Source

  1 /* Driver for Microtek Scanmaker X6 USB scanner, and possibly others.
  2  *
  3  * (C) Copyright 2000 John Fremlin <vii@penguinpowered.com>
  4  * (C) Copyright 2000 Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>
  5  *
  6  * Parts shamelessly stolen from usb-storage and copyright by their
  7  * authors. Thanks to Matt Dharm for giving us permission!
  8  *
  9  * This driver implements a SCSI host controller driver and a USB
  10  * device driver. To avoid confusion, all the USB related stuff is
  11  * prefixed by mts_usb_ and all the SCSI stuff by mts_scsi_.
  12  *
  13  * Microtek (www.microtek.com) did not release the specifications for
  14  * their USB protocol to us, so we had to reverse engineer them. We
  15  * don't know for which models they are valid.
  16  *
  17  * The X6 USB has three bulk endpoints, one output (0x1) down which
  18  * commands and outgoing data are sent, and two input: 0x82 from which
  19  * normal data is read from the scanner (in packets of maximum 32
  20  * bytes) and from which the status byte is read, and 0x83 from which
  21  * the results of a scan (or preview) are read in up to 64 * 1024 byte
  22  * chunks by the Windows driver. We don't know how much it is possible
  23  * to read at a time from 0x83.
  24  *
  25  * It seems possible to read (with URB transfers) everything from 0x82
  26  * in one go, without bothering to read in 32 byte chunks.
  27  *
  28  * There seems to be an optimisation of a further READ implicit if
  29  * you simply read from 0x83.
  30  *
  31  * Guessed protocol:
  32  *
  33  *   Send raw SCSI command to EP 0x1
  34  *
  35  *   If there is data to receive:
  36  *      If the command was READ datatype=image:
  37  *         Read a lot of data from EP 0x83
  38  *      Else:
  39  *         Read data from EP 0x82
  40  *   Else:
  41  *      If there is data to transmit:
  42  *         Write it to EP 0x1
  43  *
  44  *   Read status byte from EP 0x82
  45  *
  46  * References:
  47  *
  48  * The SCSI command set for the scanner is available from
  49  *   ftp://ftp.microtek.com/microtek/devpack/
  50  *
  51  * Microtek NV sent us a more up to date version of the document. If
  52  * you want it, just send mail.
  53  *
  54  * Status:
  55  *
  56  *   Untested with multiple scanners.
  57  *   Untested on SMP.
  58  *   Untested on a bigendian machine.
  59  *
  60  * History:
  61  *
  62  *   20000417 starting history
  63  *   20000417 fixed load oops
  64  *   20000417 fixed unload oops
  65  *   20000419 fixed READ IMAGE detection
  66  *   20000424 started conversion to use URBs
  67  *   20000502 handled short transfers as errors
  68  *   20000513 rename and organisation of functions (john)
  69  *   20000513 added IDs for all products supported by Windows driver (john)
  70  *   20000514 Rewrote mts_scsi_queuecommand to use URBs (john)
  71  *   20000514 Version 0.0.8j
  72  *      20000514 Fix reporting of non-existant devices to SCSI layer (john)
  73  *   20000514 Added MTS_DEBUG_INT (john)
  74  *   20000514 Changed "usb-microtek" to "microtek" for consistency (john)
  75  *   20000514 Stupid bug fixes (john)
  76  *   20000514 Version 0.0.9j
  77  *   20000515 Put transfer context and URB in mts_desc (john)
  78  *   20000515 Added prelim turn off debugging support (john)
  79  *   20000515 Version 0.0.10j
  80  *      20000515 Fixed up URB allocation (clear URB on alloc) (john)
  81  *      20000515 Version 0.0.11j
  82  *   20000516 Removed unnecessary spinlock in mts_transfer_context (john)
  83  *   20000516 Removed unnecessary up on instance lock in mts_remove_nolock (john)
  84  *   20000516 Implemented (badly) scsi_abort (john)
  85  *   20000516 Version 0.0.12j
  86  *      20000517 Hopefully removed mts_remove_nolock quasideadlock (john)
  87  *      20000517 Added mts_debug_dump to print ll USB info (john)
  88  *   20000518 Tweaks and documentation updates (john)
  89  *   20000518 Version 0.0.13j
  90  *   20000518 Cleaned up abort handling (john)
  91  *   20000523 Removed scsi_command and various scsi_..._resets (john)
  92  *   20000523 Added unlink URB on scsi_abort, now OHCI supports it (john)
  93  *   20000523 Fixed last tiresome compile warning (john)
  94  *   20000523 Version 0.0.14j (though version 0.1 has come out?)
  95  *   20000602 Added primitive reset
  96  *   20000602 Version 0.2.0
  97  *   20000603 various cosmetic changes
  98  *   20000603 Version 0.2.1
  99  *   20000620 minor cosmetic changes
  100  *   20000620 Version 0.2.2
  101  *   20000822 Hopefully fixed deadlock in mts_remove_nolock()
  102  *   20000822 Fixed minor race in mts_transfer_cleanup()
  103  *   20000822 Fixed deadlock on submission error in queuecommand
  104  *   20000822 Version 0.2.3
  105  *   20000913 Reduced module size if debugging is off
  106  *   20000913 Version 0.2.4
  107  *      20010210 New abort logic
  108  *      20010210 Version 0.3.0
  109  *   20010217 Merged scatter/gather
  110  *   20010218 Version 0.4.0
  111  *   20010218 Cosmetic fixes
  112  *   20010218 Version 0.4.1
  113  *      20010306 Abort while using scatter/gather
  114  *      20010306 Version 0.4.2
  115  *      20010311 Remove all timeouts and tidy up generally (john)
  116  *   20010320 check return value of scsi_register()
  117  *   20010320 Version 0.4.3
  118  *   20010408 Identify version on module load.
  119  *   20011003 Fix multiple requests
  120  */
  121 
  122 #include <linux/module.h>
  123 #include <linux/kernel.h>
  124 #include <linux/sched.h>
  125 #include <linux/signal.h>
  126 #include <linux/errno.h>
  127 #include <linux/random.h>
  128 #include <linux/poll.h>
  129 #include <linux/init.h>
  130 #include <linux/slab.h>
  131 #include <linux/spinlock.h>
  132 #include <linux/smp_lock.h>
  133 #include <linux/usb.h>
  134 #include <linux/proc_fs.h>
  135 
  136 #include <asm/atomic.h>
  137 #include <linux/blkdev.h>
  138 #include "../../scsi/scsi.h"
  139 #include <scsi/scsi_host.h>
  140 
  141 #include "microtek.h"
  142 
  143 /*
  144  * Version Information
  145  */
  146 #define DRIVER_VERSION "v0.4.3"
  147 #define DRIVER_AUTHOR "John Fremlin <vii@penguinpowered.com>, Oliver Neukum <Oliver.Neukum@lrz.uni-muenchen.de>"
  148 #define DRIVER_DESC "Microtek Scanmaker X6 USB scanner driver"
  149 
  150 /* Should we do debugging? */
  151 
  152 //#define MTS_DO_DEBUG
  153 
  154 /* USB layer driver interface */
  155 
  156 static int mts_usb_probe(struct usb_interface *intf,
  157           const struct usb_device_id *id);
  158 static void mts_usb_disconnect(struct usb_interface *intf);
  159 
  160 static struct usb_device_id mts_usb_ids [];
  161 
  162 static struct usb_driver mts_usb_driver = {
  163    .name =      "microtekX6",
  164    .probe =   mts_usb_probe,
  165    .disconnect =   mts_usb_disconnect,
  166    .id_table =   mts_usb_ids,
  167 };
  168 
  169 
  170 /* Internal driver stuff */
  171 
  172 #define MTS_VERSION   "0.4.3"
  173 #define MTS_NAME   "microtek usb (rev " MTS_VERSION "): "
  174 
  175 #define MTS_WARNING(x...) \
  176    printk( KERN_WARNING MTS_NAME x )
  177 #define MTS_ERROR(x...) \
  178    printk( KERN_ERR MTS_NAME x )
  179 #define MTS_INT_ERROR(x...) \
  180    MTS_ERROR(x)
  181 #define MTS_MESSAGE(x...) \
  182    printk( KERN_INFO MTS_NAME x )
  183 
  184 #if defined MTS_DO_DEBUG
  185 
  186 #define MTS_DEBUG(x...) \
  187    printk( KERN_DEBUG MTS_NAME x )
  188 
  189 #define MTS_DEBUG_GOT_HERE() \
  190    MTS_DEBUG("got to %s:%d (%s)\n", __FILE__, (int)__LINE__, __PRETTY_FUNCTION__ )
  191 #define MTS_DEBUG_INT() \
  192    do { MTS_DEBUG_GOT_HERE(); \
  193         MTS_DEBUG("transfer = 0x%x context = 0x%x\n",(int)transfer,(int)context ); \
  194         MTS_DEBUG("status = 0x%x data-length = 0x%x sent = 0x%x\n",(int)transfer->status,(int)context->data_length, (int)transfer->actual_length ); \
  195              mts_debug_dump(context->instance);\
  196       } while(0)
  197 #else
  198 
  199 #define MTS_NUL_STATEMENT do { } while(0)
  200 
  201 #define MTS_DEBUG(x...)   MTS_NUL_STATEMENT
  202 #define MTS_DEBUG_GOT_HERE() MTS_NUL_STATEMENT
  203 #define MTS_DEBUG_INT() MTS_NUL_STATEMENT
  204 
  205 #endif
  206 
  207 
  208 
  209 #define MTS_INT_INIT()\
  210    struct mts_transfer_context* context = (struct mts_transfer_context*)transfer->context; \
  211    MTS_DEBUG_INT();\
  212 
  213 #ifdef MTS_DO_DEBUG
  214 
  215 static inline void mts_debug_dump(struct mts_desc* desc) {
  216    MTS_DEBUG("desc at 0x%x: toggle = %02x%02x\n",
  217         (int)desc,
  218         (int)desc->usb_dev->toggle[1],(int)desc->usb_dev->toggle[0]
  219       );
  220    MTS_DEBUG("ep_out=%x ep_response=%x ep_image=%x\n",
  221         usb_sndbulkpipe(desc->usb_dev,desc->ep_out),
  222         usb_rcvbulkpipe(desc->usb_dev,desc->ep_response),
  223         usb_rcvbulkpipe(desc->usb_dev,desc->ep_image)
  224       );
  225 }
  226 
  227 
  228 static inline void mts_show_command(Scsi_Cmnd *srb)
  229 {
  230    char *what = NULL;
  231 
  232    switch (srb->cmnd[0]) {
  233    case TEST_UNIT_READY: what = "TEST_UNIT_READY"; break;
  234    case REZERO_UNIT: what = "REZERO_UNIT"; break;
  235    case REQUEST_SENSE: what = "REQUEST_SENSE"; break;
  236    case FORMAT_UNIT: what = "FORMAT_UNIT"; break;
  237    case READ_BLOCK_LIMITS: what = "READ_BLOCK_LIMITS"; break;
  238    case REASSIGN_BLOCKS: what = "REASSIGN_BLOCKS"; break;
  239    case READ_6: what = "READ_6"; break;
  240    case WRITE_6: what = "WRITE_6"; break;
  241    case SEEK_6: what = "SEEK_6"; break;
  242    case READ_REVERSE: what = "READ_REVERSE"; break;
  243    case WRITE_FILEMARKS: what = "WRITE_FILEMARKS"; break;
  244    case SPACE: what = "SPACE"; break;
  245    case INQUIRY: what = "INQUIRY"; break;
  246    case RECOVER_BUFFERED_DATA: what = "RECOVER_BUFFERED_DATA"; break;
  247    case MODE_SELECT: what = "MODE_SELECT"; break;
  248    case RESERVE: what = "RESERVE"; break;
  249    case RELEASE: what = "RELEASE"; break;
  250    case COPY: what = "COPY"; break;
  251    case ERASE: what = "ERASE"; break;
  252    case MODE_SENSE: what = "MODE_SENSE"; break;
  253    case START_STOP: what = "START_STOP"; break;
  254    case RECEIVE_DIAGNOSTIC: what = "RECEIVE_DIAGNOSTIC"; break;
  255    case SEND_DIAGNOSTIC: what = "SEND_DIAGNOSTIC"; break;
  256    case ALLOW_MEDIUM_REMOVAL: what = "ALLOW_MEDIUM_REMOVAL"; break;
  257    case SET_WINDOW: what = "SET_WINDOW"; break;
  258    case READ_CAPACITY: what = "READ_CAPACITY"; break;
  259    case READ_10: what = "READ_10"; break;
  260    case WRITE_10: what = "WRITE_10"; break;
  261    case SEEK_10: what = "SEEK_10"; break;
  262    case WRITE_VERIFY: what = "WRITE_VERIFY"; break;
  263    case VERIFY: what = "VERIFY"; break;
  264    case SEARCH_HIGH: what = "SEARCH_HIGH"; break;
  265    case SEARCH_EQUAL: what = "SEARCH_EQUAL"; break;
  266    case SEARCH_LOW: what = "SEARCH_LOW"; break;
  267    case SET_LIMITS: what = "SET_LIMITS"; break;
  268    case READ_POSITION: what = "READ_POSITION"; break;
  269    case SYNCHRONIZE_CACHE: what = "SYNCHRONIZE_CACHE"; break;
  270    case LOCK_UNLOCK_CACHE: what = "LOCK_UNLOCK_CACHE"; break;
  271    case READ_DEFECT_DATA: what = "READ_DEFECT_DATA"; break;
  272    case MEDIUM_SCAN: what = "MEDIUM_SCAN"; break;
  273    case COMPARE: what = "COMPARE"; break;
  274    case COPY_VERIFY: what = "COPY_VERIFY"; break;
  275    case WRITE_BUFFER: what = "WRITE_BUFFER"; break;
  276    case READ_BUFFER: what = "READ_BUFFER"; break;
  277    case UPDATE_BLOCK: what = "UPDATE_BLOCK"; break;
  278    case READ_LONG: what = "READ_LONG"; break;
  279    case WRITE_LONG: what = "WRITE_LONG"; break;
  280    case CHANGE_DEFINITION: what = "CHANGE_DEFINITION"; break;
  281    case WRITE_SAME: what = "WRITE_SAME"; break;
  282    case READ_TOC: what = "READ_TOC"; break;
  283    case LOG_SELECT: what = "LOG_SELECT"; break;
  284    case LOG_SENSE: what = "LOG_SENSE"; break;
  285    case MODE_SELECT_10: what = "MODE_SELECT_10"; break;
  286    case MODE_SENSE_10: what = "MODE_SENSE_10"; break;
  287    case MOVE_MEDIUM: what = "MOVE_MEDIUM"; break;
  288    case READ_12: what = "READ_12"; break;
  289    case WRITE_12: what = "WRITE_12"; break;
  290    case WRITE_VERIFY_12: what = "WRITE_VERIFY_12"; break;
  291    case SEARCH_HIGH_12: what = "SEARCH_HIGH_12"; break;
  292    case SEARCH_EQUAL_12: what = "SEARCH_EQUAL_12"; break;
  293    case SEARCH_LOW_12: what = "SEARCH_LOW_12"; break;
  294    case READ_ELEMENT_STATUS: what = "READ_ELEMENT_STATUS"; break;
  295    case SEND_VOLUME_TAG: what = "SEND_VOLUME_TAG"; break;
  296    case WRITE_LONG_2: what = "WRITE_LONG_2"; break;
  297    default:
  298       MTS_DEBUG("can't decode command\n");
  299       goto out;
  300       break;
  301    }
  302    MTS_DEBUG( "Command %s (%d bytes)\n", what, srb->cmd_len);
  303 
  304  out:
  305    MTS_DEBUG( "  %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
  306           srb->cmnd[0], srb->cmnd[1], srb->cmnd[2], srb->cmnd[3], srb->cmnd[4], srb->cmnd[5],
  307           srb->cmnd[6], srb->cmnd[7], srb->cmnd[8], srb->cmnd[9]);
  308 }
  309 
  310 #else
  311 
 
- 312 static inline void mts_show_command(Scsi_Cmnd * dummy)
  313 {
  314 }
  315 
 
- 316 static inline void mts_debug_dump(struct mts_desc* dummy)
  317 {
  318 }
  319 
  320 #endif
  321 
 
- 322 static inline void mts_urb_abort(struct mts_desc* desc) {
    323    MTS_DEBUG_GOT_HERE();
- 323 do-while (0)
  324    mts_debug_dump(desc);
  325 
  326    usb_kill_urb( desc->urb );
  327 }
  328 
 
- 329 static int mts_slave_alloc (struct scsi_device *s)
  330 {
  331    s->inquiry_len = 0x24;
 - 332    return 0;
  333 }
  334 
 
- 335 static int mts_slave_configure (struct scsi_device *s)
  336 {
  337    blk_queue_dma_alignment(s->request_queue, (512 - 1));
 - 338    return 0;
  339 }
  340 
 
- 341 static int mts_scsi_abort (Scsi_Cmnd *srb)
  342 {
  343    struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
  344 
    345    MTS_DEBUG_GOT_HERE();
- 345 do-while (0)
  346 
  347    mts_urb_abort(desc);
  348 
 - 349    return FAILED;
  350 }
  351 
 
- 352 static int mts_scsi_host_reset (Scsi_Cmnd *srb)
  353 {
  354    struct mts_desc* desc = (struct mts_desc*)(srb->device->host->hostdata[0]);
  355    int result, rc;
  356 
    357    MTS_DEBUG_GOT_HERE();
- 357 do-while (0)
  358    mts_debug_dump(desc);
  359 
  360    rc = usb_lock_device_for_reset(desc->usb_dev, desc->usb_intf);
- 361    if (rc < 0)
 - 362       return FAILED;
  363    result = usb_reset_device(desc->usb_dev);;
- 364    if (rc)
  365       usb_unlock_device(desc->usb_dev);
    366    return result ? FAILED : SUCCESS;
- 366 ternary-?: result
 - 366 return result ? 0x2003 : 0x2002
  367 }
  368 
  369 static
  370 int mts_scsi_queuecommand (Scsi_Cmnd *srb, mts_scsi_cmnd_callback callback );
  371 
  372 static void mts_transfer_cleanup( struct urb *transfer );
  373 static void mts_do_sg(struct urb * transfer, struct pt_regs *regs);
  374 
  375 static inline
 
- 376 void mts_int_submit_urb (struct urb* transfer,
  377          int pipe,
  378          void* data,
  379          unsigned length,
  380          usb_complete_t callback )
  381 /* Interrupt context! */
  382 
  383 /* Holding transfer->context->lock! */
  384 {
  385    int res;
  386 
    387    MTS_INT_INIT();
- 387 do-while (0)
  388 
  389    usb_fill_bulk_urb(transfer,
  390             context->instance->usb_dev,
  391             pipe,
  392             data,
  393             length,
  394             callback,
  395             context
  396       );
  397 
  398    transfer->status = 0;
  399 
  400    res = usb_submit_urb( transfer, GFP_ATOMIC );
- 401    if ( unlikely(res) ) {
  402       MTS_INT_ERROR( "could not submit URB! Error was %d\n",(int)res );
  403       context->srb->result = DID_ERROR << 16;
  404       mts_transfer_cleanup(transfer);
  405    }
 - 406    return;
  407 }
  408 
  409 
 
- 410 static void mts_transfer_cleanup( struct urb *transfer )
  411 /* Interrupt context! */
  412 {
    413    MTS_INT_INIT();
- 413 do-while (0)
  414 
- 415    if ( likely(context->final_callback != NULL) )
  416       context->final_callback(context->srb);
  417 
  418 }
  419 
 
- 420 static void mts_transfer_done( struct urb *transfer, struct pt_regs *regs )
  421 {
    422    MTS_INT_INIT();
- 422 do-while (0)
  423 
  424    context->srb->result &= MTS_SCSI_ERR_MASK;
  425    context->srb->result |= (unsigned)(*context->scsi_status)<<1;
  426 
  427    mts_transfer_cleanup(transfer);
  428 
 - 429    return;
  430 }
  431 
  432 
 
- 433 static void mts_get_status( struct urb *transfer )
  434 /* Interrupt context! */
  435 {
    436    MTS_INT_INIT();
- 436 do-while (0)
  437 
  438    mts_int_submit_urb(transfer,
  439             usb_rcvbulkpipe(context->instance->usb_dev,
  440                   context->instance->ep_response),
  441             context->scsi_status,
  442             1,
  443             mts_transfer_done );
  444 }
  445 
 
- 446 static void mts_data_done( struct urb* transfer, struct pt_regs *regs )
  447 /* Interrupt context! */
  448 {
    449    MTS_INT_INIT();
- 449 do-while (0)
  450 
- 451    if ( context->data_length != transfer->actual_length ) {
  452       context->srb->resid = context->data_length - transfer->actual_length;
- 453    } else if ( unlikely(transfer->status) ) {
    454       context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
- 454   ternary-?: transfer -> status == - 2
  455    }
  456 
  457    mts_get_status(transfer);
  458 
 - 459    return;
  460 }
  461 
  462 
 
- 463 static void mts_command_done( struct urb *transfer, struct pt_regs *regs )
  464 /* Interrupt context! */
  465 {
    466    MTS_INT_INIT();
- 466 do-while (0)
  467 
- 468    if ( unlikely(transfer->status) ) {
- 469            if (transfer->status == -ENOENT) {
  470               /* We are being killed */
    471          MTS_DEBUG_GOT_HERE();
- 471     do-while (0)
  472          context->srb->result = DID_ABORT<<16;
    473                 } else {
  474               /* A genuine error has occurred */
    475          MTS_DEBUG_GOT_HERE();
- 475     do-while (0)
  476 
  477               context->srb->result = DID_ERROR<<16;
  478                 }
  479       mts_transfer_cleanup(transfer);
  480 
 - 481       return;
  482    }
  483 
- 484    if (context->srb->cmnd[0] == REQUEST_SENSE) {
  485       mts_int_submit_urb(transfer,
  486                context->data_pipe,
  487                context->srb->sense_buffer,
  488                context->data_length,
  489                mts_data_done);
    490    } else { if ( context->data ) {
- 490   if (context -> data)
  491          mts_int_submit_urb(transfer,
  492                   context->data_pipe,
  493                   context->data,
  494                   context->data_length,
    495                   context->srb->use_sg > 1 ? mts_do_sg : mts_data_done);
- 495     ternary-?: context -> srb -> use_sg > 1
    496       } else {
  497          mts_get_status(transfer);
  498       }
  499    }
  500 
 - 501    return;
  502 }
  503 
 
- 504 static void mts_do_sg (struct urb* transfer, struct pt_regs *regs)
  505 {
  506    struct scatterlist * sg;
    507    MTS_INT_INIT();
- 507 do-while (0)
  508 
    509    MTS_DEBUG("Processing fragment %d of %d\n", context->fragment,context->srb->use_sg);
- 509 do-while (0)
  510 
- 511    if (unlikely(transfer->status)) {
    512                 context->srb->result = (transfer->status == -ENOENT ? DID_ABORT : DID_ERROR)<<16;
- 512   ternary-?: transfer -> status == - 2
  513       mts_transfer_cleanup(transfer);
  514         }
  515 
  516    sg = context->srb->buffer;
  517    context->fragment++;
  518    mts_int_submit_urb(transfer,
  519             context->data_pipe,
  520             page_address(sg[context->fragment].page) +
  521             sg[context->fragment].offset,
  522             sg[context->fragment].length,
    523             context->fragment + 1 == context->srb->use_sg ? mts_data_done : mts_do_sg);
- 523 ternary-?: context -> fragment + 1 == context ..
 - 524    return;
  525 }
  526 
  527 static const u8 mts_read_image_sig[] = { 0x28, 00, 00, 00 };
  528 static const u8 mts_read_image_sig_len = 4;
  529 static const unsigned char mts_direction[256/8] = {
  530    0x28, 0x81, 0x14, 0x14, 0x20, 0x01, 0x90, 0x77,
  531    0x0C, 0x20, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00,
  532    0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01,
  533    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  534 };
  535 
  536 
  537 #define MTS_DIRECTION_IS_IN(x) ((mts_direction[x>>3] >> (x & 7)) & 1)
  538 
  539 static void
 
- 540 mts_build_transfer_context( Scsi_Cmnd *srb, struct mts_desc* desc )
  541 {
  542    int pipe;
  543    struct scatterlist * sg;
  544    
    545    MTS_DEBUG_GOT_HERE();
- 545 do-while (0)
  546 
  547