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

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


File: drivers/scsi/ide-scsi.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 2/513)

Start/ End/    
True False - Line Source

  1 /*
  2  * linux/drivers/scsi/ide-scsi.c   Version 0.9      Jul   4, 1999
  3  *
  4  * Copyright (C) 1996 - 1999 Gadi Oxman <gadio@netvision.net.il>
  5  */
  6 
  7 /*
  8  * Emulation of a SCSI host adapter for IDE ATAPI devices.
  9  *
  10  * With this driver, one can use the Linux SCSI drivers instead of the
  11  * native IDE ATAPI drivers.
  12  *
  13  * Ver 0.1   Dec  3 96   Initial version.
  14  * Ver 0.2   Jan 26 97   Fixed bug in cleanup_module() and added emulation
  15  *                        of MODE_SENSE_6/MODE_SELECT_6 for cdroms. Thanks
  16  *                        to Janos Farkas for pointing this out.
  17  *                       Avoid using bitfields in structures for m68k.
  18  *                       Added Scatter/Gather and DMA support.
  19  * Ver 0.4   Dec  7 97   Add support for ATAPI PD/CD drives.
  20  *                       Use variable timeout for each command.
  21  * Ver 0.5   Jan  2 98   Fix previous PD/CD support.
  22  *                       Allow disabling of SCSI-6 to SCSI-10 transformation.
  23  * Ver 0.6   Jan 27 98   Allow disabling of SCSI command translation layer
  24  *                        for access through /dev/sg.
  25  *                       Fix MODE_SENSE_6/MODE_SELECT_6/INQUIRY translation.
  26  * Ver 0.7   Dec 04 98   Ignore commands where lun != 0 to avoid multiple
  27  *                        detection of devices with CONFIG_SCSI_MULTI_LUN
  28  * Ver 0.8   Feb 05 99   Optical media need translation too. Reverse 0.7.
  29  * Ver 0.9   Jul 04 99   Fix a bug in SG_SET_TRANSFORM.
  30  * Ver 0.91  Jun 10 02   Fix "off by one" error in transforms
  31  * Ver 0.92  Dec 31 02   Implement new SCSI mid level API
  32  */
  33 
  34 #define IDESCSI_VERSION "0.92"
  35 
  36 #include <linux/module.h>
  37 #include <linux/config.h>
  38 #include <linux/types.h>
  39 #include <linux/string.h>
  40 #include <linux/kernel.h>
  41 #include <linux/mm.h>
  42 #include <linux/ioport.h>
  43 #include <linux/blkdev.h>
  44 #include <linux/errno.h>
  45 #include <linux/hdreg.h>
  46 #include <linux/slab.h>
  47 #include <linux/ide.h>
  48 #include <linux/scatterlist.h>
  49 #include <linux/delay.h>
  50 
  51 #include <asm/io.h>
  52 #include <asm/bitops.h>
  53 #include <asm/uaccess.h>
  54 
  55 #include <scsi/scsi.h>
  56 #include <scsi/scsi_cmnd.h>
  57 #include <scsi/scsi_device.h>
  58 #include <scsi/scsi_host.h>
  59 #include <scsi/scsi_tcq.h>
  60 #include <scsi/sg.h>
  61 
  62 #define IDESCSI_DEBUG_LOG      0
  63 
  64 typedef struct idescsi_pc_s {
  65    u8 c[12];            /* Actual packet bytes */
  66    int request_transfer;         /* Bytes to transfer */
  67    int actually_transferred;      /* Bytes actually transferred */
  68    int buffer_size;         /* Size of our data buffer */
  69    struct request *rq;         /* The corresponding request */
  70    u8 *buffer;            /* Data buffer */
  71    u8 *current_position;         /* Pointer into the above buffer */
  72    struct scatterlist *sg;         /* Scatter gather table */
  73    int b_count;            /* Bytes transferred from current entry */
  74    struct scsi_cmnd *scsi_cmd;      /* SCSI command */
  75    void (*done)(struct scsi_cmnd *);   /* Scsi completion routine */
  76    unsigned long flags;         /* Status/Action flags */
  77    unsigned long timeout;         /* Command timeout */
  78 } idescsi_pc_t;
  79 
  80 /*
  81  *   Packet command status bits.
  82  */
  83 #define PC_DMA_IN_PROGRESS      0   /* 1 while DMA in progress */
  84 #define PC_WRITING         1   /* Data direction */
  85 #define PC_TRANSFORM         2   /* transform SCSI commands */
  86 #define PC_TIMEDOUT         3   /* command timed out */
  87 #define PC_DMA_OK         4   /* Use DMA */
  88 
  89 /*
  90  *   SCSI command transformation layer
  91  */
  92 #define IDESCSI_TRANSFORM      0   /* Enable/Disable transformation */
  93 #define IDESCSI_SG_TRANSFORM      1   /* /dev/sg transformation */
  94 
  95 /*
  96  *   Log flags
  97  */
  98 #define IDESCSI_LOG_CMD         0   /* Log SCSI commands */
  99 
  100 typedef struct ide_scsi_obj {
  101    ide_drive_t      *drive;
  102    ide_driver_t      *driver;
  103    struct gendisk      *disk;
  104    struct Scsi_Host   *host;
  105 
  106    idescsi_pc_t *pc;         /* Current packet command */
  107    unsigned long flags;         /* Status/Action flags */
  108    unsigned long transform;      /* SCSI cmd translation layer */
  109    unsigned long log;         /* log flags */
  110 } idescsi_scsi_t;
  111 
  112 static DECLARE_MUTEX(idescsi_ref_sem);
  113 
  114 #define ide_scsi_g(disk) \
  115    container_of((disk)->private_data, struct ide_scsi_obj, driver)
  116 
 
