This source file includes following definitions.
- sg_ioctl
- sg_open
- sg_close
- sg_malloc
- sg_free
- sg_read
- sg_command_done
- sg_write
- sg_detect
- sg_init
- sg_attach
- sg_detach
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 "hosts.h"
25 #include "scsi_ioctl.h"
26 #include "sg.h"
27
28 static void sg_init(void);
29 static int sg_attach(Scsi_Device *);
30 static int sg_detect(Scsi_Device *);
31 static void sg_detach(Scsi_Device *);
32
33
34 struct Scsi_Device_Template sg_template = {NULL, NULL, "sg", 0xff,
35 SCSI_GENERIC_MAJOR, 0, 0, 0, 0,
36 sg_detect, sg_init,
37 NULL, sg_attach, sg_detach};
38
39 #ifdef SG_BIG_BUFF
40 static char *big_buff;
41 static struct wait_queue *big_wait;
42 static int big_inuse=0;
43 #endif
44
45 struct scsi_generic
46 {
47 Scsi_Device *device;
48 int users;
49 struct wait_queue *generic_wait;
50 struct wait_queue *read_wait;
51 struct wait_queue *write_wait;
52 int timeout;
53 int buff_len;
54 char *buff;
55 struct sg_header header;
56 char exclude;
57 char pending;
58 char complete;
59 };
60
61 static struct scsi_generic *scsi_generics=NULL;
62 static void sg_free(char *buff,int size);
63
64 static int sg_ioctl(struct inode * inode,struct file * file,
65 unsigned int cmd_in, unsigned long arg)
66 {
67 int dev = MINOR(inode->i_rdev);
68 if ((dev<0) || (dev>=sg_template.dev_max))
69 return -ENXIO;
70 switch(cmd_in)
71 {
72 case SG_SET_TIMEOUT:
73 scsi_generics[dev].timeout=get_fs_long((int *) arg);
74 return 0;
75 case SG_GET_TIMEOUT:
76 return scsi_generics[dev].timeout;
77 default:
78 return scsi_ioctl(scsi_generics[dev].device, cmd_in, (void *) arg);
79 }
80 }
81
82 static int sg_open(struct inode * inode, struct file * filp)
83 {
84 int dev=MINOR(inode->i_rdev);
85 int flags=filp->f_flags;
86 if (dev>=sg_template.dev_max || !scsi_generics[dev].device)
87 return -ENXIO;
88 if (O_RDWR!=(flags & O_ACCMODE))
89 return -EACCES;
90 if (flags & O_EXCL)
91 {
92 while(scsi_generics[dev].users)
93 {
94 if (flags & O_NONBLOCK)
95 return -EBUSY;
96 interruptible_sleep_on(&scsi_generics[dev].generic_wait);
97 if (current->signal & ~current->blocked)
98 return -ERESTARTSYS;
99 }
100 scsi_generics[dev].exclude=1;
101 }
102 else
103 while(scsi_generics[dev].exclude)
104 {
105 if (flags & O_NONBLOCK)
106 return -EBUSY;
107 interruptible_sleep_on(&scsi_generics[dev].generic_wait);
108 if (current->signal & ~current->blocked)
109 return -ERESTARTSYS;
110 }
111 if (!scsi_generics[dev].users && scsi_generics[dev].pending && scsi_generics[dev].complete)
112 {
113 if (scsi_generics[dev].buff != NULL)
114 sg_free(scsi_generics[dev].buff,scsi_generics[dev].buff_len);
115 scsi_generics[dev].buff=NULL;
116 scsi_generics[dev].pending=0;
117 }
118 if (!scsi_generics[dev].users)
119 scsi_generics[dev].timeout=SG_DEFAULT_TIMEOUT;
120 if (scsi_generics[dev].device->host->hostt->usage_count)
121 (*scsi_generics[dev].device->host->hostt->usage_count)++;
122 scsi_generics[dev].users++;
123 return 0;
124 }
125
126 static void sg_close(struct inode * inode, struct file * filp)
127 {
128 int dev=MINOR(inode->i_rdev);
129 scsi_generics[dev].users--;
130 if (scsi_generics[dev].device->host->hostt->usage_count)
131 (*scsi_generics[dev].device->host->hostt->usage_count)--;
132 scsi_generics[dev].exclude=0;
133 wake_up(&scsi_generics[dev].generic_wait);
134 }
135
136 static char *sg_malloc(int size)
137 {
138 if (size<=4096)
139 return (char *) scsi_malloc(size);
140 #ifdef SG_BIG_BUFF
141 if (size<SG_BIG_BUFF)
142 {
143 while(big_inuse)
144 {
145 interruptible_sleep_on(&big_wait);
146 if (current->signal & ~current->blocked)
147 return NULL;
148 }
149 big_inuse=1;
150 return big_buff;
151 }
152 #endif
153 return NULL;
154 }
155
156 static void sg_free(char *buff,int size)
157 {
158 #ifdef SG_BIG_BUFF
159 if (buff==big_buff)
160 {
161 big_inuse=0;
162 wake_up(&big_wait);
163 return;
164 }
165 #endif
166 scsi_free(buff,size);
167 }
168
169 static int sg_read(struct inode *inode,struct file *filp,char *buf,int count)
170 {
171 int dev=MINOR(inode->i_rdev);
172 int i;
173 struct scsi_generic *device=&scsi_generics[dev];
174 if ((i=verify_area(VERIFY_WRITE,buf,count)))
175 return i;
176 while(!device->pending || !device->complete)
177 {
178 if (filp->f_flags & O_NONBLOCK)
179 return -EWOULDBLOCK;
180 interruptible_sleep_on(&device->read_wait);
181 if (current->signal & ~current->blocked)
182 return -ERESTARTSYS;
183 }
184 device->header.pack_len=device->header.reply_len;
185 device->header.result=0;
186 if (count>=sizeof(struct sg_header))
187 {
188 memcpy_tofs(buf,&device->header,sizeof(struct sg_header));
189 buf+=sizeof(struct sg_header);
190 if (count>device->header.pack_len)
191 count=device->header.pack_len;
192 if (count > sizeof(struct sg_header)) {
193 memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header));
194 }
195 }
196 else
197 count=0;
198 sg_free(device->buff,device->buff_len);
199 device->buff = NULL;
200 device->pending=0;
201 wake_up(&device->write_wait);
202 return count;
203 }
204
205 static void sg_command_done(Scsi_Cmnd * SCpnt)
206 {
207 int dev=SCpnt->request.dev;
208 struct scsi_generic *device=&scsi_generics[dev];
209 if (!device->pending)
210 {
211 printk("unexpected done for sg %d\n",dev);
212 SCpnt->request.dev=-1;
213 return;
214 }
215 memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer));
216 if (SCpnt->sense_buffer[0])
217 {
218 device->header.result=EIO;
219 }
220 else
221 device->header.result=SCpnt->result;
222 device->complete=1;
223 SCpnt->request.dev=-1;
224 wake_up(&scsi_generics[dev].read_wait);
225 }
226
227 static int sg_write(struct inode *inode,struct file *filp,char *buf,int count)
228 {
229 int dev=MINOR(inode->i_rdev);
230 Scsi_Cmnd *SCpnt;
231 int bsize,size,amt,i;
232 unsigned char opcode;
233 unsigned char cmnd[MAX_COMMAND_SIZE];
234 struct scsi_generic *device=&scsi_generics[dev];
235
236 if ((i=verify_area(VERIFY_READ,buf,count)))
237 return i;
238
239
240
241
242 if (count<(sizeof(struct sg_header) + 6))
243 return -EIO;
244
245 while(device->pending)
246 {
247 if (filp->f_flags & O_NONBLOCK)
248 return -EWOULDBLOCK;
249 #ifdef DEBUG
250 printk("sg_write: sleeping on pending request\n");
251 #endif
252 interruptible_sleep_on(&device->write_wait);
253 if (current->signal & ~current->blocked)
254 return -ERESTARTSYS;
255 }
256 device->pending=1;
257 device->complete=0;
258 memcpy_fromfs(&device->header,buf,sizeof(struct sg_header));
259
260 device->header.pack_len=count;
261 buf+=sizeof(struct sg_header);
262 bsize=(device->header.pack_len>device->header.reply_len) ? device->header.pack_len : device->header.reply_len;
263 bsize-=sizeof(struct sg_header);
264 amt=bsize;
265 if (!bsize)
266 bsize++;
267 bsize=(bsize+511) & ~511;
268 if ((bsize<0) || !(device->buff=sg_malloc(device->buff_len=bsize)))
269 {
270 device->pending=0;
271 wake_up(&device->write_wait);
272 return -ENOMEM;
273 }
274 #ifdef DEBUG
275 printk("allocating device\n");
276 #endif
277 if (!(SCpnt=allocate_device(NULL,device->device, !(filp->f_flags & O_NONBLOCK))))
278 {
279 device->pending=0;
280 wake_up(&device->write_wait);
281 sg_free(device->buff,device->buff_len);
282 device->buff = NULL;
283 return -EWOULDBLOCK;
284 }
285 #ifdef DEBUG
286 printk("device allocated\n");
287 #endif
288
289 SCpnt->request.dev=dev;
290 SCpnt->sense_buffer[0]=0;
291 opcode = get_fs_byte(buf);
292 size=COMMAND_SIZE(opcode);
293 if (opcode >= 0xc0 && device->header.twelve_byte) size = 12;
294 SCpnt->cmd_len = size;
295
296
297
298 if (count<(sizeof(struct sg_header) + size))
299 {
300 device->pending=0;
301 wake_up(&device->write_wait);
302 sg_free(device->buff,device->buff_len);
303 device->buff = NULL;
304 return -EIO;
305 }
306
307 memcpy_fromfs(cmnd,buf,size);
308 buf+=size;
309 memcpy_fromfs(device->buff,buf,device->header.pack_len-size-sizeof(struct sg_header));
310 cmnd[1]=(cmnd[1] & 0x1f) | (device->device->lun<<5);
311 #ifdef DEBUG
312 printk("do cmd\n");
313 #endif
314 scsi_do_cmd (SCpnt,(void *) cmnd,
315 (void *) device->buff,device->header.pack_len-size-sizeof(struct sg_header),
316 sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
317 #ifdef DEBUG
318 printk("done cmd\n");
319 #endif
320 return count;
321 }
322
323 static struct file_operations sg_fops = {
324 NULL,
325 sg_read,
326 sg_write,
327 NULL,
328 NULL,
329 sg_ioctl,
330 NULL,
331 sg_open,
332 sg_close,
333 NULL
334 };
335
336
337 static int sg_detect(Scsi_Device * SDp){
338 ++sg_template.dev_noticed;
339 return 1;
340 }
341
342
343 static void sg_init()
344 {
345 static int sg_registered = 0;
346
347 if (sg_template.dev_noticed == 0) return;
348
349 if(!sg_registered) {
350 if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
351 {
352 printk("Unable to get major %d for generic SCSI device\n",
353 SCSI_GENERIC_MAJOR);
354 return;
355 }
356 sg_registered++;
357 }
358
359
360 if(scsi_generics) return;
361
362 #ifdef DEBUG
363 printk("sg: Init generic device.\n");
364 #endif
365
366 #ifdef SG_BIG_BUFF
367 big_buff= (char *) scsi_init_malloc(SG_BIG_BUFF, GFP_ATOMIC | GFP_DMA);
368 #endif
369
370 scsi_generics = (struct scsi_generic *)
371 scsi_init_malloc((sg_template.dev_noticed + SG_EXTRA_DEVS)
372 * sizeof(struct scsi_generic), GFP_ATOMIC);
373 memset(scsi_generics, 0, (sg_template.dev_noticed + SG_EXTRA_DEVS)
374 * sizeof(struct scsi_generic));
375
376 sg_template.dev_max = sg_template.dev_noticed;
377 }
378
379 static int sg_attach(Scsi_Device * SDp)
380 {
381 struct scsi_generic * gpnt;
382 int i;
383
384 if(sg_template.nr_dev >= sg_template.dev_max)
385 {
386 SDp->attached--;
387 return 1;
388 }
389
390 for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++)
391 if(!gpnt->device) break;
392
393 if(i >= sg_template.dev_max) panic ("scsi_devices corrupt (sg)");
394
395 scsi_generics[i].device=SDp;
396 scsi_generics[i].users=0;
397 scsi_generics[i].generic_wait=NULL;
398 scsi_generics[i].read_wait=NULL;
399 scsi_generics[i].write_wait=NULL;
400 scsi_generics[i].buff=NULL;
401 scsi_generics[i].exclude=0;
402 scsi_generics[i].pending=0;
403 scsi_generics[i].timeout=SG_DEFAULT_TIMEOUT;
404 sg_template.nr_dev++;
405 return 0;
406 };
407
408
409
410 static void sg_detach(Scsi_Device * SDp)
411 {
412 struct scsi_generic * gpnt;
413 int i;
414
415 for(gpnt = scsi_generics, i=0; i<sg_template.dev_max; i++, gpnt++)
416 if(gpnt->device == SDp) {
417 gpnt->device = NULL;
418 SDp->attached--;
419 sg_template.nr_dev--;
420 return;
421 }
422 return;
423 }