This source file includes following definitions.
- optFlags
- sten_low
- dten_low
- sleep_timer
- sleep_status
- sleep_sten_low
- sleep_dten_low
- optSendCmd
- optSendParams
- optGetExecStatus
- optSleepTillExecStatus
- optStatus
- optGetData
- optReadData
- optFlushData
- optResetDrive
- optCmd
- optPlayCmd
- optReadCmd
- bin2bcd
- hsg2msf
- bcd2bin
- msf2hsg
- optGetStatus
- optGetQChannelInfo
- optGetDiskInfo
- optGetToc
- optUpdateToc
- opt_invalidate_buffers
- opt_transfer
- opt_poll
- do_optcd_request
- opt_ioctl
- opt_open
- opt_release
- version_ok
- optcd_setup
- optcd_init
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43 #include <linux/major.h>
44 #include <linux/config.h>
45
46 #ifdef MODULE
47 # include <linux/module.h>
48 # include <linux/version.h>
49 # ifndef CONFIG_MODVERSIONS
50 char kernel_version[]= UTS_RELEASE;
51 # endif
52 #else
53 # define MOD_INC_USE_COUNT
54 # define MOD_DEC_USE_COUNT
55 #endif
56
57 #include <linux/errno.h>
58 #include <linux/mm.h>
59 #include <linux/fs.h>
60 #include <linux/timer.h>
61 #include <linux/kernel.h>
62 #include <linux/cdrom.h>
63 #include <linux/ioport.h>
64 #include <asm/io.h>
65
66 #define MAJOR_NR OPTICS_CDROM_MAJOR
67
68 # include "blk.h"
69 #define optcd_port optcd
70 # include <linux/optcd.h>
71
72 static short optcd_port = OPTCD_PORTBASE;
73
74
75 inline static int optFlags(void) {
76 return inb(STATUS_PORT) & FL_STDT;
77 }
78
79
80 static int sten_low(void) {
81 int no_status;
82 unsigned long count = 0;
83 while ((no_status = (optFlags() & FL_STEN)))
84 if (++count >= BUSY_TIMEOUT)
85 break;
86 #ifdef DEBUG_DRIVE_IF
87 if (no_status)
88 printk("optcd: timeout waiting for STEN low\n");
89 else
90 printk("optcd: STEN low after %ld\n", count);
91 #endif
92 return no_status;
93 }
94
95
96 static int dten_low(void) {
97 int no_data;
98 unsigned long count = 0;
99 while ((no_data = (optFlags() & FL_DTEN)))
100 if (++count >= BUSY_TIMEOUT)
101 break;
102 #ifdef DEBUG_DRIVE_IF
103 if (no_data)
104 printk("optcd: timeout waiting for DTEN low\n");
105 else
106 printk("optcd: DTEN low after %ld\n", count);
107 #endif
108 return no_data;
109 }
110
111
112 static int sleep_timeout;
113 static unsigned char sleep_flags;
114 static struct wait_queue *waitq = NULL;
115 static struct timer_list delay_timer = {NULL, NULL, 0, 0, NULL};
116
117
118
119
120 static void sleep_timer(void) {
121 if ((sleep_flags = optFlags()) != FL_STDT) {
122 wake_up(&waitq);
123 return;
124 }
125 if (--sleep_timeout <= 0) {
126 wake_up(&waitq);
127 return;
128 }
129 SET_TIMER(sleep_timer, 1);
130 }
131
132
133
134
135 static int sleep_status(void) {
136 #ifdef DEBUG_DRIVE_IF
137 printk("optcd: sleeping %d on status\n", sleep_timeout);
138 #endif
139 if (sleep_timeout <= 0)
140 return FL_STDT;
141 if ((sleep_flags = optFlags()) == FL_STDT) {
142 SET_TIMER(sleep_timer, 1);
143 sleep_on(&waitq);
144 }
145 #ifdef DEBUG_DRIVE_IF
146 printk("optcd: woken up with %d to go, flags %d\n",
147 sleep_timeout, sleep_flags);
148 #endif
149 return sleep_flags;
150 }
151
152
153 inline static int sleep_sten_low(void) {
154 int flags;
155 sleep_timeout = SLEEP_TIMEOUT;
156 flags = sleep_status();
157 #ifdef DEBUG_DRIVE_IF
158 if (!(flags & FL_DTEN))
159 printk("optcd: DTEN while waiting for STEN\n");
160 #endif
161 return flags & FL_STEN;
162 }
163
164
165 inline static int sleep_dten_low(void) {
166 int flags;
167 sleep_timeout = SLEEP_TIMEOUT;
168 flags = sleep_status();
169 #ifdef DEBUG_DRIVE_IF
170 if (!(flags & FL_STEN))
171 printk("optcd: STEN while waiting for DTEN\n");
172 #endif
173 return flags & FL_DTEN;
174 }
175
176
177 static int optSendCmd(int cmd) {
178 unsigned char ack;
179 #if defined(DEBUG_DRIVE_IF)||defined(DEBUG_COMMANDS)
180 printk("optcd: executing command 0x%02x\n", cmd);
181 #endif
182 outb(HCON_DTS, HCON_PORT);
183 outb(cmd, COMIN_PORT);
184 if (sten_low())
185 return -ERR_IF_CMD_TIMEOUT;
186 ack = inb(DATA_PORT);
187 #ifdef DEBUG_DRIVE_IF
188 printk("optcd: acknowledge code 0x%02x\n", ack);
189 #endif
190 outb(HCON_SDRQB, HCON_PORT);
191 return ack==ST_OP_OK ? 0 : -ack;
192 }
193
194
195 static int optSendParams(struct opt_Play_msf *params) {
196 unsigned char ack;
197 #if defined(DEBUG_DRIVE_IF)||defined(DEBUG_COMMANDS)
198 printk("optcd: params %02x:%02x:%02x %02x:%02x:%02x\n",
199 params->start.min, params->start.sec, params->start.frame,
200 params->end.min, params->end.sec, params->end.frame);
201 #endif
202 outb(params -> start.min, COMIN_PORT);
203 outb(params -> start.sec, COMIN_PORT);
204 outb(params -> start.frame, COMIN_PORT);
205 outb(params -> end.min, COMIN_PORT);
206 outb(params -> end.sec, COMIN_PORT);
207 outb(params -> end.frame, COMIN_PORT);
208 if (sten_low())
209 return -ERR_IF_CMD_TIMEOUT;
210 ack = inb(DATA_PORT);
211 #ifdef DEBUG_DRIVE_IF
212 printk("optcd: acknowledge code 0x%02x\n", ack);
213 #endif
214 return ack==ST_PA_OK ? 0 : -ack;
215 }
216
217
218
219
220 static int optGetExecStatus(void) {
221 unsigned char exec_status;
222 if (sten_low())
223 return -ERR_IF_CMD_TIMEOUT;
224 exec_status = inb(DATA_PORT);
225 #ifdef DEBUG_DRIVE_IF
226 printk("optcd: returned execution status: 0x%02x\n", exec_status);
227 #endif
228 return exec_status;
229 }
230
231
232
233
234 static int optSleepTillExecStatus(void) {
235 unsigned char exec_status;
236 if (sleep_sten_low())
237 return -ERR_IF_CMD_TIMEOUT;
238 exec_status = inb(DATA_PORT);
239 #ifdef DEBUG_DRIVE_IF
240 printk("optcd: returned execution status: 0x%02x\n", exec_status);
241 #endif
242 return exec_status;
243 }
244
245
246 inline static int optStatus(void) {
247 unsigned char status;
248 if (optFlags() & FL_STEN)
249 return -ERR_IF_NOSTAT;
250 status = inb(DATA_PORT);
251 #ifdef DEBUG_DRIVE_IF
252 printk("optcd: read status: 0x%02x\n", status);
253 #endif
254 return status;
255 }
256
257
258 static int optGetData(void) {
259 unsigned char data;
260 if (sten_low())
261 return -ERR_IF_DATA_TIMEOUT;
262 data = inb(DATA_PORT);
263 #ifdef DEBUG_DRIVE_IF
264 printk("optcd: read data: 0x%02x\n", data);
265 #endif
266 return data;
267 }
268
269
270 inline static void optReadData(char *buf, int n) {
271 insb(DATA_PORT, buf, n);
272 }
273
274
275 inline static void optFlushData(void) {
276 while (optFlags() != FL_STDT)
277 inb(DATA_PORT);
278 }
279
280
281 static int optResetDrive(void) {
282 unsigned long count = 0;
283 int flags;
284 #ifdef DEBUG_DRIVE_IF
285 printk("optcd: reset drive\n");
286 #endif
287 outb(0, RESET_PORT);
288 while (++count < RESET_WAIT)
289 inb(DATA_PORT);
290 count = 0;
291 while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
292 if (++count >= BUSY_TIMEOUT)
293 break;
294 #ifdef DEBUG_DRIVE_IF
295 if (flags == FL_RESET)
296 printk("optcd: drive reset\n");
297 else
298 printk("optcd: reset failed\n");
299 #endif
300 if (flags != FL_RESET)
301 return 0;
302 outb(HCON_SDRQB, HCON_PORT);
303 return 1;
304 }
305
306
307
308
309
310 inline static int optCmd(int cmd) {
311 int ack = optSendCmd(cmd);
312 if (ack < 0)
313 return ack;
314 if (cmd < COMFETCH)
315 return optGetExecStatus();
316 else
317 return optSleepTillExecStatus();
318 }
319
320
321 inline static int optPlayCmd(int cmd, struct opt_Play_msf *params) {
322 int ack = optSendCmd(cmd);
323 if (ack < 0)
324 return ack;
325 if ((ack = optSendParams(params)) < 0)
326 return ack;
327 return optSleepTillExecStatus();
328 }
329
330
331
332 inline static int optReadCmd(int cmd, struct opt_Play_msf *params) {
333 int ack = optSendCmd(cmd);
334 if (ack < 0)
335 return ack;
336 return optSendParams(params);
337 }
338
339
340
341
342
343 inline static unsigned char bin2bcd(unsigned char p) {
344 #ifdef DEBUG_CONV
345 if (p > 99)
346 printk("optcd: error bin2bcd %d\n", p);
347 #endif
348 return (p % 10) | ((p / 10) << 4);
349 }
350
351
352 static void hsg2msf(long hsg, struct msf *msf) {
353 hsg += 150;
354 msf -> min = hsg / 4500;
355 hsg %= 4500;
356 msf -> sec = hsg / 75;
357 msf -> frame = hsg % 75;
358 #ifdef DEBUG_CONV
359 if (msf -> min >= 70)
360 printk("optcd: Error hsg2msf address Minutes\n");
361 if (msf -> sec >= 60)
362 printk("optcd: Error hsg2msf address Seconds\n");
363 if (msf -> frame >= 75)
364 printk("optcd: Error hsg2msf address Frames\n");
365 #endif
366 msf -> min = bin2bcd(msf -> min);
367 msf -> sec = bin2bcd(msf -> sec);
368 msf -> frame = bin2bcd(msf -> frame);
369 }
370
371
372 inline static int bcd2bin(unsigned char bcd) {
373 return (bcd >> 4) * 10 + (bcd & 0x0f);
374 }
375
376
377 static long msf2hsg(struct msf *mp) {
378 #ifdef DEBUG_CONV
379 if (mp -> min >= 70)
380 printk("optcd: Error msf2hsg address Minutes\n");
381 if (mp -> sec >= 60)
382 printk("optcd: Error msf2hsg address Seconds\n");
383 if (mp -> frame >= 75)
384 printk("optcd: Error msf2hsg address Frames\n");
385 #endif
386 return bcd2bin(mp -> frame)
387 + bcd2bin(mp -> sec) * 75
388 + bcd2bin(mp -> min) * 4500
389 - 150;
390 }
391
392
393
394
395 static int optAudioStatus = CDROM_AUDIO_NO_STATUS;
396 static char optDiskChanged = 1;
397 static char optTocUpToDate = 0;
398 static struct opt_DiskInfo DiskInfo;
399 static struct opt_Toc Toc[MAX_TRACKS];
400
401
402 static int optGetStatus(void) {
403 int st;
404 if ((st = optCmd(COMIOCTLISTAT)) < 0)
405 return st;
406 if (st == 0xff)
407 return -ERR_IF_NOSTAT;
408 if (((st & ST_MODE_BITS) != ST_M_AUDIO) &&
409 (optAudioStatus == CDROM_AUDIO_PLAY)) {
410 optAudioStatus = CDROM_AUDIO_COMPLETED;
411 }
412 if (st & ST_DSK_CHG) {
413 optDiskChanged = 1;
414 optTocUpToDate = 0;
415 optAudioStatus = CDROM_AUDIO_NO_STATUS;
416 }
417 return st;
418 }
419
420
421
422
423
424 static int optGetQChannelInfo(struct opt_Toc *qp) {
425 int st;
426 #ifdef DEBUG_TOC
427 printk("optcd: starting optGetQChannelInfo\n");
428 #endif
429 if ((st = optGetStatus()) < 0)
430 return st;
431 if ((st = optCmd(COMSUBQ)) < 0)
432 return st;
433 if ((qp -> ctrl_addr = st = optGetData()), st < 0) return st;
434 if ((qp -> track = st = optGetData()), st < 0) return st;
435 if ((qp -> pointIndex = st = optGetData()), st < 0) return st;
436 if ((qp -> trackTime.min = st = optGetData()), st < 0) return st;
437 if ((qp -> trackTime.sec = st = optGetData()), st < 0) return st;
438 if ((qp -> trackTime.frame = st = optGetData()), st < 0) return st;
439 if ((st = optGetData()) < 0) return st;
440 if ((qp -> diskTime.min = st = optGetData()), st < 0) return st;
441 if ((qp -> diskTime.sec = st = optGetData()), st < 0) return st;
442 if ((qp -> diskTime.frame = st = optGetData()), st < 0) return st;
443 #ifdef DEBUG_TOC
444 printk("optcd: exiting optGetQChannelInfo\n");
445 #endif
446 return 0;
447 }
448
449 #define QINFO_FIRSTTRACK 0xa0
450 #define QINFO_LASTTRACK 0xa1
451 #define QINFO_DISKLENGTH 0xa2
452
453 static int optGetDiskInfo(void) {
454 int st, limit;
455 unsigned char test = 0;
456 struct opt_Toc qInfo;
457 #ifdef DEBUG_TOC
458 printk("optcd: starting optGetDiskInfo\n");
459 #endif
460 optDiskChanged = 0;
461 if ((st = optCmd(COMLEADIN)) < 0)
462 return st;
463 for (limit = 300; (limit > 0) && (test != 0x0f); limit--) {
464 if ((st = optGetQChannelInfo(&qInfo)) < 0)
465 return st;
466 switch (qInfo.pointIndex) {
467 case QINFO_FIRSTTRACK:
468 DiskInfo.first = bcd2bin(qInfo.diskTime.min);
469 #ifdef DEBUG_TOC
470 printk("optcd: got first: %d\n", DiskInfo.first);
471 #endif
472 test |= 0x01;
473 break;
474 case QINFO_LASTTRACK:
475 DiskInfo.last = bcd2bin(qInfo.diskTime.min);
476 #ifdef DEBUG_TOC
477 printk("optcd: got last: %d\n", DiskInfo.last);
478 #endif
479 test |= 0x02;
480 break;
481 case QINFO_DISKLENGTH:
482 DiskInfo.diskLength.min = qInfo.diskTime.min;
483 DiskInfo.diskLength.sec = qInfo.diskTime.sec-2;
484 DiskInfo.diskLength.frame = qInfo.diskTime.frame;
485 #ifdef DEBUG_TOC
486 printk("optcd: got length: %x:%x.%x\n",
487 DiskInfo.diskLength.min,
488 DiskInfo.diskLength.sec,
489 DiskInfo.diskLength.frame);
490 #endif
491 test |= 0x04;
492 break;
493 default:
494 if ((test & 0x01)
495 && (qInfo.pointIndex == DiskInfo.first)) {
496
497 DiskInfo.firstTrack.min = qInfo.diskTime.min;
498 DiskInfo.firstTrack.sec = qInfo.diskTime.sec;
499 DiskInfo.firstTrack.frame = qInfo.diskTime.frame;
500 #ifdef DEBUG_TOC
501 printk("optcd: got start: %x:%x.%x\n",
502 DiskInfo.firstTrack.min,
503 DiskInfo.firstTrack.sec,
504 DiskInfo.firstTrack.frame);
505 #endif
506 test |= 0x08;
507 }
508 }
509 }
510 #ifdef DEBUG_TOC
511 printk("optcd: exiting optGetDiskInfo\n");
512 #endif
513 if (test != 0x0f)
514 return -ERR_TOC_MISSINGINFO;
515 return 0;
516 }
517
518 static int optGetToc(void) {
519 int st, count, px, limit;
520 struct opt_Toc qInfo;
521 #ifdef DEBUG_TOC
522 int i;
523 printk("optcd: starting optGetToc\n");
524 #endif
525 for (count = 0; count < MAX_TRACKS; count++)
526 Toc[count].pointIndex = 0;
527 if ((st = optCmd(COMLEADIN)) < 0)
528 return st;
529 st = 0;
530 count = DiskInfo.last + 3;
531 for (limit = 300; (limit > 0) && (count > 0); limit--) {
532 if ((st = optGetQChannelInfo(&qInfo)) < 0)
533 break;
534 px = bcd2bin(qInfo.pointIndex);
535 if (px > 0 && px < MAX_TRACKS && qInfo.track == 0)
536 if (Toc[px].pointIndex == 0) {
537 Toc[px] = qInfo;
538 count--;
539 }
540 }
541 Toc[DiskInfo.last + 1].diskTime = DiskInfo.diskLength;
542 #ifdef DEBUG_TOC
543 printk("optcd: exiting optGetToc\n");
544 for (i = 1; i <= DiskInfo.last + 1; i++)
545 printk("i = %3d ctl-adr = %02x track %2d px "
546 "%02x %02x:%02x.%02x %02x:%02x.%02x\n",
547 i, Toc[i].ctrl_addr,
548 Toc[i].track,
549 Toc[i].pointIndex,
550 Toc[i].trackTime.min,
551 Toc[i].trackTime.sec,
552 Toc[i].trackTime.frame,
553 Toc[i].diskTime.min,
554 Toc[i].diskTime.sec,
555 Toc[i].diskTime.frame);
556 for (i = 100; i < 103; i++)
557 printk("i = %3d ctl-adr = %02x track %2d px "
558 "%02x %02x:%02x.%02x %02x:%02x.%02x\n",
559 i, Toc[i].ctrl_addr,
560 Toc[i].track,
561 Toc[i].pointIndex,
562 Toc[i].trackTime.min,
563 Toc[i].trackTime.sec,
564 Toc[i].trackTime.frame,
565 Toc[i].diskTime.min,
566 Toc[i].diskTime.sec,
567 Toc[i].diskTime.frame);
568 #endif
569 return count ? -ERR_TOC_MISSINGENTRY : 0;
570 }
571
572 static int optUpdateToc(void) {
573 #ifdef DEBUG_TOC
574 printk("optcd: starting optUpdateToc\n");
575 #endif
576 if (optTocUpToDate)
577 return 0;
578 if (optGetDiskInfo() < 0)
579 return -EIO;
580 if (optGetToc() < 0)
581 return -EIO;
582 optTocUpToDate = 1;
583 #ifdef DEBUG_TOC
584 printk("optcd: exiting optUpdateToc\n");
585 #endif
586 return 0;
587 }
588
589
590
591
592 #define OPT_BUF_SIZ 16
593 #define OPT_BLOCKSIZE 2048
594 #define OPT_BLOCKSIZE_RAW 2336
595 #define OPT_BLOCKSIZE_ALL 2646
596 #define OPT_NOBUF -1
597
598
599 static char opt_buf[OPT_BLOCKSIZE*OPT_BUF_SIZ];
600 static volatile int opt_buf_bn[OPT_BUF_SIZ], opt_next_bn;
601 static volatile int opt_buf_in = 0, opt_buf_out = OPT_NOBUF;
602
603 inline static void opt_invalidate_buffers(void) {
604 int i;
605 #ifdef DEBUG_BUFFERS
606 printk("optcd: executing opt_invalidate_buffers\n");
607 #endif
608 for (i = 0; i < OPT_BUF_SIZ; i++)
609 opt_buf_bn[i] = OPT_NOBUF;
610 opt_buf_out = OPT_NOBUF;
611 }
612
613
614
615
616
617 static void opt_transfer(void) {
618 #if (defined DEBUG_BUFFERS) || (defined DEBUG_REQUEST)
619 printk("optcd: executing opt_transfer\n");
620 #endif
621 if (!CURRENT_VALID)
622 return;
623 while (CURRENT -> nr_sectors) {
624 int bn = CURRENT -> sector / 4;
625 int i, offs, nr_sectors;
626 for (i = 0; i < OPT_BUF_SIZ && opt_buf_bn[i] != bn; ++i);
627 #ifdef DEBUG_REQUEST
628 printk("optcd: found %d\n", i);
629 #endif
630 if (i >= OPT_BUF_SIZ) {
631 opt_buf_out = OPT_NOBUF;
632 break;
633 }
634 offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
635 nr_sectors = 4 - (CURRENT -> sector & 3);
636 if (opt_buf_out != i) {
637 opt_buf_out = i;
638 if (opt_buf_bn[i] != bn) {
639 opt_buf_out = OPT_NOBUF;
640 continue;
641 }
642 }
643 if (nr_sectors > CURRENT -> nr_sectors)
644 nr_sectors = CURRENT -> nr_sectors;
645 memcpy(CURRENT -> buffer, opt_buf + offs, nr_sectors * 512);
646 CURRENT -> nr_sectors -= nr_sectors;
647 CURRENT -> sector += nr_sectors;
648 CURRENT -> buffer += nr_sectors * 512;
649 }
650 }
651
652
653
654
655 enum opt_state_e {
656 OPT_S_IDLE,
657 OPT_S_START,
658 OPT_S_READ,
659 OPT_S_DATA,
660 OPT_S_STOP,
661 OPT_S_STOPPING
662 };
663
664 static volatile enum opt_state_e opt_state = OPT_S_IDLE;
665 #ifdef DEBUG_STATE
666 static volatile enum opt_state_e opt_state_old = OPT_S_STOP;
667 static volatile int opt_st_old = 0;
668 static volatile long opt_state_n = 0;
669 #endif
670
671 static volatile int opt_transfer_is_active = 0;
672 static volatile int opt_error = 0;
673 static int optTries;
674
675 static void opt_poll(void) {
676 static int optTimeout;
677 static volatile int opt_read_count = 1;
678 int st = 0;
679 int loop_ctl = 1;
680 int skip = 0;
681
682 if (opt_error) {
683 printk("optcd: I/O error 0x%02x\n", opt_error);
684 opt_invalidate_buffers();
685 #ifdef WARN_IF_READ_FAILURE
686 if (optTries == 5)
687 printk("optcd: read block %d failed; audio disk?\n",
688 opt_next_bn);
689 #endif
690 if (!optTries--) {
691 printk("optcd: read block %d failed; Giving up\n",
692 opt_next_bn);
693 if (opt_transfer_is_active) {
694 optTries = 0;
695 loop_ctl = 0;
696 }
697 if (CURRENT_VALID)
698 end_request(0);
699 optTries = 5;
700 }
701 opt_error = 0;
702 opt_state = OPT_S_STOP;
703 }
704
705 while (loop_ctl)
706 {
707 loop_ctl = 0;
708
709 #ifdef DEBUG_STATE
710 if (opt_state == opt_state_old)
711 opt_state_n++;
712 else {
713 opt_state_old = opt_state;
714 if (++opt_state_n > 1)
715 printk("optcd: %ld times in previous state\n",
716 opt_state_n);
717 printk("optcd: state %d\n", opt_state);
718 opt_state_n = 0;
719 }
720 #endif
721 switch (opt_state) {
722 case OPT_S_IDLE:
723 return;
724 case OPT_S_START:
725 if (optSendCmd(COMDRVST))
726 return;
727 opt_state = OPT_S_READ;
728 optTimeout = 3000;
729 break;
730 case OPT_S_READ: {
731 struct opt_Play_msf msf;
732 if (!skip) {
733 if ((st = optStatus()) < 0)
734 break;
735 if (st & ST_DSK_CHG) {
736 optDiskChanged = 1;
737 optTocUpToDate = 0;
738 opt_invalidate_buffers();
739 }
740 }
741 skip = 0;
742 if ((st & ST_DOOR_OPEN) || (st & ST_DRVERR)) {
743 optDiskChanged = 1;
744 optTocUpToDate = 0;
745 printk((st & ST_DOOR_OPEN)
746 ? "optcd: door open\n"
747 : "optcd: disk removed\n");
748 if (opt_transfer_is_active) {
749 opt_state = OPT_S_START;
750 loop_ctl = 1;
751 break;
752 }
753 opt_state = OPT_S_IDLE;
754 while (CURRENT_VALID)
755 end_request(0);
756 return;
757 }
758 if (!CURRENT_VALID) {
759 opt_state = OPT_S_STOP;
760 loop_ctl = 1;
761 break;
762 }
763 opt_next_bn = CURRENT -> sector / 4;
764 hsg2msf(opt_next_bn, &msf.start);
765 opt_read_count = OPT_BUF_SIZ;
766 msf.end.min = 0;
767 msf.end.sec = 0;
768 msf.end.frame = opt_read_count;
769 #ifdef DEBUG_REQUEST
770 printk("optcd: reading %x:%x.%x %x:%x.%x\n",
771 msf.start.min,
772 msf.start.sec,
773 msf.start.frame,
774 msf.end.min,
775 msf.end.sec,
776 msf.end.frame);
777 printk("optcd: opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n",
778 opt_next_bn,
779 opt_buf_in,
780 opt_buf_out,
781 opt_buf_bn[opt_buf_in]);
782 #endif
783 optReadCmd(COMREAD, &msf);
784 opt_state = OPT_S_DATA;
785 optTimeout = READ_TIMEOUT;
786 break;
787 }
788 case OPT_S_DATA:
789 st = optFlags() & (FL_STEN|FL_DTEN);
790 #ifdef DEBUG_STATE
791 if (st != opt_st_old) {
792 opt_st_old = st;
793 printk("optcd: st:%x\n", st);
794 }
795 if (st == FL_STEN)
796 printk("timeout cnt: %d\n", optTimeout);
797 #endif
798 switch (st) {
799 case FL_DTEN:
800 #ifdef WARN_IF_READ_FAILURE
801 if (optTries == 5)
802 printk("optcd: read block %d failed; audio disk?\n",
803 opt_next_bn);
804 #endif
805 if (!optTries--) {
806 printk("optcd: read block %d failed; Giving up\n",
807 opt_next_bn);
808 if (opt_transfer_is_active) {
809 optTries = 0;
810 break;
811 }
812 if (CURRENT_VALID)
813 end_request(0);
814 optTries = 5;
815 }
816 opt_state = OPT_S_START;
817 optTimeout = READ_TIMEOUT;
818 loop_ctl = 1;
819 case (FL_STEN|FL_DTEN):
820 break;
821 default:
822 optTries = 5;
823 if (!CURRENT_VALID && opt_buf_in == opt_buf_out) {
824 opt_state = OPT_S_STOP;
825 loop_ctl = 1;
826 break;
827 }
828 if (opt_read_count<=0)
829 printk("optcd: warning - try to read 0 frames\n");
830 while (opt_read_count) {
831 opt_buf_bn[opt_buf_in] = OPT_NOBUF;
832 if (dten_low()) {
833 printk("read_count:%d CURRENT->nr_sectors:%ld opt_buf_in:%d\n",
834 opt_read_count,
835 CURRENT->nr_sectors,
836 opt_buf_in);
837 printk("opt_transfer_is_active:%x\n",
838 opt_transfer_is_active);
839 opt_read_count = 0;
840 opt_state = OPT_S_STOP;
841 loop_ctl = 1;
842 end_request(0);
843 break;
844 }
845 optReadData(opt_buf+OPT_BLOCKSIZE*opt_buf_in, OPT_BLOCKSIZE);
846 opt_read_count--;
847 #ifdef DEBUG_REQUEST
848 printk("OPT_S_DATA; ---I've read data- read_count: %d\n",
849 opt_read_count);
850 printk("opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n",
851 opt_next_bn,
852 opt_buf_in,
853 opt_buf_out,
854 opt_buf_bn[opt_buf_in]);
855 #endif
856 opt_buf_bn[opt_buf_in] = opt_next_bn++;
857 if (opt_buf_out == OPT_NOBUF)
858 opt_buf_out = opt_buf_in;
859 opt_buf_in = opt_buf_in + 1 ==
860 OPT_BUF_SIZ ? 0 : opt_buf_in + 1;
861 }
862 if (!opt_transfer_is_active) {
863 while (CURRENT_VALID) {
864 opt_transfer();
865 if (CURRENT -> nr_sectors == 0)
866 end_request(1);
867 else
868 break;
869 }
870 }
871
872 if (CURRENT_VALID
873 && (CURRENT -> sector / 4 < opt_next_bn ||
874 CURRENT -> sector / 4 >
875 opt_next_bn + OPT_BUF_SIZ)) {
876 opt_state = OPT_S_STOP;
877 loop_ctl = 1;
878 break;
879 }
880 optTimeout = READ_TIMEOUT;
881 if (opt_read_count == 0) {
882 opt_state = OPT_S_STOP;
883 loop_ctl = 1;
884 break;
885 }
886 }
887 break;
888 case OPT_S_STOP:
889 if (opt_read_count != 0)
890 printk("optcd: discard data=%x frames\n",
891 opt_read_count);
892 while (opt_read_count != 0) {
893 optFlushData();
894 opt_read_count--;
895 }
896 if (optSendCmd(COMDRVST))
897 return;
898 opt_state = OPT_S_STOPPING;
899 optTimeout = 1000;
900 break;
901 case OPT_S_STOPPING:
902 if ((st = optStatus()) < 0 && optTimeout)
903 break;
904 if ((st != -1) && (st & ST_DSK_CHG)) {
905 optDiskChanged = 1;
906 optTocUpToDate = 0;
907 opt_invalidate_buffers();
908 }
909 if (CURRENT_VALID) {
910 if (st != -1) {
911 opt_state = OPT_S_READ;
912 loop_ctl = 1;
913 skip = 1;
914 break;
915 } else {
916 opt_state = OPT_S_START;
917 optTimeout = 1;
918 }
919 } else {
920 opt_state = OPT_S_IDLE;
921 return;
922 }
923 break;
924 default:
925 printk("optcd: invalid state %d\n", opt_state);
926 return;
927 }
928 }
929
930 if (!optTimeout--) {
931 printk("optcd: timeout in state %d\n", opt_state);
932 opt_state = OPT_S_STOP;
933 if (optCmd(COMSTOP) < 0)
934 return;
935 }
936
937 SET_TIMER(opt_poll, 1);
938 }
939
940
941 static void do_optcd_request(void) {
942 #ifdef DEBUG_REQUEST
943 printk("optcd: do_optcd_request(%ld+%ld)\n",
944 CURRENT -> sector, CURRENT -> nr_sectors);
945 #endif
946 opt_transfer_is_active = 1;
947 while (CURRENT_VALID) {
948 if (CURRENT->bh) {
949 if (!CURRENT->bh->b_lock)
950 panic(DEVICE_NAME ": block not locked");
951 }
952 opt_transfer();
953 if (CURRENT -> nr_sectors == 0) {
954 end_request(1);
955 } else {
956 opt_buf_out = OPT_NOBUF;
957 if (opt_state == OPT_S_IDLE) {
958
959 if (optUpdateToc() < 0) {
960 while (CURRENT_VALID)
961 end_request(0);
962 break;
963 }
964
965 opt_state = OPT_S_START;
966 optTries = 5;
967 SET_TIMER(opt_poll, 1);
968 }
969 break;
970 }
971 }
972 opt_transfer_is_active = 0;
973 #ifdef DEBUG_REQUEST
974 printk("opt_next_bn:%d opt_buf_in:%d opt_buf_out:%d opt_buf_bn:%d\n",
975 opt_next_bn, opt_buf_in, opt_buf_out, opt_buf_bn[opt_buf_in]);
976 printk("optcd: do_optcd_request ends\n");
977 #endif
978 }
979
980
981
982
983 static int opt_ioctl(struct inode *ip, struct file *fp,
984 unsigned int cmd, unsigned long arg) {
985 static struct opt_Play_msf opt_Play;
986 int err;
987 #ifdef DEBUG_VFS
988 printk("optcd: starting opt_ioctl, command 0x%x\n", cmd);
989 #endif
990 if (!ip)
991 return -EINVAL;
992 if (optGetStatus() < 0)
993 return -EIO;
994 if ((err = optUpdateToc()) < 0)
995 return err;
996
997 switch (cmd) {
998 case CDROMPAUSE: {
999 struct opt_Toc qInfo;
1000
1001 if (optAudioStatus != CDROM_AUDIO_PLAY)
1002 return -EINVAL;
1003 if (optGetQChannelInfo(&qInfo) < 0) {
1004
1005 optAudioStatus = CDROM_AUDIO_NO_STATUS;
1006 return 0;
1007 }
1008 opt_Play.start = qInfo.diskTime;
1009 if (optCmd(COMPAUSEON) < 0)
1010 return -EIO;
1011 optAudioStatus = CDROM_AUDIO_PAUSED;
1012 break;
1013 }
1014 case CDROMRESUME:
1015 if (optAudioStatus != CDROM_AUDIO_PAUSED)
1016 return -EINVAL;
1017 if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
1018 optAudioStatus = CDROM_AUDIO_ERROR;
1019 return -EIO;
1020 }
1021 optAudioStatus = CDROM_AUDIO_PLAY;
1022 break;
1023 case CDROMPLAYMSF: {
1024 int st;
1025 struct cdrom_msf msf;
1026
1027 if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof msf)))
1028 return st;
1029 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1030 opt_Play.start.min = bin2bcd(msf.cdmsf_min0);
1031 opt_Play.start.sec = bin2bcd(msf.cdmsf_sec0);
1032 opt_Play.start.frame = bin2bcd(msf.cdmsf_frame0);
1033 opt_Play.end.min = bin2bcd(msf.cdmsf_min1);
1034 opt_Play.end.sec = bin2bcd(msf.cdmsf_sec1);
1035 opt_Play.end.frame = bin2bcd(msf.cdmsf_frame1);
1036 if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
1037 optAudioStatus = CDROM_AUDIO_ERROR;
1038 return -EIO;
1039 }
1040 optAudioStatus = CDROM_AUDIO_PLAY;
1041 break;
1042 }
1043 case CDROMPLAYTRKIND: {
1044 int st;
1045 struct cdrom_ti ti;
1046
1047 if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof ti)))
1048 return st;
1049 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
1050 if (ti.cdti_trk0 < DiskInfo.first
1051 || ti.cdti_trk0 > DiskInfo.last
1052 || ti.cdti_trk1 < ti.cdti_trk0)
1053 return -EINVAL;
1054 if (ti.cdti_trk1 > DiskInfo.last)
1055 ti.cdti_trk1 = DiskInfo.last;
1056 opt_Play.start = Toc[ti.cdti_trk0].diskTime;
1057 opt_Play.end = Toc[ti.cdti_trk1 + 1].diskTime;
1058 #ifdef DEBUG_VFS
1059 printk("optcd: play %02x:%02x.%02x to %02x:%02x.%02x\n",
1060 opt_Play.start.min,
1061 opt_Play.start.sec,
1062 opt_Play.start.frame,
1063 opt_Play.end.min,
1064 opt_Play.end.sec,
1065 opt_Play.end.frame);
1066 #endif
1067 if (optPlayCmd(COMPLAY, &opt_Play) < 0) {
1068 optAudioStatus = CDROM_AUDIO_ERROR;
1069 return -EIO;
1070 }
1071 optAudioStatus = CDROM_AUDIO_PLAY;
1072 break;
1073 }
1074 case CDROMREADTOCHDR: {
1075 int st;
1076 struct cdrom_tochdr tocHdr;
1077
1078 if ((st = verify_area(VERIFY_WRITE,(void *)arg,sizeof tocHdr)))
1079 return st;
1080 if (!optTocUpToDate)
1081 optGetDiskInfo();
1082 tocHdr.cdth_trk0 = DiskInfo.first;
1083 tocHdr.cdth_trk1 = DiskInfo.last;
1084 memcpy_tofs((void *) arg, &tocHdr, sizeof tocHdr);
1085 break;
1086 }
1087 case CDROMREADTOCENTRY: {
1088 int st;
1089 struct cdrom_tocentry entry;
1090 struct opt_Toc *tocPtr;
1091
1092 if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof entry)))
1093 return st;
1094 if ((st = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry)))
1095 return st;
1096 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
1097 if (!optTocUpToDate)
1098 optGetDiskInfo();
1099 if (entry.cdte_track == CDROM_LEADOUT)
1100 tocPtr = &Toc[DiskInfo.last + 1];
1101 else if (entry.cdte_track > DiskInfo.last
1102 || entry.cdte_track < DiskInfo.first)
1103 return -EINVAL;
1104 else
1105 tocPtr = &Toc[entry.cdte_track];
1106 entry.cdte_adr = tocPtr -> ctrl_addr;
1107 entry.cdte_ctrl = tocPtr -> ctrl_addr >> 4;
1108 switch (entry.cdte_format) {
1109 case CDROM_LBA:
1110 entry.cdte_addr.lba = msf2hsg(&tocPtr -> diskTime);
1111 break;
1112 case CDROM_MSF:
1113 entry.cdte_addr.msf.minute =
1114 bcd2bin(tocPtr -> diskTime.min);
1115 entry.cdte_addr.msf.second =
1116 bcd2bin(tocPtr -> diskTime.sec);
1117 entry.cdte_addr.msf.frame =
1118 bcd2bin(tocPtr -> diskTime.frame);
1119 break;
1120 default:
1121 return -EINVAL;
1122 }
1123 memcpy_tofs((void *) arg, &entry, sizeof entry);
1124 break;
1125 }
1126 case CDROMSTOP:
1127 optCmd(COMSTOP);
1128 optAudioStatus = CDROM_AUDIO_NO_STATUS;
1129 break;
1130 case CDROMSTART:
1131 optCmd(COMCLOSE);
1132 break;
1133 case CDROMEJECT:
1134 optCmd(COMUNLOCK);
1135 optCmd(COMOPEN);
1136 break;
1137 case CDROMVOLCTRL: {
1138 int st;
1139 struct cdrom_volctrl volctrl;
1140
1141 if ((st = verify_area(VERIFY_READ, (void *) arg,
1142 sizeof(volctrl))))
1143 return st;
1144 memcpy_fromfs(&volctrl, (char *) arg, sizeof(volctrl));
1145 opt_Play.start.min = 0x10;
1146 opt_Play.start.sec = 0x32;
1147 opt_Play.start.frame = volctrl.channel0;
1148 opt_Play.end.min = volctrl.channel1;
1149 opt_Play.end.sec = volctrl.channel2;
1150 opt_Play.end.frame = volctrl.channel3;
1151 if (optPlayCmd(COMCHCTRL, &opt_Play) < 0)
1152 return -EIO;
1153 break;
1154 }
1155 case CDROMSUBCHNL: {
1156 int st;
1157 struct cdrom_subchnl subchnl;
1158 struct opt_Toc qInfo;
1159
1160 if ((st = verify_area(VERIFY_READ,
1161 (void *) arg, sizeof subchnl)))
1162 return st;
1163 if ((st = verify_area(VERIFY_WRITE,
1164 (void *) arg, sizeof subchnl)))
1165 return st;
1166 memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
1167 if (optGetQChannelInfo(&qInfo) < 0)
1168 return -EIO;
1169 subchnl.cdsc_audiostatus = optAudioStatus;
1170 subchnl.cdsc_adr = qInfo.ctrl_addr;
1171 subchnl.cdsc_ctrl = qInfo.ctrl_addr >> 4;
1172 subchnl.cdsc_trk = bcd2bin(qInfo.track);
1173 subchnl.cdsc_ind = bcd2bin(qInfo.pointIndex);
1174 switch (subchnl.cdsc_format) {
1175 case CDROM_LBA:
1176 subchnl.cdsc_absaddr.lba = msf2hsg(&qInfo.diskTime);
1177 subchnl.cdsc_reladdr.lba = msf2hsg(&qInfo.trackTime);
1178 break;
1179 case CDROM_MSF:
1180 subchnl.cdsc_absaddr.msf.minute =
1181 bcd2bin(qInfo.diskTime.min);
1182 subchnl.cdsc_absaddr.msf.second =
1183 bcd2bin(qInfo.diskTime.sec);
1184 subchnl.cdsc_absaddr.msf.frame =
1185 bcd2bin(qInfo.diskTime.frame);
1186 subchnl.cdsc_reladdr.msf.minute =
1187 bcd2bin(qInfo.trackTime.min);
1188 subchnl.cdsc_reladdr.msf.second =
1189 bcd2bin(qInfo.trackTime.sec);
1190 subchnl.cdsc_reladdr.msf.frame =
1191 bcd2bin(qInfo.trackTime.frame);
1192 break;
1193 default:
1194 return -EINVAL;
1195 }
1196 memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
1197 break;
1198 }
1199 case CDROMREADMODE1: {
1200 int st;
1201 struct cdrom_msf msf;
1202 char buf[OPT_BLOCKSIZE];
1203
1204 if ((st = verify_area(VERIFY_READ, (void *) arg, sizeof msf)))
1205 return st;
1206 if ((st = verify_area(VERIFY_WRITE,(void *)arg,OPT_BLOCKSIZE)))
1207 return st;
1208 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1209 opt_Play.start.min = bin2bcd(msf.cdmsf_min0);
1210 opt_Play.start.sec = bin2bcd(msf.cdmsf_sec0);
1211 opt_Play.start.frame = bin2bcd(msf.cdmsf_frame0);
1212 opt_Play.end.min = 0;
1213 opt_Play.end.sec = 0;
1214 opt_Play.end.frame = 1;
1215 st = optReadCmd(COMREAD, &opt_Play);
1216 #ifdef DEBUG_VFS
1217 printk("optcd: COMREAD status 0x%x\n", st);
1218 #endif
1219 sleep_dten_low();
1220 optReadData(buf, OPT_BLOCKSIZE);
1221 memcpy_tofs((void *) arg, &buf, OPT_BLOCKSIZE);
1222 break;
1223 }
1224 case CDROMMULTISESSION:
1225 return -EINVAL;
1226
1227 default:
1228 return -EINVAL;
1229 }
1230 #ifdef DEBUG_VFS
1231 printk("optcd: exiting opt_ioctl\n");
1232 #endif
1233 return 0;
1234 }
1235
1236 static int optPresent = 0;
1237 static int opt_open_count = 0;
1238
1239
1240 static int opt_open(struct inode *ip, struct file *fp) {
1241 #ifdef DEBUG_VFS
1242 printk("optcd: starting opt_open\n");
1243 #endif
1244 if (!optPresent)
1245 return -ENXIO;
1246 if (!opt_open_count && opt_state == OPT_S_IDLE) {
1247 int st;
1248 opt_invalidate_buffers();
1249 if ((st = optGetStatus()) < 0)
1250 return -EIO;
1251 if (st & ST_DOOR_OPEN) {
1252 optCmd(COMCLOSE);
1253 if ((st = optGetStatus()) < 0)
1254 return -EIO;
1255 }
1256 if (st & (ST_DOOR_OPEN|ST_DRVERR)) {
1257 printk("optcd: no disk or door open\n");
1258 return -EIO;
1259 }
1260 if (optUpdateToc() < 0)
1261 return -EIO;
1262 }
1263 opt_open_count++;
1264 MOD_INC_USE_COUNT;
1265 optCmd(COMLOCK);
1266 #ifdef DEBUG_VFS
1267 printk("optcd: exiting opt_open\n");
1268 #endif
1269 return 0;
1270 }
1271
1272
1273 static void opt_release(struct inode *ip, struct file *fp) {
1274 #ifdef DEBUG_VFS
1275 printk("optcd: executing opt_release\n");
1276 printk("inode: %p, inode -> i_rdev: 0x%x, file: %p\n",
1277 ip, ip -> i_rdev, fp);
1278 #endif
1279 if (!--opt_open_count) {
1280 opt_invalidate_buffers();
1281 sync_dev(ip -> i_rdev);
1282 invalidate_buffers(ip -> i_rdev);
1283 CLEAR_TIMER;
1284 optCmd(COMUNLOCK);
1285 }
1286 MOD_DEC_USE_COUNT;
1287 }
1288
1289
1290
1291
1292 static int version_ok(void) {
1293 char devname[100];
1294 int count, i, ch;
1295
1296 if (optCmd(COMVERSION) < 0)
1297 return 0;
1298 if ((count = optGetData()) < 0)
1299 return 0;
1300 for (i = 0, ch = -1; count > 0; count--) {
1301 if ((ch = optGetData()) < 0)
1302 break;
1303 if (i < 99)
1304 devname[i++] = ch;
1305 }
1306 devname[i] = '\0';
1307 if (ch < 0)
1308 return 0;
1309 printk("optcd: Device %s detected\n", devname);
1310 return ((devname[0] == 'D')
1311 && (devname[1] == 'O')
1312 && (devname[2] == 'L')
1313 && (devname[3] == 'P')
1314 && (devname[4] == 'H')
1315 && (devname[5] == 'I')
1316 && (devname[6] == 'N'));
1317 }
1318
1319
1320 static struct file_operations opt_fops = {
1321 NULL,
1322 block_read,
1323 block_write,
1324 NULL,
1325 NULL,
1326 opt_ioctl,
1327 NULL,
1328 opt_open,
1329 opt_release,
1330 NULL,
1331 NULL,
1332 NULL,
1333 NULL
1334 };
1335
1336
1337
1338 void optcd_setup(char *str, int *ints) {
1339 if (ints[0] > 0)
1340 optcd_port = ints[1];
1341 }
1342
1343 #ifndef MODULE
1344 #define RETURN_EIO return mem_start
1345 #else
1346 #define RETURN_EIO return -EIO
1347 #endif
1348
1349
1350
1351
1352 #ifndef MODULE
1353 unsigned long optcd_init(unsigned long mem_start, unsigned long mem_end) {
1354 #else
1355 int init_module(void) {
1356 #endif
1357 if (optcd_port <= 0) {
1358 printk("optcd: no Optics Storage CDROM Initialization\n");
1359 RETURN_EIO;
1360 }
1361 if (check_region(optcd_port, 4)) {
1362 printk("optcd: conflict, I/O port 0x%x already used\n",
1363 optcd_port);
1364 RETURN_EIO;
1365 }
1366 if (!optResetDrive()) {
1367 printk("optcd: drive at 0x%x not ready\n", optcd_port);
1368 RETURN_EIO;
1369 }
1370 if (!version_ok()) {
1371 printk("optcd: unknown drive detected; aborting\n");
1372 RETURN_EIO;
1373 }
1374 if (optCmd(COMINITDOUBLE) < 0) {
1375 printk("optcd: cannot init double speed mode\n");
1376 RETURN_EIO;
1377 }
1378 if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0)
1379 {
1380 printk("optcd: unable to get major %d\n", MAJOR_NR);
1381 RETURN_EIO;
1382 }
1383 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1384 read_ahead[MAJOR_NR] = 4;
1385 request_region(optcd_port, 4, "optcd");
1386 optPresent = 1;
1387 printk("optcd: 8000 AT CDROM at 0x%x\n", optcd_port);
1388 #ifndef MODULE
1389 return mem_start;
1390 #else
1391 return 0;
1392 #endif
1393 }
1394
1395 #ifdef MODULE
1396 void cleanup_module(void) {
1397 if (MOD_IN_USE) {
1398 printk("optcd: module in use - can't remove it.\n");
1399 return;
1400 }
1401 if ((unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL)) {
1402 printk("optcd: what's that: can't unregister\n");
1403 return;
1404 }
1405 release_region(optcd_port, 4);
1406 printk("optcd: module released.\n");
1407 }
1408 #endif MODULE