- 117 static struct ide_scsi_obj *ide_scsi_get(struct gendisk *disk)
  118 {
  119    struct ide_scsi_obj *scsi = NULL;
  120 
  121    down(&idescsi_ref_sem);
  122    scsi = ide_scsi_g(disk);
- 123    if (scsi)
  124       scsi_host_get(scsi->host);
  125    up(&idescsi_ref_sem);
 - 126    return scsi;
  127 }
  128 
 
- 129 static void ide_scsi_put(struct ide_scsi_obj *scsi)
  130 {
  131    down(&idescsi_ref_sem);
  132    scsi_host_put(scsi->host);
  133    up(&idescsi_ref_sem);
  134 }
  135 
 
- 136 static inline idescsi_scsi_t *scsihost_to_idescsi(struct Scsi_Host *host)
  137 {
 - 138    return (idescsi_scsi_t*) (&host[1]);
  139 }
  140 
 
- 141 static inline idescsi_scsi_t *drive_to_idescsi(ide_drive_t *ide_drive)
  142 {
 - 143    return scsihost_to_idescsi(ide_drive->driver_data);
  144 }
  145 
  146 /*
  147  *   Per ATAPI device status bits.
  148  */
  149 #define IDESCSI_DRQ_INTERRUPT      0   /* DRQ interrupt device */
  150 
  151 /*
  152  *   ide-scsi requests.
  153  */
  154 #define IDESCSI_PC_RQ         90
  155 
 
- 156 static void idescsi_discard_data (ide_drive_t *drive, unsigned int bcount)
  157 {
- 158    while (bcount--)
  159       (void) HWIF(drive)->INB(IDE_DATA_REG);
  160 }
  161 
 
- 162 static void idescsi_output_zeros (ide_drive_t *drive, unsigned int bcount)
  163 {
- 164    while (bcount--)
  165       HWIF(drive)->OUTB(0, IDE_DATA_REG);
  166 }
  167 
  168 /*
  169  *   PIO data transfer routines using the scatter gather table.
  170  */
 
