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