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