|
|
1.1 root 1: /*
2: * sr.c by David Giller
3: *
4: * adapted from:
5: * sd.c Copyright (C) 1992 Drew Eckhardt
6: * Linux scsi disk driver by
7: * Drew Eckhardt
8: *
9: * <[email protected]>
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:
21: #include "scsi.h"
22: #include "sr.h"
23:
24: #define MAJOR_NR 11
25:
26: #include "../blk.h"
27:
28: #define MAX_RETRIES 0
29: #define SR_TIMEOUT 200
30:
31: int NR_SR=0;
32: Scsi_CD scsi_CDs[MAX_SR];
33: static int sr_sizes[MAX_SR << 4];
34: static unsigned long int this_count;
35:
36: struct block_buffer
37: {
38: unsigned block;
39: unsigned start;
40: unsigned use:1;
41: unsigned char buffer[2048];
42: };
43:
44: static struct block_buffer bb[MAX_SR];
45:
46: static int sr_result;
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: }
56:
57: static struct file_operations sr_fops =
58: {
59: NULL, /* lseek - default */
60: block_read, /* read - general block-dev read */
61: block_write, /* write - general block-dev write */
62: NULL, /* readdir - bad */
63: NULL, /* select */
64: sr_ioctl, /* ioctl */
65: sr_open, /* no special open code */
66: sr_release /* release */
67: };
68:
69: /*
70: * The sense_buffer is where we put data for all mode sense commands performed.
71: */
72:
73: static unsigned char sense_buffer[255];
74:
75: /*
76: * rw_intr is the interrupt routine for the device driver. It will be notified on the
77: * end of a SCSI read / write, and will take on of several actions based on success or failure.
78: */
79:
80: static void rw_intr (int host, int result)
81: {
82: if (SR_HOST != host)
83: {
84: panic ("sr.o : rw_intr() recieving interrupt for different host.");
85: }
86:
87: if (!result)
88: { /* No error */
89: if (bb[DEVICE_NR(CURRENT->dev)].use)
90: {
91: memcpy((char *)CURRENT->buffer,
92: bb[DEVICE_NR(CURRENT->dev)].buffer +
93: (bb[DEVICE_NR(CURRENT->dev)].start << 9),
94: this_count << 9);
95: }
96:
97: CURRENT->nr_sectors -= this_count;
98:
99: #ifdef DEBUG
100: printk("(%x %x %x) ",CURRENT->bh, CURRENT->nr_sectors,
101: this_count);
102: #endif
103: if (CURRENT->nr_sectors)
104: {
105: CURRENT->sector += this_count;
106: CURRENT->errors = 0;
107: if (!CURRENT->bh)
108: {
109: (char *) CURRENT->buffer += this_count << 9;
110: } else {
111: end_request(1);
112: do_sr_request();
113: }
114: }
115: else
116: {
117: end_request(1); /* All done */
118: do_sr_request();
119: }
120: }
121:
122: /* We only come through here if we have an error of some kind */
123:
124: if (driver_byte(result) != 0) {
125: bb[DEVICE_NR(CURRENT->dev)].block = -1;
126:
127: if ((sense_buffer[0] & 0x7f) == 0x70) {
128: if ((sense_buffer[2] & 0xf) == UNIT_ATTENTION) {
129: /* detected disc change. set a bit and quietly refuse */
130: /* further access. */
131:
132: scsi_CDs[DEVICE_NR(CURRENT->dev)].changed = 1;
133: end_request(0);
134: return;
135: }
136: }
137:
138: if (sense_buffer[2] == ILLEGAL_REQUEST) {
139: printk("CD-ROM error: Drive reports ILLEGAL REQUEST.\n");
140: if (scsi_CDs[DEVICE_NR(CURRENT->dev)].ten) {
141: scsi_CDs[DEVICE_NR(CURRENT->dev)].ten = 0;
142: do_sr_request();
143: result = 0;
144: return;
145: } else {
146: end_request(0);
147: do_sr_request(); /* Do next request */
148: return;
149: }
150:
151: }
152:
153: if (sense_buffer[2] == NOT_READY) {
154: printk("CDROM not ready. Make sure you have a disc in the drive.\n");
155: end_request(0);
156: do_sr_request(); /* Do next request */
157: return;
158: };
159: }
160:
161: /* We only get this far if we have an error we have not recognized */
162: if(result) {
163: printk("SCSI CD error : host %d id %d lun %d return code = %03x\n",
164: scsi_CDs[DEVICE_NR(CURRENT->dev)].device->host_no,
165: scsi_CDs[DEVICE_NR(CURRENT->dev)].device->id,
166: scsi_CDs[DEVICE_NR(CURRENT->dev)].device->lun,
167: result);
168:
169: if (status_byte(result) == CHECK_CONDITION)
170: printk("\tSense class %x, sense error %x, extended sense %x\n",
171: sense_class(sense_buffer[0]),
172: sense_error(sense_buffer[0]),
173: sense_buffer[2] & 0xf);
174:
175: end_request(0);
176: do_sr_request();
177: }
178: }
179:
180: static int sr_open(struct inode * inode, struct file * filp)
181: {
182: if (filp->f_mode)
183: check_disk_change(inode->i_rdev);
184: return 0;
185: }
186:
187: /*
188: * do_sr_request() is the request handler function for the sr driver. Its function in life
189: * is to take block device requests, and translate them to SCSI commands.
190: */
191:
192: void do_sr_request (void)
193: {
194: unsigned int dev, block, realcount;
195: unsigned char cmd[10], *buffer, tries;
196:
197: tries = 2;
198:
199: repeat:
200: INIT_REQUEST;
201: dev = MINOR(CURRENT->dev);
202: block = CURRENT->sector;
203:
204: bb[dev].start = block % 4;
205: block = block / 4;
206:
207: if (dev >= NR_SR)
208: {
209: /* printk("CD-ROM request error: invalid device.\n"); */
210: end_request(0);
211: tries = 2;
212: goto repeat;
213: }
214:
215: if (!scsi_CDs[dev].use)
216: {
217: /* printk("CD-ROM request error: device marked not in use.\n"); */
218: end_request(0);
219: tries = 2;
220: goto repeat;
221: }
222:
223: if (scsi_CDs[dev].changed)
224: {
225: /*
226: * quietly refuse to do anything to a changed disc until the changed bit has been reset
227: */
228: /* printk("CD-ROM has been changed. Prohibiting further I/O.\n"); */
229: end_request(0);
230: tries = 2;
231: goto repeat;
232: }
233:
234: if (!CURRENT->bh)
235: this_count = CURRENT->nr_sectors;
236: else
237: this_count = (CURRENT->bh->b_size / 512);
238:
239: if (bb[dev].start)
240: {
241: bb[dev].use = 1;
242:
243: this_count = ((this_count > 4 - bb[dev].start) ?
244: (4 - bb[dev].start) : (this_count));
245:
246: if (bb[dev].block == block)
247: {
248: rw_intr(SR_HOST, 0);
249: return;
250: }
251:
252: buffer = bb[dev].buffer;
253: bb[dev].block = block;
254: }
255: else if (this_count < 4)
256: {
257: bb[dev].use = 1;
258:
259: if (bb[dev].block == block)
260: {
261: rw_intr(SR_HOST, 0);
262: return;
263: }
264:
265: buffer = bb[dev].buffer;
266: bb[dev].block = block;
267: }
268: else
269: {
270: this_count -= this_count % 4;
271: buffer = CURRENT->buffer;
272: bb[dev].use = 0;
273: }
274:
275: realcount = (this_count + 3) / 4;
276:
277: switch (CURRENT->cmd)
278: {
279: case WRITE:
280: end_request(0);
281: goto repeat;
282: break;
283: case READ :
284: cmd[0] = READ_6;
285: break;
286: default :
287: printk ("Unknown sr command %d\r\n", CURRENT->cmd);
288: panic("");
289: }
290:
291: cmd[1] = (SR_LUN << 5) & 0xe0;
292:
293: if (((realcount > 0xff) || (block > 0x1fffff)) && scsi_CDs[dev].ten)
294: {
295: if (realcount > 0xffff)
296: {
297: realcount = 0xffff;
298: this_count = realcount * 4;
299: }
300:
301: cmd[0] += READ_10 - READ_6 ;
302: cmd[2] = (unsigned char) (block >> 24) & 0xff;
303: cmd[3] = (unsigned char) (block >> 16) & 0xff;
304: cmd[4] = (unsigned char) (block >> 8) & 0xff;
305: cmd[5] = (unsigned char) block & 0xff;
306: cmd[6] = cmd[9] = 0;
307: cmd[7] = (unsigned char) (realcount >> 8) & 0xff;
308: cmd[8] = (unsigned char) realcount & 0xff;
309: }
310: else
311: {
312: if (realcount > 0xff)
313: {
314: realcount = 0xff;
315: this_count = realcount * 4;
316: }
317:
318: cmd[1] |= (unsigned char) ((block >> 16) & 0x1f);
319: cmd[2] = (unsigned char) ((block >> 8) & 0xff);
320: cmd[3] = (unsigned char) block & 0xff;
321: cmd[4] = (unsigned char) realcount;
322: cmd[5] = 0;
323: }
324:
325: scsi_do_cmd (SR_HOST, SR_ID, (void *) cmd, buffer, realcount << 11,
326: rw_intr, SR_TIMEOUT, sense_buffer, MAX_RETRIES);
327: }
328:
329: void sr_init(void)
330: {
331: int i;
332:
333: for (i = 0; i < NR_SR; ++i)
334: {
335: scsi_CDs[i].capacity = 0x1fffff;
336: scsi_CDs[i].sector_size = 2048;
337: scsi_CDs[i].use = 1;
338: scsi_CDs[i].ten = 1;
339: scsi_CDs[i].remap = 1;
340: scsi_CDs[i].changed = 0;
341: sr_sizes[i] = scsi_CDs[i].capacity;
342:
343: bb[i].block = -1;
344: }
345:
346: blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
347: blk_size[MAJOR_NR] = sr_sizes;
348: blkdev_fops[MAJOR_NR] = &sr_fops;
349: }
350: #endif
351:
352:
353:
354:
355:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.