1 /* SPDX-License-Identifier: GPL-2.0-only */
3 * linux/drivers/acorn/scsi/scsi.h
5 * Copyright (C) 2002 Russell King
7 * Commonly used scsi driver functions.
10 #include <linux/scatterlist.h>
12 #define BELT_AND_BRACES
15 * The scatter-gather list handling. This contains all
16 * the yucky stuff that needs to be fixed properly.
20 * copy_SCp_to_sg() Assumes contiguous allocation at @sg of at-most @max
21 * entries of uninitialized memory. SCp is from scsi-ml and has a valid
22 * (possibly chained) sg-list
24 static inline int copy_SCp_to_sg(struct scatterlist
*sg
, struct scsi_pointer
*SCp
, int max
)
26 int bufs
= SCp
->buffers_residual
;
28 /* FIXME: It should be easy for drivers to loop on copy_SCp_to_sg().
29 * and to remove this BUG_ON. Use min() in-its-place
31 BUG_ON(bufs
+ 1 > max
);
33 sg_set_buf(sg
, SCp
->ptr
, SCp
->this_residual
);
36 struct scatterlist
*src_sg
;
39 for_each_sg(sg_next(SCp
->buffer
), src_sg
, bufs
, i
)
47 static inline int next_SCp(struct scsi_pointer
*SCp
)
49 int ret
= SCp
->buffers_residual
;
51 SCp
->buffer
= sg_next(SCp
->buffer
);
52 SCp
->buffers_residual
--;
53 SCp
->ptr
= sg_virt(SCp
->buffer
);
54 SCp
->this_residual
= SCp
->buffer
->length
;
57 SCp
->this_residual
= 0;
62 static inline unsigned char get_next_SCp_byte(struct scsi_pointer
*SCp
)
67 SCp
->this_residual
-= 1;
72 static inline void put_next_SCp_byte(struct scsi_pointer
*SCp
, unsigned char c
)
76 SCp
->this_residual
-= 1;
79 static inline void init_SCp(struct scsi_cmnd
*SCpnt
)
81 memset(&SCpnt
->SCp
, 0, sizeof(struct scsi_pointer
));
83 if (scsi_bufflen(SCpnt
)) {
84 unsigned long len
= 0;
86 SCpnt
->SCp
.buffer
= scsi_sglist(SCpnt
);
87 SCpnt
->SCp
.buffers_residual
= scsi_sg_count(SCpnt
) - 1;
88 SCpnt
->SCp
.ptr
= sg_virt(SCpnt
->SCp
.buffer
);
89 SCpnt
->SCp
.this_residual
= SCpnt
->SCp
.buffer
->length
;
90 SCpnt
->SCp
.phase
= scsi_bufflen(SCpnt
);
92 #ifdef BELT_AND_BRACES
94 * Calculate correct buffer length. Some commands
95 * come in with the wrong scsi_bufflen.
97 struct scatterlist
*sg
;
98 unsigned i
, sg_count
= scsi_sg_count(SCpnt
);
100 scsi_for_each_sg(SCpnt
, sg
, sg_count
, i
)
103 if (scsi_bufflen(SCpnt
) != len
) {
105 "scsi%d.%c: bad request buffer "
106 "length %d, should be %ld\n",
107 SCpnt
->device
->host
->host_no
,
108 '0' + SCpnt
->device
->id
,
109 scsi_bufflen(SCpnt
), len
);
111 * FIXME: Totaly naive fixup. We should abort
115 min_t(unsigned long, len
,
116 scsi_bufflen(SCpnt
));
121 SCpnt
->SCp
.ptr
= NULL
;
122 SCpnt
->SCp
.this_residual
= 0;
123 SCpnt
->SCp
.phase
= 0;