- 171 static void idescsi_input_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
  172 {
  173    int count;
  174    char *buf;
  175 
- 176    while (bcount) {
- 177       if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
  178          printk (KERN_ERR "ide-scsi: scatter gather table too small, discarding data\n");
  179          idescsi_discard_data (drive, bcount);
 - 180          return;
  181       }
  182       count = min(pc->sg->length - pc->b_count, bcount);
- 183       if (PageHighMem(pc->sg->page)) {
  184          unsigned long flags;
  185 
    186          local_irq_save(flags);
    186       do
- 186       do-while (0)
- 186     do-while (0)
  187          buf = kmap_atomic(pc->sg->page, KM_IRQ0) +
  188                pc->sg->offset;
  189          drive->hwif->atapi_input_bytes(drive,
  190                   buf + pc->b_count, count);
    191          kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
- 191     do-while (0)
  192          local_irq_restore(flags);
    193       } else {
  194          buf = page_address(pc->sg->page) + pc->sg->offset;
  195          drive->hwif->atapi_input_bytes(drive,
  196                   buf + pc->b_count, count);
  197       }
  198       bcount -= count; pc->b_count += count;
- 199       if (pc->b_count == pc->sg->length) {
  200          pc->sg++;
  201          pc->b_count = 0;
  202       }
  203    }
  204 }
  205 
 
- 206 static void idescsi_output_buffers (ide_drive_t *drive, idescsi_pc_t *pc, unsigned int bcount)
  207 {
  208    int count;
  209    char *buf;
  210 
- 211    while (bcount) {
- 212       if (pc->sg - (struct scatterlist *) pc->scsi_cmd->request_buffer > pc->scsi_cmd->use_sg) {
  213          printk (KERN_ERR "ide-scsi: scatter gather table too small, padding with zeros\n");
  214          idescsi_output_zeros (drive, bcount);
 - 215          return;
  216       }
  217       count = min(pc->sg->length - pc->b_count, bcount);
- 218       if (PageHighMem(pc->sg->page)) {
  219          unsigned long flags;
  220 
    221          local_irq_save(flags);
    221       do
- 221       do-while (0)
- 221     do-while (0)
  222          buf = kmap_atomic(pc->sg->page, KM_IRQ0) +
  223                   pc->sg->offset;
  224          drive->hwif->atapi_output_bytes(drive,
  225                   buf + pc->b_count, count);
    226          kunmap_atomic(buf - pc->sg->offset, KM_IRQ0);
- 226     do-while (0)
  227          local_irq_restore(flags);
    228       } else {
  229          buf = page_address(pc->sg->page) + pc->sg->offset;
  230          drive->hwif->atapi_output_bytes(drive,
  231                   buf + pc->b_count, count);
  232       }
  233       bcount -= count; pc->b_count += count;
- 234       if (pc->b_count == pc->sg->length) {
  235          pc->sg++;
  236          pc->b_count = 0;
  237       }
  238    }
  239 }
  240 
  241 /*
  242  *   Most of the SCSI commands are supported directly by ATAPI devices.
  243  *   idescsi_transform_pc handles the few exceptions.
  244  */
 
