|
|
1.1 root 1: #include <linux/config.h>
2: #ifdef CONFIG_BLK_DEV_SR
3: #include <linux/kernel.h>
4: #include <linux/sched.h>
5: #include <linux/fs.h>
6: #include <asm/segment.h>
7: #include <linux/errno.h>
8:
9: #include "../blk.h"
10: #include "scsi.h"
11: #include "sr.h"
12:
13: #include <linux/cdrom.h>
14:
15: #define IOCTL_RETRIES 3
16: /* The CDROM is fairly slow, so we need a little extra time */
17: #define IOCTL_TIMEOUT 200
18:
19: static u_char sr_cmd[10];
20: static u_char data_buffer[255];
21: static u_char sense_buffer[255];
22: static int the_result;
23:
24: static struct wait_queue *sr_cmd_wait = NULL; /* For waiting until cmd done*/
25: static u_char sr_lock = 0; /* To make sure that only one person is doing
26: an ioctl at one time */
27: static int target;
28:
29: extern int scsi_ioctl (int dev, int cmd, void *arg);
30:
31: static void lock_sr_ioctl( void )
32: {
33: /* We do not use wakeup here because there could conceivably be three
34: processes trying to get at the drive simultaneously, and we would
35: be screwed if that happened.
36: */
37:
38: while (sr_lock);
39: sr_lock = 1;
40: }
41:
42: static void unlock_sr_ioctl( void )
43: {
44: sr_lock = 0;
45: }
46:
47: static void sr_ioctl_done( int host, int result )
48: {
49: the_result = result;
50: wake_up(&sr_cmd_wait);
51: }
52:
53: /* We do our own retries because we want to know what the specific
54: error code is. Normally the UNIT_ATTENTION code will automatically
55: clear after one error */
56:
57: static int do_ioctl( void )
58: {
59: int retries = IOCTL_RETRIES;
60: retry:
61:
62: the_result = -1;
63:
64: scsi_do_cmd(scsi_CDs[target].device->host_no, scsi_CDs[target].device->id,
65: (void *) sr_cmd, (void *) data_buffer, 255, sr_ioctl_done,
66: IOCTL_TIMEOUT, (void *) sense_buffer, 0);
67:
68: while (the_result < 0) sleep_on(&sr_cmd_wait);
69:
70: if(driver_byte(the_result) != 0 &&
71: (sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
72: scsi_CDs[target].changed = 1;
73: printk("Disc change detected.\n");
74: };
75:
76: if (the_result && retries)
77: {
78: retries--;
79: goto retry;
80: }
81:
82: /* Minimal error checking. Ignore cases we know about, and report the rest. */
83: if(driver_byte(the_result) != 0)
84: switch(sense_buffer[2] & 0xf) {
85: case UNIT_ATTENTION:
86: scsi_CDs[target].changed = 1;
87: printk("Disc change detected.\n");
88: break;
89: case NOT_READY: /* This happens if there is no disc in drive */
90: printk("CDROM not ready. Make sure there is a disc in the drive.\n");
91: break;
92: case ILLEGAL_REQUEST:
93: printk("CDROM (ioctl) reports ILLEGAL REQUEST.\n");
94: break;
95: default:
96: printk("SCSI CD error: host %d id %d lun %d return code = %03x\n",
97: scsi_CDs[target].device->host_no,
98: scsi_CDs[target].device->id,
99: scsi_CDs[target].device->lun,
100: the_result);
101: printk("\tSense class %x, sense error %x, extended sense %x\n",
102: sense_class(sense_buffer[0]),
103: sense_error(sense_buffer[0]),
104: sense_buffer[2] & 0xf);
105:
106: };
107: return the_result;
108: }
109:
110: /*
111: * This function checks to see if the media has been changed in the
112: * CDROM drive. It is possible that we have already sensed a change,
113: * or the drive may have sensed one and not yet reported it. We must
114: * be ready for either case. This function always reports the current
115: * value of the changed bit. If flag is 0, then the changed bit is reset.
116: * This function could be done as an ioctl, but we would need to have
117: * an inode for that to work, and we do not always have one.
118: */
119:
120: int check_cdrom_media_change(int full_dev, int flag){
121: int retval;
122:
123: lock_sr_ioctl();
124:
125: target = MINOR(full_dev);
126:
127: if (target >= NR_SR) {
128: printk("CD-ROM request error: invalid device.\n");
129: unlock_sr_ioctl();
130: return 0;
131: };
132:
133: sr_cmd[0] = TEST_UNIT_READY;
134: sr_cmd[1] = (scsi_CDs[target].device->lun << 5) & 0xe0;
135: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = sr_cmd[5] = 0;
136:
137: retval = do_ioctl();
138:
139: if(retval){ /* Unable to test, unit probably not ready. This usually
140: means there is no disc in the drive. Mark as changed,
141: and we will figure it out later once the drive is
142: available again. */
143:
144: scsi_CDs[target].changed = 1;
145: unlock_sr_ioctl();
146: return 1; /* This will force a flush, if called from
147: check_disk_change */
148: };
149:
150: retval = scsi_CDs[target].changed;
151: if(!flag) scsi_CDs[target].changed = 0;
152: unlock_sr_ioctl();
153:
154: return retval;
155: }
156:
157: int sr_ioctl(struct inode * inode, struct file * file, unsigned long cmd, unsigned long arg)
158: {
159: int dev = inode->i_rdev;
160: int result;
161:
162: target = MINOR(dev);
163:
164: switch (cmd)
165: {
166: /* linux-specific */
167: case CDROMDOORUNLOCK:
168: lock_sr_ioctl();
169:
170: sr_cmd[0] = ALLOW_MEDIUM_REMOVAL;
171: sr_cmd[1] = scsi_CDs[target].device->lun << 5;
172: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
173: sr_cmd[4] = SR_REMOVAL_ALLOW;
174:
175: result = do_ioctl();
176:
177: unlock_sr_ioctl();
178: return result;
179:
180: case CDROMDOORLOCK:
181: lock_sr_ioctl();
182:
183: sr_cmd[0] = ALLOW_MEDIUM_REMOVAL;
184: sr_cmd[1] = scsi_CDs[target].device->lun << 5;
185: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
186: sr_cmd[4] = SR_REMOVAL_PREVENT;
187:
188: result = do_ioctl();
189:
190: unlock_sr_ioctl();
191: return result;
192:
193: /* Sun-compatible */
194: case CDROMPAUSE:
195: lock_sr_ioctl();
196:
197: sr_cmd[0] = SCMD_PAUSE_RESUME;
198: sr_cmd[1] = scsi_CDs[target].device->lun << 5;
199: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
200: sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
201: sr_cmd[8] = 1;
202: sr_cmd[9] = 0;
203:
204: result = do_ioctl();
205:
206: unlock_sr_ioctl();
207: return result;
208:
209: case CDROMRESUME:
210: lock_sr_ioctl();
211:
212: sr_cmd[0] = SCMD_PAUSE_RESUME;
213: sr_cmd[1] = scsi_CDs[target].device->lun << 5;
214: sr_cmd[2] = sr_cmd[3] = sr_cmd[4] = 0;
215: sr_cmd[5] = sr_cmd[6] = sr_cmd[7] = 0;
216: sr_cmd[8] = 0;
217: sr_cmd[9] = 0;
218:
219: result = do_ioctl();
220:
221: unlock_sr_ioctl();
222: return result;
223:
224: case CDROMPLAYMSF:
225: {
226: struct cdrom_msf msf;
227: lock_sr_ioctl();
228:
229: memcpy_fromfs(&msf, (void *) arg, sizeof(msf));
230:
231: sr_cmd[0] = SCMD_PLAYAUDIO_MSF;
232: sr_cmd[1] = scsi_CDs[target].device->lun << 5;
233: sr_cmd[2] = 0;
234: sr_cmd[3] = msf.cdmsf_min0;
235: sr_cmd[4] = msf.cdmsf_sec0;
236: sr_cmd[5] = msf.cdmsf_frame0;
237: sr_cmd[6] = msf.cdmsf_min1;
238: sr_cmd[7] = msf.cdmsf_sec1;
239: sr_cmd[8] = msf.cdmsf_frame1;
240: sr_cmd[9] = 0;
241:
242: result = do_ioctl();
243:
244: unlock_sr_ioctl();
245: return result;
246: }
247:
248: case CDROMPLAYTRKIND:
249: {
250: struct cdrom_ti ti;
251: lock_sr_ioctl();
252:
253: memcpy_fromfs(&ti, (void *) arg, sizeof(ti));
254:
255: sr_cmd[0] = SCMD_PLAYAUDIO_TI;
256: sr_cmd[1] = scsi_CDs[target].device->lun << 5;
257: sr_cmd[2] = 0;
258: sr_cmd[3] = 0;
259: sr_cmd[4] = ti.cdti_trk0;
260: sr_cmd[5] = ti.cdti_ind0;
261: sr_cmd[6] = 0;
262: sr_cmd[7] = ti.cdti_trk1;
263: sr_cmd[8] = ti.cdti_ind1;
264: sr_cmd[9] = 0;
265:
266: result = do_ioctl();
267:
268: unlock_sr_ioctl();
269: return result;
270: }
271:
272: case CDROMREADTOCHDR:
273: return -EINVAL;
274: case CDROMREADTOCENTRY:
275: return -EINVAL;
276:
277: case CDROMSTOP:
278: lock_sr_ioctl();
279:
280: sr_cmd[0] = START_STOP;
281: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
282: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
283: sr_cmd[4] = 0;
284:
285: result = do_ioctl();
286:
287: unlock_sr_ioctl();
288: return result;
289:
290: case CDROMSTART:
291: lock_sr_ioctl();
292:
293: sr_cmd[0] = START_STOP;
294: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
295: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
296: sr_cmd[4] = 1;
297:
298: result = do_ioctl();
299:
300: unlock_sr_ioctl();
301: return result;
302:
303: case CDROMEJECT:
304: lock_sr_ioctl();
305:
306: sr_cmd[0] = START_STOP;
307: sr_cmd[1] = ((scsi_CDs[target].device->lun) << 5) | 1;
308: sr_cmd[2] = sr_cmd[3] = sr_cmd[5] = 0;
309: sr_cmd[4] = 0x02;
310:
311: result = do_ioctl();
312:
313: unlock_sr_ioctl();
314: return result;
315:
316: case CDROMVOLCTRL:
317: return -EINVAL;
318: case CDROMSUBCHNL:
319: return -EINVAL;
320: case CDROMREADMODE2:
321: return -EINVAL;
322: case CDROMREADMODE1:
323: return -EINVAL;
324:
325: RO_IOCTLS(dev,arg);
326: default:
327: return scsi_ioctl(scsi_CDs[target].device,cmd,(void *) arg);
328: }
329: }
330:
331: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.