This source file includes following definitions.
- sr_release
- check_cdrom_media_change
- rw_intr
- sr_open
- do_sr_request
- sr_init
1
2
3
4
5
6
7
8
9
10
11
12 #include <linux/config.h>
13
14 #ifdef CONFIG_BLK_DEV_SR
15
16 #include <linux/fs.h>
17 #include <linux/kernel.h>
18 #include <linux/sched.h>
19 #include <linux/string.h>
20 #include <linux/errno.h>
21
22 #include "scsi.h"
23 #include "sr.h"
24 #include "scsi_ioctl.h"
25
26 #define MAJOR_NR 11
27
28 #include "../blk.h"
29
30 #define MAX_RETRIES 0
31 #define SR_TIMEOUT 200
32
33 int NR_SR=0;
34 Scsi_CD scsi_CDs[MAX_SR];
35 static int sr_sizes[MAX_SR << 4];
36 static unsigned long int this_count;
37
38 struct block_buffer
39 {
40 unsigned block;
41 unsigned start;
42 unsigned use:1;
43 unsigned char buffer[2048];
44 };
45
46 static struct block_buffer * bb;
47
48 static int sr_open(struct inode *, struct file *);
49
50 extern int sr_ioctl(struct inode *, struct file *, unsigned int, unsigned int);
51
52 static void sr_release(struct inode * inode, struct file * file)
53 {
54 sync_dev(inode->i_rdev);
55 if(! --scsi_CDs[MINOR(inode->i_rdev)].device->access_count)
56 sr_ioctl(inode, NULL, SCSI_IOCTL_DOORUNLOCK, 0);
57 }
58
59 static struct file_operations sr_fops =
60 {
61 NULL,
62 block_read,
63 block_write,
64 NULL,
65 NULL,
66 sr_ioctl,
67 NULL,
68 sr_open,
69 sr_release
70 };
71
72
73
74
75
76
77
78
79
80
81
82 int check_cdrom_media_change(int full_dev, int flag){
83 int retval, target;
84 struct inode inode;
85
86 target = MINOR(full_dev);
87
88 if (target >= NR_SR) {
89 printk("CD-ROM request error: invalid device.\n");
90 return 0;
91 };
92
93 inode.i_rdev = full_dev;
94 retval = sr_ioctl(&inode, NULL, SCSI_IOCTL_TEST_UNIT_READY, 0);
95
96 if(retval){
97
98
99
100
101 scsi_CDs[target].device->changed = 1;
102 return 1;
103
104 };
105
106 retval = scsi_CDs[target].device->changed;
107 if(!flag) scsi_CDs[target].device->changed = 0;
108 return retval;
109 }
110
111
112
113
114 static unsigned char sense_buffer[255];
115
116
117
118
119
120
121 static void rw_intr (int host, int result)
122 {
123 if (SR_HOST != host)
124 {
125 panic ("sr.o : rw_intr() recieving interrupt for different host.");
126 }
127
128 if (!result)
129 {
130 if (bb[DEVICE_NR(CURRENT->dev)].use)
131 {
132 memcpy((char *)CURRENT->buffer,
133 bb[DEVICE_NR(CURRENT->dev)].buffer +
134 (bb[DEVICE_NR(CURRENT->dev)].start << 9),
135 this_count << 9);
136 }
137
138 CURRENT->nr_sectors -= this_count;
139
140 #ifdef DEBUG
141 printk("(%x %x %x) ",CURRENT->bh, CURRENT->nr_sectors,
142 this_count);
143 #endif
144 if (CURRENT->nr_sectors)
145 {
146 CURRENT->sector += this_count;
147 CURRENT->errors = 0;
148 if (!CURRENT->bh)
149 {
150 (char *) CURRENT->buffer += this_count << 9;
151 } else {
152 end_request(1);
153 do_sr_request();
154 }
155 }
156 else
157 {
158 end_request(1);
159 do_sr_request();
160 }
161 }
162
163
164
165 if (driver_byte(result) != 0) {
166 bb[DEVICE_NR(CURRENT->dev)].block = -1;
167
168 if ((sense_buffer[0] & 0x7f) == 0x70) {
169 if ((sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
170
171
172
173 scsi_CDs[DEVICE_NR(CURRENT->dev)].device->changed = 1;
174 end_request(0);
175 do_sr_request();
176 return;
177 }
178 }
179
180 if (sense_buffer[2] == ILLEGAL_REQUEST) {
181 printk("CD-ROM error: Drive reports ILLEGAL REQUEST.\n");
182 if (scsi_CDs[DEVICE_NR(CURRENT->dev)].ten) {
183 scsi_CDs[DEVICE_NR(CURRENT->dev)].ten = 0;
184 do_sr_request();
185 result = 0;
186 return;
187 } else {
188 printk("CD-ROM error: Drive reports %d.\n", sense_buffer[2]); end_request(0);
189 do_sr_request();
190 return;
191 }
192
193 }
194
195 if (sense_buffer[2] == NOT_READY) {
196 printk("CDROM not ready. Make sure you have a disc in the drive.\n");
197 end_request(0);
198 do_sr_request();
199 return;
200 };
201 }
202
203
204 if(result) {
205 printk("SCSI CD error : host %d id %d lun %d return code = %03x\n",
206 scsi_CDs[DEVICE_NR(CURRENT->dev)].device->host_no,
207 scsi_CDs[DEVICE_NR(CURRENT->dev)].device->id,
208 scsi_CDs[DEVICE_NR(CURRENT->dev)].device->lun,
209 result);
210
211 if (status_byte(result) == CHECK_CONDITION)
212 printk("\tSense class %x, sense error %x, extended sense %x\n",
213 sense_class(sense_buffer[0]),
214 sense_error(sense_buffer[0]),
215 sense_buffer[2] & 0xf);
216
217 end_request(0);
218 do_sr_request();
219 }
220 }
221
222 static int sr_open(struct inode * inode, struct file * filp)
223 {
224 if(MINOR(inode->i_rdev) >= NR_SR ||
225 !scsi_CDs[MINOR(inode->i_rdev)].device) return -EACCES;
226
227 check_disk_change(inode->i_rdev);
228
229 if(!scsi_CDs[MINOR(inode->i_rdev)].device->access_count++)
230 sr_ioctl(inode, NULL, SCSI_IOCTL_DOORLOCK, 0);
231 return 0;
232 }
233
234
235
236
237
238
239 void do_sr_request (void)
240 {
241 unsigned int dev, block, realcount;
242 unsigned char cmd[10], *buffer, tries;
243
244 tries = 2;
245
246 repeat:
247 INIT_REQUEST;
248 dev = MINOR(CURRENT->dev);
249 block = CURRENT->sector;
250
251 bb[dev].start = block % 4;
252 block = block / 4;
253
254 if (dev >= NR_SR)
255 {
256
257 end_request(0);
258 tries = 2;
259 goto repeat;
260 }
261
262 if (!scsi_CDs[dev].use)
263 {
264
265 end_request(0);
266 tries = 2;
267 goto repeat;
268 }
269
270 if (scsi_CDs[dev].device->changed)
271 {
272
273
274
275
276 end_request(0);
277 tries = 2;
278 goto repeat;
279 }
280
281 if (!CURRENT->bh)
282 this_count = CURRENT->nr_sectors;
283 else
284 this_count = (CURRENT->bh->b_size / 512);
285
286 if (bb[dev].start)
287 {
288 bb[dev].use = 1;
289
290 this_count = ((this_count > 4 - bb[dev].start) ?
291 (4 - bb[dev].start) : (this_count));
292
293 if (bb[dev].block == block)
294 {
295 rw_intr(SR_HOST, 0);
296 return;
297 }
298
299 buffer = bb[dev].buffer;
300 bb[dev].block = block;
301 }
302 else if (this_count < 4)
303 {
304 bb[dev].use = 1;
305
306 if (bb[dev].block == block)
307 {
308 rw_intr(SR_HOST, 0);
309 return;
310 }
311
312 buffer = bb[dev].buffer;
313 bb[dev].block = block;
314 }
315 else
316 {
317 this_count -= this_count % 4;
318 buffer = CURRENT->buffer;
319 bb[dev].use = 0;
320 }
321
322 realcount = (this_count + 3) / 4;
323
324 switch (CURRENT->cmd)
325 {
326 case WRITE:
327 end_request(0);
328 goto repeat;
329 break;
330 case READ :
331 cmd[0] = READ_6;
332 break;
333 default :
334 printk ("Unknown sr command %d\r\n", CURRENT->cmd);
335 panic("");
336 }
337
338 cmd[1] = (SR_LUN << 5) & 0xe0;
339
340 if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten)
341 {
342 if (realcount > 0xffff)
343 {
344 realcount = 0xffff;
345 this_count = realcount * 4;
346 }
347
348 cmd[0] += READ_10 - READ_6 ;
349 cmd[2] = (unsigned char) (block >> 24) & 0xff;
350 cmd[3] = (unsigned char) (block >> 16) & 0xff;
351 cmd[4] = (unsigned char) (block >> 8) & 0xff;
352 cmd[5] = (unsigned char) block & 0xff;
353 cmd[6] = cmd[9] = 0;
354 cmd[7] = (unsigned char) (realcount >> 8) & 0xff;
355 cmd[8] = (unsigned char) realcount & 0xff;
356 }
357 else
358 {
359 if (realcount > 0xff)
360 {
361 realcount = 0xff;
362 this_count = realcount * 4;
363 }
364
365 cmd[1] |= (unsigned char) ((block >> 16) & 0x1f);
366 cmd[2] = (unsigned char) ((block >> 8) & 0xff);
367 cmd[3] = (unsigned char) block & 0xff;
368 cmd[4] = (unsigned char) realcount;
369 cmd[5] = 0;
370 }
371
372 scsi_do_cmd (SR_HOST, SR_ID, (void *) cmd, buffer, realcount << 11,
373 rw_intr, SR_TIMEOUT, sense_buffer, MAX_RETRIES);
374 }
375
376 unsigned long sr_init(unsigned long memory_start, unsigned long memory_end)
377 {
378 int i;
379
380 bb = (struct block_buffer *) memory_start;
381 memory_start += NR_SR * sizeof(struct block_buffer);
382
383 for (i = 0; i < NR_SR; ++i)
384 {
385 scsi_CDs[i].capacity = 0x1fffff;
386 scsi_CDs[i].sector_size = 2048;
387 scsi_CDs[i].use = 1;
388 scsi_CDs[i].ten = 1;
389 scsi_CDs[i].remap = 1;
390 sr_sizes[i] = scsi_CDs[i].capacity;
391
392 bb[i].block = -1;
393 }
394
395 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
396 blk_size[MAJOR_NR] = sr_sizes;
397 blkdev_fops[MAJOR_NR] = &sr_fops;
398 return memory_start;
399 }
400 #endif
401
402
403
404
405