- 245 static inline void idescsi_transform_pc1 (ide_drive_t *drive, idescsi_pc_t *pc)
  246 {
  247    u8 *c = pc->c, *scsi_buf = pc->buffer, *sc = pc->scsi_cmd->cmnd;
  248    char *atapi_buf;
  249 
- 250    if (!test_bit(PC_TRANSFORM, &pc->flags))
- 250 ternary-?: __builtin_constant_p ( 2 )
 - 251       return;
- 252    if (drive->media == ide_cdrom || drive->media == ide_optical) {
 - 252   T || _
 - 252   F || T
 - 252   F || F
- 253       if (c[0] == READ_6 || c[0] == WRITE_6) {
 - 253     T || _
 - 253     F || T
 - 253     F || F
  254          c[8] = c[4];      c[5] = c[3];      c[4] = c[2];
  255          c[3] = c[1] & 0x1f;   c[2] = 0;      c[1] &= 0xe0;
  256          c[0] += (READ_10 - READ_6);
  257       }
- 258       if (c[0] == MODE_SENSE || c[0] == MODE_SELECT) {
 - 258     T || _
 - 258     F || T
 - 258     F || F
  259          unsigned short new_len;
- 260          if (!scsi_buf)
 - 261             return;
- 262          if ((atapi_buf = kmalloc(pc->buffer_size + 4, GFP_ATOMIC)) == NULL)
 - 263             return;
  264          memset(atapi_buf, 0, pc->buffer_size + 4);
  265          memset (c, 0, 12);
  266          c[0] = sc[0] | 0x40;
  267          c[1] = sc[1];
  268          c[2] = sc[2];
  269          new_len = sc[4] + 4;
  270          c[8] = new_len;
  271          c[7] = new_len >> 8;
  272          c[9] = sc[5];
- 273          if (c[0] == MODE_SELECT_10) {
  274             atapi_buf[1] = scsi_buf[0];   /* Mode data length */
  275             atapi_buf[2] = scsi_buf[1];   /* Medium type */
  276             atapi_buf[3] = scsi_buf[2];   /* Device specific parameter */
  277             atapi_buf[7] = scsi_buf[3];   /* Block descriptor length */
  278             memcpy(atapi_buf + 8, scsi_buf + 4, pc->buffer_size - 4);
  279          }
  280          pc->buffer = atapi_buf;
  281          pc->request_transfer += 4;
  282          pc->buffer_size += 4;
  283       }
  284    }
  285 }
  286 
 
- 287 static inline void idescsi_transform_pc2 (ide_drive_t *drive, idescsi_pc_t *pc)
  288 {
  289    u8 *atapi_buf = pc->buffer;
  290    u8 *sc = pc->scsi_cmd->cmnd;
  291    u8 *scsi_buf = pc->scsi_cmd->request_buffer;
  292 
- 293    if (!test_bit(PC_TRANSFORM, &pc->flags))
- 293 ternary-?: __builtin_constant_p ( 2 )
 - 294       return;
- 295    if (drive->media == ide_cdrom || drive->media == ide_optical) {
 - 295   T || _
 - 295   F || T
 - 295   F || F
- 296       if (pc->c[0] == MODE_SENSE_10 && sc[0] == MODE_SENSE) {
 - 296     T && T
 - 296     T && F
 - 296     F && _
  297          scsi_buf[0] = atapi_buf[1];      /* Mode data length */
  298          scsi_buf[1] = atapi_buf[2];      /* Medium type */
  299          scsi_buf[2] = atapi_buf[3];      /* Device specific parameter */
  300          scsi_buf[3] = atapi_buf[7];      /* Block descriptor length */
  301          memcpy(scsi_buf + 4, atapi_buf + 8, pc->request_transfer - 8);
  302       }
- 303       if (pc->c[0] == INQUIRY) {
  304          scsi_buf[2] |= 2;         /* ansi_revision */
  305          scsi_buf[3] = (scsi_buf[3] & 0xf0) | 2;   /* response data format */
  306       }
  307    }
- 308    if (atapi_buf && atapi_buf != scsi_buf)
 - 308   T && T
 - 308   T && F
 - 308   F && _
  309       kfree(atapi_buf);
  310 }
  311 
 
- 312 static void hexdump(u8 *x, int len)
  313 {
  314    int i;
  315 
  316    printk("[ ");
- 317    for (i = 0; i < len; i++)
  318       printk("%x ", x[i]);
  319    printk("]\n");
  320 }
  321 
 
