1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * Copyright (C) 2002 Russell King
5 * Commonly used functions by the ARM SCSI-II drivers.
8 #include <linux/scatterlist.h>
10 #define BELT_AND_BRACES
13 struct scsi_pointer scsi_pointer
;
16 static inline struct scsi_pointer
*arm_scsi_pointer(struct scsi_cmnd
*cmd
)
18 struct arm_cmd_priv
*acmd
= scsi_cmd_priv(cmd
);
20 return &acmd
->scsi_pointer
;
24 * The scatter-gather list handling. This contains all
25 * the yucky stuff that needs to be fixed properly.
29 * copy_SCp_to_sg() Assumes contiguous allocation at @sg of at-most @max
30 * entries of uninitialized memory. SCp is from scsi-ml and has a valid
31 * (possibly chained) sg-list
33 static inline int copy_SCp_to_sg(struct scatterlist
*sg
, struct scsi_pointer
*SCp
, int max
)
35 int bufs
= SCp
->buffers_residual
;
37 /* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg().
38 * and to remove this BUG_ON. Use min() in-its-place
40 BUG_ON(bufs
+ 1 > max
);
42 sg_set_buf(sg
, SCp
->ptr
, SCp
->this_residual
);
45 struct scatterlist
*src_sg
;
48 for_each_sg(sg_next(SCp
->buffer
), src_sg
, bufs
, i
)
56 static inline int next_SCp(struct scsi_pointer
*SCp
)
58 int ret
= SCp
->buffers_residual
;
60 SCp
->buffer
= sg_next(SCp
->buffer
);
61 SCp
->buffers_residual
--;
62 SCp
->ptr
= sg_virt(SCp
->buffer
);
63 SCp
->this_residual
= SCp
->buffer
->length
;
66 SCp
->this_residual
= 0;
71 static inline unsigned char get_next_SCp_byte(struct scsi_pointer
*SCp
)
76 SCp
->this_residual
-= 1;
81 static inline void put_next_SCp_byte(struct scsi_pointer
*SCp
, unsigned char c
)
85 SCp
->this_residual
-= 1;
88 static inline void init_SCp(struct scsi_cmnd
*SCpnt
)
90 struct scsi_pointer
*scsi_pointer
= arm_scsi_pointer(SCpnt
);
92 memset(scsi_pointer
, 0, sizeof(struct scsi_pointer
));
94 if (scsi_bufflen(SCpnt
)) {
95 unsigned long len
= 0;
97 scsi_pointer
->buffer
= scsi_sglist(SCpnt
);
98 scsi_pointer
->buffers_residual
= scsi_sg_count(SCpnt
) - 1;
99 scsi_pointer
->ptr
= sg_virt(scsi_pointer
->buffer
);
100 scsi_pointer
->this_residual
= scsi_pointer
->buffer
->length
;
101 scsi_pointer
->phase
= scsi_bufflen(SCpnt
);
103 #ifdef BELT_AND_BRACES
105 * Calculate correct buffer length. Some commands
106 * come in with the wrong scsi_bufflen.
108 struct scatterlist
*sg
;
109 unsigned i
, sg_count
= scsi_sg_count(SCpnt
);
111 scsi_for_each_sg(SCpnt
, sg
, sg_count
, i
)
114 if (scsi_bufflen(SCpnt
) != len
) {
116 "scsi%d.%c: bad request buffer "
117 "length %d, should be %ld\n",
118 SCpnt
->device
->host
->host_no
,
119 '0' + SCpnt
->device
->id
,
120 scsi_bufflen(SCpnt
), len
);
122 * FIXME: Totaly naive fixup. We should abort
125 scsi_pointer
->phase
=
126 min_t(unsigned long, len
,
127 scsi_bufflen(SCpnt
));
132 scsi_pointer
->ptr
= NULL
;
133 scsi_pointer
->this_residual
= 0;
134 scsi_pointer
->phase
= 0;