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 if (count > sizeof(struct sg_header)) {
177 memcpy_tofs(buf,device->buff,count-sizeof(struct sg_header));
178 }
179 }
180 else
181 count=0;
182 sg_free(device->buff,device->buff_len);
183 device->pending=0;
184 wake_up(&device->write_wait);
185 return count;
186 }
187
188 static void sg_command_done(Scsi_Cmnd * SCpnt)
189 {
190 int dev=SCpnt->request.dev;
191 struct scsi_generic *device=&scsi_generics[dev];
192 if (!device->pending)
193 {
194 printk("unexpected done for sg %d\n",dev);
195 SCpnt->request.dev=-1;
196 return;
197 }
198 memcpy(device->header.sense_buffer, SCpnt->sense_buffer, sizeof(SCpnt->sense_buffer));
199 if (SCpnt->sense_buffer[0])
200 {
201 device->header.result=EIO;
202 }
203 else
204 device->header.result=SCpnt->result;
205 device->complete=1;
206 SCpnt->request.dev=-1;
207 wake_up(&scsi_generics[dev].read_wait);
208 }
209
210 static int sg_write(struct inode *inode,struct file *filp,char *buf,int count)
211 {
212 int dev=MINOR(inode->i_rdev);
213 Scsi_Cmnd *SCpnt;
214 int bsize,size,amt,i;
215 unsigned char cmnd[MAX_COMMAND_SIZE];
216 struct scsi_generic *device=&scsi_generics[dev];
217
218 if ((i=verify_area(VERIFY_READ,buf,count)))
219 return i;
220 if (count<sizeof(struct sg_header))
221 return -EIO;
222
223 while(device->pending)
224 {
225 if (filp->f_flags & O_NONBLOCK)
226 return -EWOULDBLOCK;
227 #ifdef DEBUG
228 printk("sg_write: sleeping on pending request\n");
229 #endif
230 interruptible_sleep_on(&device->write_wait);
231 if (current->signal & ~current->blocked)
232 return -ERESTARTSYS;
233 }
234 device->pending=1;
235 device->complete=0;
236 memcpy_fromfs(&device->header,buf,sizeof(struct sg_header));
237
238 device->header.pack_len=count;
239 buf+=sizeof(struct sg_header);
240 bsize=(device->header.pack_len>device->header.reply_len) ? device->header.pack_len : device->header.reply_len;
241 bsize-=sizeof(struct sg_header);
242 amt=bsize;
243 if (!bsize)
244 bsize++;
245 bsize=(bsize+511) & ~511;
246 if ((bsize<0) || !(device->buff=sg_malloc(device->buff_len=bsize)))
247 {
248 device->pending=0;
249 wake_up(&device->write_wait);
250 return -ENOMEM;
251 }
252 #ifdef DEBUG
253 printk("allocating device\n");
254 #endif
255 if (!(SCpnt=allocate_device(NULL,device->device, !(filp->f_flags & O_NONBLOCK))))
256 {
257 device->pending=0;
258 wake_up(&device->write_wait);
259 sg_free(device->buff,device->buff_len);
260 return -EWOULDBLOCK;
261 }
262 #ifdef DEBUG
263 printk("device allocated\n");
264 #endif
265
266 SCpnt->request.dev=dev;
267 SCpnt->sense_buffer[0]=0;
268 size=COMMAND_SIZE(get_fs_byte(buf));
269 memcpy_fromfs(cmnd,buf,size);
270 buf+=size;
271 memcpy_fromfs(device->buff,buf,device->header.pack_len-size-sizeof(struct sg_header));
272 cmnd[1]=(cmnd[1] & 0x1f) | (device->device->lun<<5);
273 #ifdef DEBUG
274 printk("do cmd\n");
275 #endif
276 scsi_do_cmd (SCpnt,(void *) cmnd,
277 (void *) device->buff,amt,sg_command_done,device->timeout,SG_DEFAULT_RETRIES);
278 #ifdef DEBUG
279 printk("done cmd\n");
280 #endif
281 return count;
282 }
283
284 static struct file_operations sg_fops = {
285 NULL,
286 sg_read,
287 sg_write,
288 NULL,
289 NULL,
290 sg_ioctl,
291 NULL,
292 sg_open,
293 sg_close,
294 NULL
295 };
296
297
298
299 unsigned long sg_init(unsigned long mem_start, unsigned long mem_end)
300 {
301 if (register_chrdev(SCSI_GENERIC_MAJOR,"sg",&sg_fops))
302 {
303 printk("Unable to get major %d for generic SCSI device\n",
304 SCSI_GENERIC_MAJOR);
305 return mem_start;
306 }
307 if (NR_SG == 0) return mem_start;
308
309 #ifdef DEBUG
310 printk("sg: Init generic device.\n");
311 #endif
312
313 #ifdef SG_BIG_BUFF
314 big_buff= (char *) mem_start;
315 mem_start+=SG_BIG_BUFF;
316 #endif
317 return mem_start;
318 }
319
320 void sg_init1()
321 {
322 scsi_generics = (struct scsi_generic *)
323 scsi_init_malloc(MAX_SG * sizeof(struct scsi_generic));
324 };
325
326 void sg_attach(Scsi_Device * SDp)
327 {
328 if(NR_SG >= MAX_SG)
329 panic ("scsi_devices corrupt (sg)");
330 scsi_generics[NR_SG].device=SDp;
331 scsi_generics[NR_SG].users=0;
332 scsi_generics[NR_SG].generic_wait=NULL;
333 scsi_generics[NR_SG].read_wait=NULL;
334 scsi_generics[NR_SG].write_wait=NULL;
335 scsi_generics[NR_SG].exclude=0;
336 scsi_generics[NR_SG].pending=0;
337 scsi_generics[NR_SG].timeout=SG_DEFAULT_TIMEOUT;
338 NR_SG++;
339 };