- 322 static int idescsi_check_condition(ide_drive_t *drive, struct request *failed_command)
  323 {
  324    idescsi_scsi_t *scsi = drive_to_idescsi(drive);
  325    idescsi_pc_t   *pc;
  326    struct request *rq;
  327    u8             *buf;
  328 
  329    /* stuff a sense request in front of our current request */
  330    pc = kmalloc (sizeof (idescsi_pc_t), GFP_ATOMIC);
  331    rq = kmalloc (sizeof (struct request), GFP_ATOMIC);
  332    buf = kmalloc(SCSI_SENSE_BUFFERSIZE, GFP_ATOMIC);
- 333    if (pc == NULL || rq == NULL || buf == NULL) {
 - 333   T || _ || _
 - 333   F || T || _
 - 333   F || F || T
 - 333   F || F || F
  334       kfree(buf);
  335       kfree(rq);
  336       kfree(pc);
 - 337       return -ENOMEM;
  338    }
  339    memset (pc, 0, sizeof (idescsi_pc_t));
  340    memset (buf, 0, SCSI_SENSE_BUFFERSIZE);
  341    ide_init_drive_cmd(rq);
  342    rq->special = (char *) pc;
  343    pc->rq = rq;
  344    pc->buffer = buf;
  345    pc->c[0] = REQUEST_SENSE;
  346    pc->c[4] = pc->request_transfer = pc->buffer_size = SCSI_SENSE_BUFFERSIZE;
  347    rq->flags = REQ_SENSE;
  348    pc->timeout = jiffies + WAIT_READY;
  349    /* NOTE! Save the failed packet command in "rq->buffer" */
  350    rq->buffer = (void *) failed_command->special;
  351    pc->scsi_cmd = ((idescsi_pc_t *) failed_command->special)->scsi_cmd;
- 352    if (test_bit(IDESCSI_LOG_CMD, &scsi->log)) {
- 352 ternary-?: __builtin_constant_p ( 0 )
  353       printk ("ide-scsi: %s: queue cmd = ", drive->name);
  354       hexdump(pc->c, 6);
  355    }
  356    rq->rq_disk = scsi->disk;
 - 357    return ide_do_drive_cmd(drive, rq, ide_preempt);
  358 }
  359 
  360 static int idescsi_end_request(ide_drive_t *, int, int);
  361 
  362 static ide_startstop_t
 
- 363 idescsi_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err)
  364 {
- 365    if (HWIF(drive)->INB(IDE_STATUS_REG) & (BUSY_STAT|DRQ_STAT))
  366       /* force an abort */
  367       HWIF(drive)->OUTB(WIN_IDLEIMMEDIATE,IDE_COMMAND_REG);
  368 
  369    rq->errors++;
  370 
  371    idescsi_end_request(drive, 0, 0);
  372 
 - 373    return ide_stopped;
  374 }
  375 
  376 static ide_startstop_t
 
- 377 idescsi_atapi_abort(ide_drive_t *drive, struct request *rq)
  378 {
  379 #if IDESCSI_DEBUG_LOG
  380    printk(KERN_WARNING "idescsi_atapi_abort called for %lu\n",
  381          ((idescsi_pc_t *) rq->special)->scsi_cmd->serial_number);
  382 #endif
  383    rq->errors |= ERROR_MAX;
  384 
  385    idescsi_end_request(drive, 0, 0);
  386 
 - 387    return ide_stopped;
  388 }
  389 
 
