This source file includes following definitions.
- sg_ioctl
- sg_open
- sg_close
- sg_malloc
- sg_free
- sg_read
- sg_command_done
- sg_write
- sg_init
- sg_init1
- sg_attach
1
2
3
4
5
6
7
8
9
10 #include <linux/fs.h>
11 #include <linux/kernel.h>
12 #include <linux/sched.h>
13 #include <linux/string.h>
14 #include <linux/errno.h>
15 #include <linux/mtio.h>
16 #include <linux/ioctl.h>
17 #include <linux/fcntl.h>
18 #include <asm/io.h>
19 #include <asm/segment.h>
20 #include <asm/system.h>
21
22 #include "../block/blk.h"
23 #include "scsi.h"
24 #include "scsi_ioctl.h"
25 #include "sg.h"
26
27 int NR_SG=0;
28 int MAX_SG=0;
29
30 #ifdef SG_BIG_BUFF
31 static char *big_buff;
32 static struct wait_queue *big_wait;
33 static int big_inuse=0;
34 #endif
35
36 struct scsi_generic
37 {
38 Scsi_Device *device;
39 int users;
40 struct wait_queue *generic_wait;
41 struct wait_queue *read_wait;
42 struct wait_queue *write_wait;
43 int timeout;
44 int buff_len;
45 char *buff;
46 struct sg_header header;
47 char exclude;
48 char pending;
49 char complete;
50 };
51
52 static struct scsi_generic *scsi_generics=NULL;
53
54 static int sg_ioctl(struct inode * inode,struct file * file,
55 unsigned int cmd_in, unsigned long arg)
56 {
57 int dev = MINOR(inode->i_rdev);
58 if ((dev<0) || (dev>=NR_SG))
59 return -ENXIO;
60 switch(cmd_in)
61 {
62 case SG_SET_TIMEOUT:
63 scsi_generics[dev].timeout=get_fs_long((int *) arg);
64 return 0;
65 case SG_GET_TIMEOUT:
66 return scsi_generics[dev].timeout;
67 default:
68 return scsi_ioctl(scsi_generics[dev].device, cmd_in, (void *) arg);
69 }
70 }
71
72 static int sg_open(struct inode * inode, struct file * filp)
73 {
74 int dev=MINOR(inode->i_rdev);
75 int flags=filp->f_flags;
76 if (dev>=NR_SG)
77 return -ENXIO;
78 if (O_RDWR!=(flags & O_ACCMODE))
79 return -EACCES;
80 if (flags & O_EXCL)
81 {
82 while(scsi_generics[dev].users)
83 {
84 if (flags & O_NONBLOCK)
85 return -EBUSY;
86 interruptible_sleep_on(&scsi_generics[dev].generic_wait);
87 if (current->signal & ~current->blocked)
88 return -ERESTARTSYS;
89 }
90 scsi_generics[dev].exclude=1;
91 }
92 else
93 while(scsi_generics[dev].exclude)
94 {
95 if (flags & O_NONBLOCK)
96 return -EBUSY;
97 interruptible_sleep_on(&scsi_generics[dev].generic_wait);
98 if (current->signal & ~current->blocked)
99 return -ERESTARTSYS;
100 }
101 if (!scsi_generics[dev].users && scsi_generics[dev].pending && scsi_generics[dev].complete)
102 {
103 scsi_free(scsi_generics[dev].buff,scsi_generics[dev].buff_len);
104 scsi_generics[dev].pending=0;
105 }
106 if (!scsi_generics[dev].users)
107 scsi_generics[dev].timeout=SG_DEFAULT_TIMEOUT;
108 scsi_generics[dev].users++;
109 return 0;
110 }
111
112 static void sg_close(struct inode * inode, struct file * filp)
113 {
114 int dev=MINOR(inode->i_rdev);
115 scsi_generics[dev].users--;
116 scsi_generics[dev].exclude=0;
117 wake_up(&scsi_generics[dev].generic_wait);
118 }
119
120 static char *sg_malloc(int size)
121 {
122 if (size<=4096)
123 return (char *) scsi_malloc(size);
124 #ifdef SG_BIG_BUFF
125 if (size<SG_BIG_BUFF)
126 {
127 while(big_inuse)
128 {
129 interruptible_sleep_on(&big_wait);
130 if (current->signal & ~current->blocked)
131 return NULL;
132 }
133 big_inuse=1;
134 return big_buff;
135 }
136 #endif
137 return NULL;
138 }
139
140 static void sg_free(char *buff,int size)
141 {
142 #ifdef SG_BIG_BUFF
143 if (buff==big_buff)
144 {
145 big_inuse=0;
146 wake_up(&big_wait);
147 return;
148 }
149 #endif
150 scsi_free(buff,size);
151 }
152
153 static int sg_read(struct inode *inode,struct file *filp,char *buf,int count)
154 {
155 int dev=MINOR(inode->i_rdev);
156 int i;
157 struct scsi_generic *device=&scsi_generics[dev];
158 if ((i=verify_area(VERIFY_WRITE,buf,count)))
159 return i;
160 while(!device->pending || !device->complete)
161 {
162 if (filp->f_flags & O_NONBLOCK)
163 return -EWOULDBLOCK;
164 interruptible_sleep_on(&device->read_wait);
165 if (current->signal & ~current->blocked)
166 return -ERESTARTSYS;
167 }
168 device->header.pack_len=device->header.reply_len;
169 device->header.result=0;
170 if (count>=sizeof(struct sg_header))
171 {
172 memcpy_tofs(buf,&device->header,sizeof(struct sg_header));
173 buf+=sizeof(struct sg_header);
174 if (count>device->header.pack_len)
175 count=device->header.pack_len;
176 memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header));
177 }
178 else
179 count=0;
180 sg_free(device->buff,device->buff_len);
181 device->pending=0;
182 wake_up(&device->write_wait);
183 return count;
184 }
185
186 static void sg_command_done(Scsi_Cmnd * SCpnt)
187 {
188 int dev=SCpnt->request.dev;
189 struct scsi_generic *device=&scsi_generics[dev];
190 if (!device->pending)
191 {
192 printk("unexpected done for sg %d\n",dev);
193 SCpnt->request.dev=-1;
194 return;
195 }
196 if (SCpnt->sense_buffer[0])
197 {
198 device->header.result=EIO;
199 }
200 else
201 device->header.result=SCpnt->result;
202 device->complete=1;
203 SCpnt->request.dev=-1;
204 wake_up(&scsi_generics[dev].read_wait);
205 }
206
207 static int sg_write(struct inode *inode,struct file *filp,char *buf,int count)
208 {
209 int dev=MINOR(inode->i_rdev);
210 Scsi_Cmnd *SCpnt;
211 int bsize,size,amt,i;
212 unsigned char cmnd[MAX_COMMAND_SIZE];
213 struct scsi_generic *device=&scsi_generics[dev];
214 if ((i=verify_area(VERIFY_READ,buf,count)))
215 return i;
216 if (count<sizeof(struct sg_header))
217 return -EIO;
218
219 while(device->pending)
220 {
221 if (filp->f_flags & O_NONBLOCK)
222 return -EWOULDBLOCK;
223 #ifdef DEBUG
224 printk("sg_write: sleeping on pending request\n");
225 #endif
226 interruptible_sleep_on(&device->write_wait);
227 if (current->signal & ~current->blocked)
228 return -ERESTARTSYS;
229 }
230 device->pending=1;
231 device->complete=0;
232 memcpy_fromfs(&device->header,buf,sizeof(struct sg_header));
233
234 device->header.pack_len=count;
235 buf+=sizeof(struct sg_header);
236 bsize=(device->header.pack_len>device->header.reply_len) ? device->header.pack_len : device->header.reply_len;
237 bsize-=sizeof(struct sg_header);
238 amt=bsize;
239 if (!bsize)
240 bsize++;
241 bsize=(bsize+511) & ~511;
242 if ((bsize<0) || !(device->buff=sg_malloc(device->buff_len=bsize)))
243 {
244 device->pending=0;
245 wake_up(&device->write_wait);
246 return -ENOMEM;
247 }
248 #ifdef DEBUG
249 printk("allocating device\n");
250 #endif
251 if (!(SCpnt=allocate_device(NULL,device->device->index, !(filp->f_flags & O_NONBLOCK))))
252 {
253 device->pending=0;
254 wake_up(&device->write_wait);
255 sg_free(device->buff,device->buff_len);
256 return -EWOULDBLOCK;
257 }
258 #ifdef DEBUG
259 printk("device allocated\n");
260 #endif
261
262 SCpnt->request.dev=dev;
263 SCpnt->sense_buffer[0]=0;
264 size=COMMAND_SIZE(get_fs_byte(buf));
265 memcpy_fromfs(cmnd,buf,size);
266 buf+=size;
267 memcpy_fromfs(device->buff,buf,device->header.pack_len-size-sizeof(struct sg_header));
268 cmnd[1]=(cmnd[1] & 0x1f) | (device->device->lun<<5);
269 #ifdef DEBUG
270 printk("do cmd\n");
271 #endif
272 scsi_do_cmd (SCpnt,(void *) cmnd,
273 (void *) device->buff,amt,sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
274 #ifdef DEBUG
275 printk("done cmd\n");
276 #endif
277 return count;
278 }
279
280 static struct file_operations sg_fops = {
281 NULL,
282 sg_read,
283 sg_write,
284 NULL,
285 NULL,
286 sg_ioctl,
287 NULL,
288 sg_open,
289 sg_close,
290 NULL
291 };
292
293
294
295 unsigned long sg_init(unsigned long mem_start, unsigned long mem_end)
296 {
297 if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
298 {
299 printk("Unable to get major %d for generic SCSI device\n",
300 SCSI_GENERIC_MAJOR);
301 return mem_start;
302 }
303 if (NR_SG == 0) return mem_start;
304
305 #ifdef DEBUG
306 printk("sg: Init generic device.\n");
307 #endif
308
309 #ifdef SG_BIG_BUFF
310 big_buff= (char *) mem_start;
311 mem_start+=SG_BIG_BUFF;
312 #endif
313 return mem_start;
314 }
315
316 unsigned long sg_init1(unsigned long mem_start, unsigned long mem_end)
317 {
318 scsi_generics = (struct scsi_generic *) mem_start;
319 mem_start += MAX_SG * sizeof(struct scsi_generic);
320 return mem_start;
321 };
322
323 void sg_attach(Scsi_Device * SDp)
324 {
325 if(NR_SG >= MAX_SG)
326 panic ("scsi_devices corrupt (sg)");
327 scsi_generics[NR_SG].device=SDp;
328 scsi_generics[NR_SG].users=0;
329 scsi_generics[NR_SG].generic_wait=NULL;
330 scsi_generics[NR_SG].read_wait=NULL;
331 scsi_generics[NR_SG].write_wait=NULL;
332 scsi_generics[NR_SG].exclude=0;
333 scsi_generics[NR_SG].pending=0;
334 scsi_generics[NR_SG].timeout=SG_DEFAULT_TIMEOUT;
335 NR_SG++;
336 };