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 #define BELT_AND_BRACES
14 
15 /*
16  * The scatter-gather list handling.  This contains all
17  * the yucky stuff that needs to be fixed properly.
18  */
copy_SCp_to_sg(struct scatterlist * sg,Scsi_Pointer * SCp,int max)19 static inline int copy_SCp_to_sg(struct scatterlist *sg, Scsi_Pointer *SCp, int max)
20 {
21 	int bufs = SCp->buffers_residual;
22 
23 	BUG_ON(bufs + 1 > max);
24 
25 	sg->address = SCp->ptr;
26 	sg->length = SCp->this_residual;
27 
28 	if (bufs)
29 		memcpy(sg + 1, SCp->buffer + 1,
30 		       sizeof(struct scatterlist) * bufs);
31 	return bufs + 1;
32 }
33 
next_SCp(Scsi_Pointer * SCp)34 static inline int next_SCp(Scsi_Pointer *SCp)
35 {
36 	int ret = SCp->buffers_residual;
37 	if (ret) {
38 		SCp->buffer++;
39 		SCp->buffers_residual--;
40 		SCp->ptr = (unsigned char *)SCp->buffer->address;
41 		SCp->this_residual = SCp->buffer->length;
42 	} else {
43 		SCp->ptr = NULL;
44 		SCp->this_residual = 0;
45 	}
46 	return ret;
47 }
48 
get_next_SCp_byte(Scsi_Pointer * SCp)49 static inline unsigned char get_next_SCp_byte(Scsi_Pointer *SCp)
50 {
51 	char c = *SCp->ptr;
52 
53 	SCp->ptr += 1;
54 	SCp->this_residual -= 1;
55 
56 	return c;
57 }
58 
put_next_SCp_byte(Scsi_Pointer * SCp,unsigned char c)59 static inline void put_next_SCp_byte(Scsi_Pointer *SCp, unsigned char c)
60 {
61 	*SCp->ptr = c;
62 	SCp->ptr += 1;
63 	SCp->this_residual -= 1;
64 }
65 
init_SCp(Scsi_Cmnd * SCpnt)66 static inline void init_SCp(Scsi_Cmnd *SCpnt)
67 {
68 	memset(&SCpnt->SCp, 0, sizeof(struct scsi_pointer));
69 
70 	if (SCpnt->use_sg) {
71 		unsigned long len = 0;
72 		int buf;
73 
74 		SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;
75 		SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;
76 		SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address;
77 		SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;
78 
79 #ifdef BELT_AND_BRACES
80 		/*
81 		 * Calculate correct buffer length.  Some commands
82 		 * come in with the wrong request_bufflen.
83 		 */
84 		for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++)
85 			len += SCpnt->SCp.buffer[buf].length;
86 
87 		if (SCpnt->request_bufflen != len)
88 			printk(KERN_WARNING "scsi%d.%c: bad request buffer "
89 			       "length %d, should be %ld\n", SCpnt->host->host_no,
90 			       '0' + SCpnt->target, SCpnt->request_bufflen, len);
91 		SCpnt->request_bufflen = len;
92 #endif
93 	} else {
94 		SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer;
95 		SCpnt->SCp.this_residual = SCpnt->request_bufflen;
96 	}
97 
98 	/*
99 	 * If the upper SCSI layers pass a buffer, but zero length,
100 	 * we aren't interested in the buffer pointer.
101 	 */
102 	if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) {
103 #if 0 //def BELT_AND_BRACES
104 		printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for "
105 		       "command ", SCpnt->host->host_no, '0' + SCpnt->target);
106 		print_command(SCpnt->cmnd);
107 #endif
108 		SCpnt->SCp.ptr = NULL;
109 	}
110 }
111 
scsi_host_hn_get(int host_no)112 static inline struct Scsi_Host *scsi_host_hn_get(int host_no)
113 {
114 	struct Scsi_Host *host = scsi_hostlist;
115 
116 	while (host) {
117 		if (host->host_no == host_no)
118 			break;
119 		host = host->next;
120 	}
121 
122 	return host;
123 }
124