linux/drivers/scsi/arm/scsi.h
<<
>>
Prefs
   1/*
   2 *  linux/drivers/acorn/scsi/scsi.h
   3 *
   4 *  Copyright (C) 2002 Russell King
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 *  Commonly used scsi driver functions.
  11 */
  12
  13#include <linux/scatterlist.h>
  14
  15#define BELT_AND_BRACES
  16
  17/*
  18 * The scatter-gather list handling.  This contains all
  19 * the yucky stuff that needs to be fixed properly.
  20 */
  21
  22/*
  23 * copy_SCp_to_sg() Assumes contiguous allocation at @sg of at-most @max
  24 * entries of uninitialized memory. SCp is from scsi-ml and has a valid
  25 * (possibly chained) sg-list
  26 */
  27static inline int copy_SCp_to_sg(struct scatterlist *sg, struct scsi_pointer *SCp, int max)
  28{
  29        int bufs = SCp->buffers_residual;
  30
  31        /* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg().
  32         * and to remove this BUG_ON. Use min() in-its-place
  33         */
  34        BUG_ON(bufs + 1 > max);
  35
  36        sg_set_buf(sg, SCp->ptr, SCp->this_residual);
  37
  38        if (bufs) {
  39                struct scatterlist *src_sg;
  40                unsigned i;
  41
  42                for_each_sg(sg_next(SCp->buffer), src_sg, bufs, i)
  43                        *(++sg) = *src_sg;
  44                sg_mark_end(sg);
  45        }
  46
  47        return bufs + 1;
  48}
  49
  50static inline int next_SCp(struct scsi_pointer *SCp)
  51{
  52        int ret = SCp->buffers_residual;
  53        if (ret) {
  54                SCp->buffer = sg_next(SCp->buffer);
  55                SCp->buffers_residual--;
  56                SCp->ptr = sg_virt(SCp->buffer);
  57                SCp->this_residual = SCp->buffer->length;
  58        } else {
  59                SCp->ptr = NULL;
  60                SCp->this_residual = 0;
  61        }
  62        return ret;
  63}
  64
  65static inline unsigned char get_next_SCp_byte(struct scsi_pointer *SCp)
  66{
  67        char c = *SCp->ptr;
  68
  69        SCp->ptr += 1;
  70        SCp->this_residual -= 1;
  71
  72        return c;
  73}
  74
  75static inline void put_next_SCp_byte(struct scsi_pointer *SCp, unsigned char c)
  76{
  77        *SCp->ptr = c;
  78        SCp->ptr += 1;
  79        SCp->this_residual -= 1;
  80}
  81
  82static inline void init_SCp(struct scsi_cmnd *SCpnt)
  83{
  84        memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer));
  85
  86        if (scsi_bufflen(SCpnt)) {
  87                unsigned long len = 0;
  88
  89                SCpnt->SCp.buffer = scsi_sglist(SCpnt);
  90                SCpnt->SCp.buffers_residual = scsi_sg_count(SCpnt) - 1;
  91                SCpnt->SCp.ptr = sg_virt(SCpnt->SCp.buffer);
  92                SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
  93                SCpnt->SCp.phase = scsi_bufflen(SCpnt);
  94
  95#ifdef BELT_AND_BRACES
  96                {       /*
  97                         * Calculate correct buffer length.  Some commands
  98                         * come in with the wrong scsi_bufflen.
  99                         */
 100                        struct scatterlist *sg;
 101                        unsigned i, sg_count = scsi_sg_count(SCpnt);
 102
 103                        scsi_for_each_sg(SCpnt, sg, sg_count, i)
 104                                len += sg->length;
 105
 106                        if (scsi_bufflen(SCpnt) != len) {
 107                                printk(KERN_WARNING
 108                                       "scsi%d.%c: bad request buffer "
 109                                       "length %d, should be %ld\n",
 110                                        SCpnt->device->host->host_no,
 111                                        '0' + SCpnt->device->id,
 112                                        scsi_bufflen(SCpnt), len);
 113                                /*
 114                                 * FIXME: Totaly naive fixup. We should abort
 115                                 * with error
 116                                 */
 117                                SCpnt->SCp.phase =
 118                                        min_t(unsigned long, len,
 119                                              scsi_bufflen(SCpnt));
 120                        }
 121                }
 122#endif
 123        } else {
 124                SCpnt->SCp.ptr = NULL;
 125                SCpnt->SCp.this_residual = 0;
 126                SCpnt->SCp.phase = 0;
 127        }
 128}
 129