- 390 static int idescsi_end_request (ide_drive_t *drive, int uptodate, int nrsecs)
  391 {
  392    idescsi_scsi_t *scsi = drive_to_idescsi(drive);
  393    struct request *rq = HWGROUP(drive)->rq;
  394    idescsi_pc_t *pc = (idescsi_pc_t *) rq->special;
    395    int log = test_bit(IDESCSI_LOG_CMD, &scsi->log);
- 395 ternary-?: __builtin_constant_p ( 0 )
  396    struct Scsi_Host *host;
  397    u8 *scsi_buf;
  398    int errors = rq->errors;
  399    unsigned long flags;
  400 
- 401    if (!(rq->flags & (REQ_SPECIAL|REQ_SENSE))) {
  402       ide_end_request(drive, uptodate, nrsecs);
 - 403       return 0;
  404    }
  405    ide_end_drive_cmd (drive, 0, 0);
- 406    if (rq->flags & REQ_SENSE) {
  407       idescsi_pc_t *opc = (idescsi_pc_t *) rq->buffer;
- 408       if (log) {
  409          printk ("ide-scsi: %s: wrap up check %lu, rst = ", drive->name, opc->scsi_cmd->serial_number);
  410          hexdump(pc->buffer,16);
  411       }
  412       memcpy((void *) opc->scsi_cmd->sense_buffer, pc->buffer, SCSI_SENSE_BUFFERSIZE);
  413       kfree(pc->buffer);
  414       kfree(pc);
  415       kfree(rq);
  416       pc = opc;
  417       rq = pc->rq;
  418       pc->scsi_cmd->result = (CHECK_CONDITION << 1) |
    419                ((test_bit(PC_TIMEDOUT, &pc->flags)?DID_TIME_OUT:DID_OK) << 16);
- 419   ternary-?: __builtin_constant_p ( 3 )
- 419   ternary-?: ( __builtin_constant_p ( 3 ) ? co..
- 420    } else if (test_bit(PC_TIMEDOUT, &pc->flags)) {
- 420 ternary-?: __builtin_constant_p ( 3 )
- 421       if (log)
  422          printk (KERN_WARNING "ide-scsi: %s: timed out for %lu\n",
  423                drive->name, pc->scsi_cmd->serial_number);
  424       pc->scsi_cmd->result = DID_TIME_OUT << 16;
- 425    } else if (errors >= ERROR_MAX) {
  426       pc->scsi_cmd->result = DID_ERROR << 16;
- 427       if (log)
  428          printk ("ide-scsi: %s: I/O error for %lu\n", drive->name, pc->scsi_cmd->serial_number);
- 429    } else if (errors) {
- 430       if (log)
  431          printk ("ide-scsi: %s: check condition for %lu\n", drive->name, pc->scsi_cmd->serial_number);
- 432       if (!idescsi_check_condition(drive, rq))
  433          /* we started a request sense, so we'll be back, exit for now */
 - 434          return 0;
  435       pc->scsi_cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
    436    } else {
  437       pc->scsi_cmd->result = DID_OK << 16;
  438       idescsi_transform_pc2 (drive, pc);
- 439       if (log) {
  440          printk ("ide-scsi: %s: suc %lu", drive->name, pc->scsi_cmd->serial_number);
- 441          if (!test_bit(PC_WRITING, &pc->flags) && pc->actually_transferred && pc->actually_transferred <= 1024 && pc->buffer) {
 - 441       !(F) && T && T && T
 - 441       !(T) && _ && _ && _
 - 441       !(F) && T && T && F
 - 441       !(F) && T && F && _
 - 441       !(F) && F && _ && _
- 441     ternary-?: __builtin_constant_p ( 1 )
  442             printk(", rst = ");
  443             scsi_buf = pc->scsi_cmd->request_buffer;
  444             hexdump(scsi_buf, min_t(unsigned, 16, pc->scsi_cmd->request_bufflen));
    445          } else printk("\n");
  446       }
  447    }
  448    host = pc->scsi_cmd->device->host;
    449    spin_lock_irqsave(host->host_lock, flags);
    449   do
    449     do
- 449     do-while (0)
- 449   do-while (0)
    449   do
    449     do
- 449     do-while (0)
- 449   do-while (0)
- 449 do-while (0)
  450    pc->done(pc->scsi_cmd);
    451    spin_unlock_irqrestore(host->host_lock, flags);