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