This source file includes following definitions.
- debug
- flag_low
- sleep_timer
- sleep_flag_low
- send_cmd
- send_params
- send_seek_params
- get_exec_status
- get_data
- reset_drive
- stdt_flags
- fetch_status
- fetch_data
- flush_data
- exec_cmd
- exec_read_cmd
- exec_seek_cmd
- exec_long_cmd
- single_bin2bcd
- bin2bcd
- lba2msf
- bcd2bin
- msf2lba
- msf_bcd2bin
- drive_status
- get_q_channel
- toc_debug_info
- read_toc
- get_multi_disk_info
- update_toc
- opt_invalidate_buffers
- transfer
- poll
- do_optcd_request
- cdrompause
- cdromresume
- cdromplaymsf
- cdromplaytrkind
- cdromreadtochdr
- cdromreadtocentry
- cdromvolctrl
- cdromsubchnl
- cdromread
- cdromseek
- cdrommultisession
- cdromreset
- opt_ioctl
- opt_open
- opt_release
- opt_media_change
- 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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61 #include <linux/module.h>
62 #include <linux/mm.h>
63 #include <linux/ioport.h>
64 #include <asm/io.h>
65
66 #define MAJOR_NR OPTICS_CDROM_MAJOR
67 #include <linux/blk.h>
68
69 #include <linux/cdrom.h>
70 #include <linux/optcd.h>
71
72
73
74
75
76
77 #if DEBUG_DRIVE_IF | DEBUG_VFS | DEBUG_CONV | DEBUG_TOC | \
78 DEBUG_BUFFERS | DEBUG_REQUEST | DEBUG_STATE | DEBUG_MULTIS
79 #define DEBUG(x) debug x
80 static void debug(int debug_this, const char* fmt, ...)
81 {
82 char s[1024];
83 va_list args;
84
85 if (!debug_this)
86 return;
87
88 va_start(args, fmt);
89 vsprintf(s, fmt, args);
90 printk("optcd: %s\n", s);
91 va_end(args);
92 }
93 #else
94 #define DEBUG(x)
95 #endif
96
97
98
99
100
101 #define optcd_port optcd
102 static short optcd_port = OPTCD_PORTBASE;
103
104
105 #define DATA_PORT optcd_port
106 #define STATUS_PORT optcd_port+1
107
108
109 #define COMIN_PORT optcd_port
110 #define RESET_PORT optcd_port+1
111 #define HCON_PORT optcd_port+2
112
113
114
115 #define ST_DRVERR 0x80
116 #define ST_DOOR_OPEN 0x40
117 #define ST_MIXEDMODE_DISK 0x20
118 #define ST_MODE_BITS 0x1c
119 #define ST_M_STOP 0x00
120 #define ST_M_READ 0x04
121 #define ST_M_AUDIO 0x04
122 #define ST_M_PAUSE 0x08
123 #define ST_M_INITIAL 0x0c
124 #define ST_M_ERROR 0x10
125 #define ST_M_OTHERS 0x14
126 #define ST_MODE2TRACK 0x02
127 #define ST_DSK_CHG 0x01
128 #define ST_L_LOCK 0x01
129 #define ST_CMD_OK 0x00
130 #define ST_OP_OK 0x01
131 #define ST_PA_OK 0x02
132 #define ST_OP_ERROR 0x05
133 #define ST_PA_ERROR 0x06
134
135
136
137
138 #define ERR_ILLCMD 0x11
139 #define ERR_ILLPARM 0x12
140 #define ERR_SLEDGE 0x13
141 #define ERR_FOCUS 0x14
142 #define ERR_MOTOR 0x15
143 #define ERR_RADIAL 0x16
144 #define ERR_PLL 0x17
145 #define ERR_SUB_TIM 0x18
146 #define ERR_SUB_NF 0x19
147 #define ERR_TRAY 0x1a
148 #define ERR_TOC 0x1b
149 #define ERR_JUMP 0x1c
150
151 #define ERR_MODE 0x21
152 #define ERR_FORM 0x22
153 #define ERR_HEADADDR 0x23
154 #define ERR_CRC 0x24
155 #define ERR_ECC 0x25
156 #define ERR_CRC_UNC 0x26
157 #define ERR_ILLBSYNC 0x27
158 #define ERR_VDST 0x28
159
160 #define ERR_READ_TIM 0x31
161 #define ERR_DEC_STP 0x32
162 #define ERR_DEC_TIM 0x33
163
164 #define ERR_KEY 0x41
165 #define ERR_READ_FINISH 0x42
166
167 #define ERR_NOBSYNC 0x01
168 #define ERR_SHORTB 0x02
169 #define ERR_LONGB 0x03
170 #define ERR_SHORTDSP 0x04
171 #define ERR_LONGDSP 0x05
172
173
174
175 #define FL_EJECT 0x20
176 #define FL_WAIT 0x10
177 #define FL_EOP 0x08
178 #define FL_STEN 0x04
179 #define FL_DTEN 0x02
180 #define FL_DRQ 0x01
181 #define FL_RESET 0xde
182 #define FL_STDT (FL_STEN|FL_DTEN)
183
184
185
186 #define HCON_DTS 0x08
187 #define HCON_SDRQB 0x04
188 #define HCON_LOHI 0x02
189 #define HCON_DMA16 0x01
190
191
192
193
194 #define COMDRVST 0x20
195 #define COMERRST 0x21
196 #define COMIOCTLISTAT 0x22
197 #define COMINITSINGLE 0x28
198 #define COMINITDOUBLE 0x29
199 #define COMUNLOCK 0x30
200 #define COMLOCK 0x31
201 #define COMLOCKST 0x32
202 #define COMVERSION 0x40
203 #define COMVOIDREADMODE 0x50
204
205 #define COMFETCH 0x60
206 #define COMREAD 0x61
207 #define COMREADRAW 0x62
208 #define COMREADALL 0x63
209
210 #define COMLEADIN 0x70
211 #define COMSEEK 0x71
212 #define COMPAUSEON 0x80
213 #define COMPAUSEOFF 0x81
214 #define COMSTOP 0x82
215 #define COMOPEN 0x90
216 #define COMCLOSE 0x91
217 #define COMPLAY 0xa0
218 #define COMPLAY_TNO 0xa2
219 #define COMSUBQ 0xb0
220 #define COMLOCATION 0xb1
221
222 #define COMCHCTRL 0xc0
223
224 #define COMDRVTEST 0xd0
225 #define COMTEST 0xd1
226
227
228
229
230
231
232 inline static int flag_low(int flag, unsigned long timeout)
233 {
234 int flag_high;
235 unsigned long count = 0;
236
237 while ((flag_high = (inb(STATUS_PORT) & flag)))
238 if (++count >= timeout)
239 break;
240
241 DEBUG((DEBUG_DRIVE_IF, "flag_low 0x%x count %ld%s",
242 flag, count, flag_high ? " timeout" : ""));
243 return !flag_high;
244 }
245
246
247
248 static int sleep_timeout;
249 static struct wait_queue *waitq = NULL;
250 static struct timer_list delay_timer = {NULL, NULL, 0, 0, NULL};
251
252 #define SET_TIMER(func, jifs) \
253 delay_timer.expires = jiffies+(jifs); \
254 delay_timer.function = (void *) (func); \
255 add_timer(&delay_timer);
256 #define CLEAR_TIMER del_timer(&delay_timer)
257
258
259
260
261 static void sleep_timer(void)
262 {
263 int flags = inb(STATUS_PORT) & FL_STDT;
264
265 if (flags == FL_STDT && --sleep_timeout > 0) {
266 SET_TIMER(sleep_timer, HZ/100);
267 } else
268 wake_up(&waitq);
269 }
270
271
272
273 static int sleep_flag_low(int flag, unsigned long timeout)
274 {
275 int flag_high;
276
277 DEBUG((DEBUG_DRIVE_IF, "sleep_flag_low"));
278
279 sleep_timeout = timeout;
280 flag_high = inb(STATUS_PORT) & flag;
281 if (flag_high && sleep_timeout > 0) {
282 SET_TIMER(sleep_timer, HZ/100);
283 sleep_on(&waitq);
284 flag_high = inb(STATUS_PORT) & flag;
285 }
286
287 DEBUG((DEBUG_DRIVE_IF, "flag 0x%x count %ld%s",
288 flag, timeout, flag_high ? " timeout" : ""));
289 return !flag_high;
290 }
291
292
293
294
295
296
297 #define ERR_IF_CMD_TIMEOUT 0x100
298 #define ERR_IF_ERR_TIMEOUT 0x101
299 #define ERR_IF_RESP_TIMEOUT 0x102
300 #define ERR_IF_DATA_TIMEOUT 0x103
301 #define ERR_IF_NOSTAT 0x104
302
303
304
305 static int send_cmd(int cmd)
306 {
307 unsigned char ack;
308
309 DEBUG((DEBUG_DRIVE_IF, "sending command 0x%02x\n", cmd));
310
311 outb(HCON_DTS, HCON_PORT);
312 outb(cmd, COMIN_PORT);
313 if (!flag_low(FL_STEN, BUSY_TIMEOUT))
314 return -ERR_IF_CMD_TIMEOUT;
315 ack = inb(DATA_PORT);
316 outb(HCON_SDRQB, HCON_PORT);
317 return ack==ST_OP_OK ? 0 : -ack;
318 }
319
320
321
322 static int send_params(struct cdrom_msf *params)
323 {
324 unsigned char ack;
325
326 DEBUG((DEBUG_DRIVE_IF, "sending parameters"
327 " %02x:%02x:%02x"
328 " %02x:%02x:%02x",
329 params->cdmsf_min0,
330 params->cdmsf_sec0,
331 params->cdmsf_frame0,
332 params->cdmsf_min1,
333 params->cdmsf_sec1,
334 params->cdmsf_frame1));
335
336 outb(params->cdmsf_min0, COMIN_PORT);
337 outb(params->cdmsf_sec0, COMIN_PORT);
338 outb(params->cdmsf_frame0, COMIN_PORT);
339 outb(params->cdmsf_min1, COMIN_PORT);
340 outb(params->cdmsf_sec1, COMIN_PORT);
341 outb(params->cdmsf_frame1, COMIN_PORT);
342 if (!flag_low(FL_STEN, BUSY_TIMEOUT))
343 return -ERR_IF_CMD_TIMEOUT;
344 ack = inb(DATA_PORT);
345 return ack==ST_PA_OK ? 0 : -ack;
346 }
347
348
349
350 static int send_seek_params(struct cdrom_msf *params)
351 {
352 unsigned char ack;
353
354 DEBUG((DEBUG_DRIVE_IF, "sending seek parameters"
355 " %02x:%02x:%02x",
356 params->cdmsf_min0,
357 params->cdmsf_sec0,
358 params->cdmsf_frame0));
359
360 outb(params->cdmsf_min0, COMIN_PORT);
361 outb(params->cdmsf_sec0, COMIN_PORT);
362 outb(params->cdmsf_frame0, COMIN_PORT);
363 if (!flag_low(FL_STEN, BUSY_TIMEOUT))
364 return -ERR_IF_CMD_TIMEOUT;
365 ack = inb(DATA_PORT);
366 return ack==ST_PA_OK ? 0 : -ack;
367 }
368
369
370
371
372 inline static int get_exec_status(int busy_waiting)
373 {
374 unsigned char exec_status;
375
376 if (busy_waiting
377 ? !flag_low(FL_STEN, BUSY_TIMEOUT)
378 : !sleep_flag_low(FL_STEN, SLEEP_TIMEOUT))
379 return -ERR_IF_CMD_TIMEOUT;
380
381 exec_status = inb(DATA_PORT);
382 DEBUG((DEBUG_DRIVE_IF, "returned exec status 0x%02x", exec_status));
383 return exec_status;
384 }
385
386
387
388
389 inline static int get_data(int short_timeout)
390 {
391 unsigned char data;
392
393 if (!flag_low(FL_STEN, short_timeout ? FAST_TIMEOUT : BUSY_TIMEOUT))
394 return -ERR_IF_DATA_TIMEOUT;
395
396 data = inb(DATA_PORT);
397 DEBUG((DEBUG_DRIVE_IF, "returned data 0x%02x", data));
398 return data;
399 }
400
401
402
403 static int reset_drive(void)
404 {
405 unsigned long count = 0;
406 int flags;
407
408 DEBUG((DEBUG_DRIVE_IF, "reset drive"));
409
410 outb(0, RESET_PORT);
411 while (++count < RESET_WAIT)
412 inb(DATA_PORT);
413
414 count = 0;
415 while ((flags = (inb(STATUS_PORT) & FL_RESET)) != FL_RESET)
416 if (++count >= BUSY_TIMEOUT)
417 break;
418
419 DEBUG((DEBUG_DRIVE_IF, "reset %s",
420 flags == FL_RESET ? "succeeded" : "failed"));
421
422 if (flags != FL_RESET)
423 return 0;
424 outb(HCON_SDRQB, HCON_PORT);
425 return 1;
426 }
427
428
429
430
431
432 inline static int stdt_flags(void)
433 {
434 return inb(STATUS_PORT) & FL_STDT;
435 }
436
437
438
439 inline static int fetch_status(void)
440 {
441 unsigned char status;
442
443 if (inb(STATUS_PORT) & FL_STEN)
444 return -ERR_IF_NOSTAT;
445
446 status = inb(DATA_PORT);
447 DEBUG((DEBUG_DRIVE_IF, "fetched exec status 0x%02x", status));
448 return status;
449 }
450
451
452
453 inline static void fetch_data(char *buf, int n)
454 {
455 insb(DATA_PORT, buf, n);
456 DEBUG((DEBUG_DRIVE_IF, "fetched 0x%x bytes", n));
457 }
458
459
460
461 inline static void flush_data(void)
462 {
463 while ((inb(STATUS_PORT) & FL_STDT) != FL_STDT)
464 inb(DATA_PORT);
465 DEBUG((DEBUG_DRIVE_IF, "flushed fifos"));
466 }
467
468
469
470
471
472
473 inline static int exec_cmd(int cmd)
474 {
475 int ack = send_cmd(cmd);
476 if (ack < 0)
477 return ack;
478 return get_exec_status(cmd < COMFETCH);
479 }
480
481
482
483
484 inline static int exec_read_cmd(int cmd, struct cdrom_msf *params)
485 {
486 int ack = send_cmd(cmd);
487 if (ack < 0)
488 return ack;
489 return send_params(params);
490 }
491
492
493
494 inline static int exec_seek_cmd(int cmd, struct cdrom_msf *params)
495 {
496 int ack = send_cmd(cmd);
497 if (ack < 0)
498 return ack;
499 ack = send_seek_params(params);
500 if (ack < 0)
501 return ack;
502 return 0;
503 }
504
505
506
507 inline static int exec_long_cmd(int cmd, struct cdrom_msf *params)
508 {
509 int ack = exec_read_cmd(cmd, params);
510 if (ack < 0)
511 return ack;
512 return get_exec_status(0);
513 }
514
515
516
517
518
519 inline static void single_bin2bcd(u_char *p)
520 {
521 DEBUG((DEBUG_CONV, "bin2bcd %02d", *p));
522 *p = (*p % 10) | ((*p / 10) << 4);
523 }
524
525
526
527 static void bin2bcd(struct cdrom_msf *msf)
528 {
529 single_bin2bcd(&msf->cdmsf_min0);
530 single_bin2bcd(&msf->cdmsf_sec0);
531 single_bin2bcd(&msf->cdmsf_frame0);
532 single_bin2bcd(&msf->cdmsf_min1);
533 single_bin2bcd(&msf->cdmsf_sec1);
534 single_bin2bcd(&msf->cdmsf_frame1);
535 }
536
537
538
539 #define CD_FPM (CD_SECS * CD_FRAMES)
540
541 static void lba2msf(int lba, struct cdrom_msf *msf)
542 {
543 DEBUG((DEBUG_CONV, "lba2msf %d", lba));
544 lba += CD_MSF_OFFSET;
545 msf->cdmsf_min0 = lba / CD_FPM; lba %= CD_FPM;
546 msf->cdmsf_sec0 = lba / CD_FRAMES;
547 msf->cdmsf_frame0 = lba % CD_FRAMES;
548 msf->cdmsf_min1 = 0;
549 msf->cdmsf_sec1 = 0;
550 msf->cdmsf_frame1 = 0;
551 bin2bcd(msf);
552 }
553
554
555
556 inline static u_char bcd2bin(u_char bcd)
557 {
558 DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
559 return (bcd >> 4) * 10 + (bcd & 0x0f);
560 }
561
562
563 static void msf2lba(union cdrom_addr *addr)
564 {
565 addr->lba = addr->msf.minute * CD_FPM
566 + addr->msf.second * CD_FRAMES
567 + addr->msf.frame - CD_MSF_OFFSET;
568 }
569
570
571
572
573 static void msf_bcd2bin(union cdrom_addr *addr)
574 {
575 addr->msf.minute = bcd2bin(addr->msf.minute);
576 addr->msf.second = bcd2bin(addr->msf.second);
577 addr->msf.frame = bcd2bin(addr->msf.frame);
578 }
579
580
581
582
583 static int audio_status = CDROM_AUDIO_NO_STATUS;
584 static char toc_uptodate = 0;
585 static char disk_changed = 1;
586
587
588 static int drive_status(void)
589 {
590 int status;
591
592 status = exec_cmd(COMIOCTLISTAT);
593 DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
594 if (status < 0)
595 return status;
596 if (status == 0xff)
597 return -ERR_IF_NOSTAT;
598
599 if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
600 (audio_status == CDROM_AUDIO_PLAY)) {
601 audio_status = CDROM_AUDIO_COMPLETED;
602 }
603
604 if (status & ST_DSK_CHG) {
605 toc_uptodate = 0;
606 disk_changed = 1;
607 audio_status = CDROM_AUDIO_NO_STATUS;
608 }
609
610 return status;
611 }
612
613
614
615
616
617 static int get_q_channel(struct cdrom_subchnl *qp)
618 {
619 int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
620
621 status = drive_status();
622 if (status < 0)
623 return status;
624 qp->cdsc_audiostatus = audio_status;
625
626 status = exec_cmd(COMSUBQ);
627 if (status < 0)
628 return status;
629
630 d1 = get_data(0);
631 if (d1 < 0)
632 return d1;
633 qp->cdsc_adr = d1;
634 qp->cdsc_ctrl = d1 >> 4;
635
636 d2 = get_data(0);
637 if (d2 < 0)
638 return d2;
639 qp->cdsc_trk = bcd2bin(d2);
640
641 d3 = get_data(0);
642 if (d3 < 0)
643 return d3;
644 qp->cdsc_ind = bcd2bin(d3);
645
646 d4 = get_data(0);
647 if (d4 < 0)
648 return d4;
649 qp->cdsc_reladdr.msf.minute = d4;
650
651 d5 = get_data(0);
652 if (d5 < 0)
653 return d5;
654 qp->cdsc_reladdr.msf.second = d5;
655
656 d6 = get_data(0);
657 if (d6 < 0)
658 return d6;
659 qp->cdsc_reladdr.msf.frame = d6;
660
661 d7 = get_data(0);
662 if (d7 < 0)
663 return d7;
664
665
666 d8 = get_data(0);
667 if (d8 < 0)
668 return d8;
669 qp->cdsc_absaddr.msf.minute = d8;
670
671 d9 = get_data(0);
672 if (d9 < 0)
673 return d9;
674 qp->cdsc_absaddr.msf.second = d9;
675
676 d10 = get_data(0);
677 if (d10 < 0)
678 return d10;
679 qp->cdsc_absaddr.msf.frame = d10;
680
681 DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
682 d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
683
684 msf_bcd2bin(&qp->cdsc_absaddr);
685 msf_bcd2bin(&qp->cdsc_reladdr);
686 if (qp->cdsc_format == CDROM_LBA) {
687 msf2lba(&qp->cdsc_absaddr);
688 msf2lba(&qp->cdsc_reladdr);
689 }
690
691 return 0;
692 }
693
694
695
696
697
698 #define ERR_TOC_MISSINGINFO 0x120
699 #define ERR_TOC_MISSINGENTRY 0x121
700
701
702 struct cdrom_disk_info {
703 unsigned char first;
704 unsigned char last;
705 struct cdrom_msf0 disk_length;
706 struct cdrom_msf0 first_track;
707
708 unsigned char next;
709 struct cdrom_msf0 next_session;
710 struct cdrom_msf0 last_session;
711 unsigned char multi;
712 unsigned char xa;
713 unsigned char audio;
714 };
715 static struct cdrom_disk_info disk_info;
716
717 #define MAX_TRACKS 111
718 static struct cdrom_subchnl toc[MAX_TRACKS];
719
720 #define QINFO_FIRSTTRACK 100
721 #define QINFO_LASTTRACK 101
722 #define QINFO_DISKLENGTH 102
723 #define QINFO_NEXTSESSION 110
724
725 #define I_FIRSTTRACK 0x01
726 #define I_LASTTRACK 0x02
727 #define I_DISKLENGTH 0x04
728 #define I_NEXTSESSION 0x08
729 #define I_ALL (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
730
731
732 #if DEBUG_TOC
733 void toc_debug_info(int i)
734 {
735 printk("#%3d ctl %1x, adr %1x, track %2d index %3d"
736 " %2d:%02d.%02d %2d:%02d.%02d\n",
737 i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
738 toc[i].cdsc_trk, toc[i].cdsc_ind,
739 toc[i].cdsc_reladdr.msf.minute,
740 toc[i].cdsc_reladdr.msf.second,
741 toc[i].cdsc_reladdr.msf.frame,
742 toc[i].cdsc_absaddr.msf.minute,
743 toc[i].cdsc_absaddr.msf.second,
744 toc[i].cdsc_absaddr.msf.frame);
745 }
746 #endif
747
748
749 static int read_toc(void)
750 {
751 int status, limit, count;
752 unsigned char got_info = 0;
753 struct cdrom_subchnl q_info;
754 #if DEBUG_TOC
755 int i;
756 #endif
757
758 DEBUG((DEBUG_TOC, "starting read_toc"));
759
760 count = 0;
761 for (limit = 60; limit > 0; limit--) {
762 int index;
763
764 q_info.cdsc_format = CDROM_MSF;
765 status = get_q_channel(&q_info);
766 if (status < 0)
767 return status;
768
769 index = q_info.cdsc_ind;
770 if (index > 0 && index < MAX_TRACKS
771 && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
772 toc[index] = q_info;
773 DEBUG((DEBUG_TOC, "got %d", index));
774 if (index < 100)
775 count++;
776
777 switch (q_info.cdsc_ind) {
778 case QINFO_FIRSTTRACK:
779 got_info |= I_FIRSTTRACK;
780 break;
781 case QINFO_LASTTRACK:
782 got_info |= I_LASTTRACK;
783 break;
784 case QINFO_DISKLENGTH:
785 got_info |= I_DISKLENGTH;
786 break;
787 case QINFO_NEXTSESSION:
788 got_info |= I_NEXTSESSION;
789 break;
790 }
791 }
792
793 if ((got_info & I_ALL) == I_ALL
794 && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
795 >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
796 break;
797 }
798
799
800 if (disk_info.first == 0) {
801 disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
802 disk_info.first_track.minute =
803 toc[disk_info.first].cdsc_absaddr.msf.minute;
804 disk_info.first_track.second =
805 toc[disk_info.first].cdsc_absaddr.msf.second;
806 disk_info.first_track.frame =
807 toc[disk_info.first].cdsc_absaddr.msf.frame;
808 }
809 disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
810 disk_info.disk_length.minute =
811 toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
812 disk_info.disk_length.second =
813 toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
814 disk_info.disk_length.frame =
815 toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
816 disk_info.next_session.minute =
817 toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
818 disk_info.next_session.second =
819 toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
820 disk_info.next_session.frame =
821 toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
822 disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
823 disk_info.last_session.minute =
824 toc[disk_info.next].cdsc_absaddr.msf.minute;
825 disk_info.last_session.second =
826 toc[disk_info.next].cdsc_absaddr.msf.second;
827 disk_info.last_session.frame =
828 toc[disk_info.next].cdsc_absaddr.msf.frame;
829 toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
830 disk_info.disk_length.minute;
831 toc[disk_info.last + 1].cdsc_absaddr.msf.second =
832 disk_info.disk_length.second;
833 toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
834 disk_info.disk_length.frame;
835 #if DEBUG_TOC
836 for (i = 1; i <= disk_info.last + 1; i++)
837 toc_debug_info(i);
838 toc_debug_info(QINFO_FIRSTTRACK);
839 toc_debug_info(QINFO_LASTTRACK);
840 toc_debug_info(QINFO_DISKLENGTH);
841 toc_debug_info(QINFO_NEXTSESSION);
842 #endif
843
844 DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
845 got_info, count));
846 if ((got_info & I_ALL) != I_ALL
847 || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
848 < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
849 return -ERR_TOC_MISSINGINFO;
850 return 0;
851 }
852
853
854 #ifdef MULTISESSION
855 static int get_multi_disk_info(void)
856 {
857 int sessions, status;
858 struct cdrom_msf multi_index;
859
860
861 for (sessions = 2; sessions < 10 ; sessions++) {
862 int count;
863
864 for (count = 100; count < MAX_TRACKS; count++)
865 toc[count].cdsc_ind = 0;
866
867 multi_index.cdmsf_min0 = disk_info.next_session.minute;
868 multi_index.cdmsf_sec0 = disk_info.next_session.second;
869 multi_index.cdmsf_frame0 = disk_info.next_session.frame;
870 if (multi_index.cdmsf_sec0 >= 20)
871 multi_index.cdmsf_sec0 -= 20;
872 else {
873 multi_index.cdmsf_sec0 += 40;
874 multi_index.cdmsf_min0--;
875 }
876 DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
877 multi_index.cdmsf_min0,
878 multi_index.cdmsf_sec0,
879 multi_index.cdmsf_frame0));
880 bin2bcd(&multi_index);
881 multi_index.cdmsf_min1 = 0;
882 multi_index.cdmsf_sec1 = 0;
883 multi_index.cdmsf_frame1 = 1;
884
885 status = exec_read_cmd(COMREAD, &multi_index);
886 if (status < 0) {
887 DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
888 -status));
889 break;
890 }
891 status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
892 0 : -ERR_TOC_MISSINGINFO;
893 flush_data();
894 if (status < 0) {
895 DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
896 break;
897 }
898
899 status = read_toc();
900 if (status < 0) {
901 DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
902 break;
903 }
904
905 disk_info.multi = 1;
906 }
907
908 exec_cmd(COMSTOP);
909
910 if (status < 0)
911 return -EIO;
912 return 0;
913 }
914 #endif MULTISESSION
915
916
917 static int update_toc(void)
918 {
919 int status, count;
920
921 if (toc_uptodate)
922 return 0;
923
924 DEBUG((DEBUG_TOC, "starting update_toc"));
925
926 disk_info.first = 0;
927 for (count = 0; count < MAX_TRACKS; count++)
928 toc[count].cdsc_ind = 0;
929
930 status = exec_cmd(COMLEADIN);
931 if (status < 0)
932 return -EIO;
933
934 status = read_toc();
935 if (status < 0) {
936 DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
937 return -EIO;
938 }
939
940
941 disk_info.audio =
942 (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
943
944
945 disk_info.xa = drive_status() & ST_MODE2TRACK;
946
947
948 disk_info.multi = 0;
949 #ifdef MULTISESSION
950 if (disk_info.xa)
951 get_multi_disk_info();
952 #endif MULTISESSION
953 if (disk_info.multi)
954 printk("optcd: Multisession support experimental, "
955 "see linux/Documentation/cdrom/optcd\n");
956
957 DEBUG((DEBUG_TOC, "exiting update_toc"));
958
959 toc_uptodate = 1;
960 return 0;
961 }
962
963
964
965
966 #define CURRENT_VALID \
967 (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR \
968 && CURRENT -> cmd == READ && CURRENT -> sector != -1)
969
970
971
972 #define NOBUF -1
973
974 static char buf[CD_FRAMESIZE * N_BUFS];
975 static volatile int buf_bn[N_BUFS], next_bn;
976 static volatile int buf_in = 0, buf_out = NOBUF;
977
978 inline static void opt_invalidate_buffers(void)
979 {
980 int i;
981
982 DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
983
984 for (i = 0; i < N_BUFS; i++)
985 buf_bn[i] = NOBUF;
986 buf_out = NOBUF;
987 }
988
989
990
991
992 static void transfer(void)
993 {
994 #if DEBUG_BUFFERS | DEBUG_REQUEST
995 printk("optcd: executing transfer\n");
996 #endif
997
998 if (!CURRENT_VALID)
999 return;
1000 while (CURRENT -> nr_sectors) {
1001 int bn = CURRENT -> sector / 4;
1002 int i, offs, nr_sectors;
1003 for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
1004
1005 DEBUG((DEBUG_REQUEST, "found %d", i));
1006
1007 if (i >= N_BUFS) {
1008 buf_out = NOBUF;
1009 break;
1010 }
1011
1012 offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
1013 nr_sectors = 4 - (CURRENT -> sector & 3);
1014
1015 if (buf_out != i) {
1016 buf_out = i;
1017 if (buf_bn[i] != bn) {
1018 buf_out = NOBUF;
1019 continue;
1020 }
1021 }
1022
1023 if (nr_sectors > CURRENT -> nr_sectors)
1024 nr_sectors = CURRENT -> nr_sectors;
1025 memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
1026 CURRENT -> nr_sectors -= nr_sectors;
1027 CURRENT -> sector += nr_sectors;
1028 CURRENT -> buffer += nr_sectors * 512;
1029 }
1030 }
1031
1032
1033
1034
1035 enum state_e {
1036 S_IDLE,
1037 S_START,
1038 S_READ,
1039 S_DATA,
1040 S_STOP,
1041 S_STOPPING
1042 };
1043
1044 static volatile enum state_e state = S_IDLE;
1045 #if DEBUG_STATE
1046 static volatile enum state_e state_old = S_STOP;
1047 static volatile int flags_old = 0;
1048 static volatile long state_n = 0;
1049 #endif
1050
1051
1052
1053
1054
1055
1056 static int in_vfs = 0;
1057
1058
1059 static volatile int transfer_is_active = 0;
1060 static volatile int error = 0;
1061 static int tries;
1062 static int timeout = 0;
1063
1064 static struct timer_list req_timer = {NULL, NULL, 0, 0, NULL};
1065
1066 #define SET_REQ_TIMER(func, jifs) \
1067 req_timer.expires = jiffies+(jifs); \
1068 req_timer.function = (void *) (func); \
1069 add_timer(&req_timer);
1070 #define CLEAR_REQ_TIMER del_timer(&req_timer)
1071
1072 static void poll(void)
1073 {
1074 static volatile int read_count = 1;
1075 int flags;
1076 int loop_again = 1;
1077 int status = 0;
1078 int skip = 0;
1079
1080 if (error) {
1081 printk("optcd: I/O error 0x%02x\n", error);
1082 opt_invalidate_buffers();
1083 if (!tries--) {
1084 printk("optcd: read block %d failed; Giving up\n",
1085 next_bn);
1086 if (transfer_is_active)
1087 loop_again = 0;
1088 if (CURRENT_VALID)
1089 end_request(0);
1090 tries = 5;
1091 }
1092 error = 0;
1093 state = S_STOP;
1094 }
1095
1096 while (loop_again)
1097 {
1098 loop_again = 0;
1099
1100
1101 #if DEBUG_STATE
1102 if (state == state_old)
1103 state_n++;
1104 else {
1105 state_old = state;
1106 if (++state_n > 1)
1107 printk("optcd: %ld times in previous state\n",
1108 state_n);
1109 printk("optcd: state %d\n", state);
1110 state_n = 0;
1111 }
1112 #endif
1113
1114 switch (state) {
1115 case S_IDLE:
1116 return;
1117 case S_START:
1118 if (in_vfs)
1119 break;
1120 if (send_cmd(COMDRVST)) {
1121 state = S_IDLE;
1122 while (CURRENT_VALID)
1123 end_request(0);
1124 return;
1125 }
1126 state = S_READ;
1127 timeout = READ_TIMEOUT;
1128 break;
1129 case S_READ: {
1130 struct cdrom_msf msf;
1131 if (!skip) {
1132 status = fetch_status();
1133 if (status < 0)
1134 break;
1135 if (status & ST_DSK_CHG) {
1136 toc_uptodate = 0;
1137 opt_invalidate_buffers();
1138 }
1139 }
1140 skip = 0;
1141 if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
1142 toc_uptodate = 0;
1143 opt_invalidate_buffers();
1144 printk((status & ST_DOOR_OPEN)
1145 ? "optcd: door open\n"
1146 : "optcd: disk removed\n");
1147 state = S_IDLE;
1148 while (CURRENT_VALID)
1149 end_request(0);
1150 return;
1151 }
1152 if (!CURRENT_VALID) {
1153 state = S_STOP;
1154 loop_again = 1;
1155 break;
1156 }
1157 next_bn = CURRENT -> sector / 4;
1158 lba2msf(next_bn, &msf);
1159 read_count = N_BUFS;
1160 msf.cdmsf_frame1 = read_count;
1161
1162 DEBUG((DEBUG_REQUEST, "reading %x:%x.%x %x:%x.%x",
1163 msf.cdmsf_min0,
1164 msf.cdmsf_sec0,
1165 msf.cdmsf_frame0,
1166 msf.cdmsf_min1,
1167 msf.cdmsf_sec1,
1168 msf.cdmsf_frame1));
1169 DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d"
1170 " buf_out:%d buf_bn:%d",
1171 next_bn,
1172 buf_in,
1173 buf_out,
1174 buf_bn[buf_in]));
1175
1176 exec_read_cmd(COMREAD, &msf);
1177 state = S_DATA;
1178 timeout = READ_TIMEOUT;
1179 break;
1180 }
1181 case S_DATA:
1182 flags = stdt_flags() & (FL_STEN|FL_DTEN);
1183
1184 #if DEBUG_STATE
1185 if (flags != flags_old) {
1186 flags_old = flags;
1187 printk("optcd: flags:%x\n", flags);
1188 }
1189 if (flags == FL_STEN)
1190 printk("timeout cnt: %d\n", timeout);
1191 #endif
1192
1193 switch (flags) {
1194 case FL_DTEN:
1195 if (!tries--) {
1196 printk("optcd: read block %d failed; "
1197 "Giving up\n", next_bn);
1198 if (transfer_is_active) {
1199 tries = 0;
1200 break;
1201 }
1202 if (CURRENT_VALID)
1203 end_request(0);
1204 tries = 5;
1205 }
1206 state = S_START;
1207 timeout = READ_TIMEOUT;
1208 loop_again = 1;
1209 case (FL_STEN|FL_DTEN):
1210 break;
1211 default:
1212 tries = 5;
1213 if (!CURRENT_VALID && buf_in == buf_out) {
1214 state = S_STOP;
1215 loop_again = 1;
1216 break;
1217 }
1218 if (read_count<=0)
1219 printk("optcd: warning - try to read"
1220 " 0 frames\n");
1221 while (read_count) {
1222 buf_bn[buf_in] = NOBUF;
1223 if (!flag_low(FL_DTEN, BUSY_TIMEOUT)) {
1224
1225 printk("read_count:%d "
1226 "CURRENT->nr_sectors:%ld "
1227 "buf_in:%d\n",
1228 read_count,
1229 CURRENT->nr_sectors,
1230 buf_in);
1231 printk("transfer active: %x\n",
1232 transfer_is_active);
1233 read_count = 0;
1234 state = S_STOP;
1235 loop_again = 1;
1236 end_request(0);
1237 break;
1238 }
1239 fetch_data(buf+
1240 CD_FRAMESIZE*buf_in,
1241 CD_FRAMESIZE);
1242 read_count--;
1243
1244 DEBUG((DEBUG_REQUEST,
1245 "S_DATA; ---I've read data- "
1246 "read_count: %d",
1247 read_count));
1248 DEBUG((DEBUG_REQUEST,
1249 "next_bn:%d buf_in:%d "
1250 "buf_out:%d buf_bn:%d",
1251 next_bn,
1252 buf_in,
1253 buf_out,
1254 buf_bn[buf_in]));
1255
1256 buf_bn[buf_in] = next_bn++;
1257 if (buf_out == NOBUF)
1258 buf_out = buf_in;
1259 buf_in = buf_in + 1 ==
1260 N_BUFS ? 0 : buf_in + 1;
1261 }
1262 if (!transfer_is_active) {
1263 while (CURRENT_VALID) {
1264 transfer();
1265 if (CURRENT -> nr_sectors == 0)
1266 end_request(1);
1267 else
1268 break;
1269 }
1270 }
1271
1272 if (CURRENT_VALID
1273 && (CURRENT -> sector / 4 < next_bn ||
1274 CURRENT -> sector / 4 >
1275 next_bn + N_BUFS)) {
1276 state = S_STOP;
1277 loop_again = 1;
1278 break;
1279 }
1280 timeout = READ_TIMEOUT;
1281 if (read_count == 0) {
1282 state = S_STOP;
1283 loop_again = 1;
1284 break;
1285 }
1286 }
1287 break;
1288 case S_STOP:
1289 if (read_count != 0)
1290 printk("optcd: discard data=%x frames\n",
1291 read_count);
1292 flush_data();
1293 if (send_cmd(COMDRVST)) {
1294 state = S_IDLE;
1295 while (CURRENT_VALID)
1296 end_request(0);
1297 return;
1298 }
1299 state = S_STOPPING;
1300 timeout = STOP_TIMEOUT;
1301 break;
1302 case S_STOPPING:
1303 status = fetch_status();
1304 if (status < 0 && timeout)
1305 break;
1306 if ((status >= 0) && (status & ST_DSK_CHG)) {
1307 toc_uptodate = 0;
1308 opt_invalidate_buffers();
1309 }
1310 if (CURRENT_VALID) {
1311 if (status >= 0) {
1312 state = S_READ;
1313 loop_again = 1;
1314 skip = 1;
1315 break;
1316 } else {
1317 state = S_START;
1318 timeout = 1;
1319 }
1320 } else {
1321 state = S_IDLE;
1322 return;
1323 }
1324 break;
1325 default:
1326 printk("optcd: invalid state %d\n", state);
1327 return;
1328 }
1329 }
1330
1331 if (!timeout--) {
1332 printk("optcd: timeout in state %d\n", state);
1333 state = S_STOP;
1334 if (exec_cmd(COMSTOP) < 0) {
1335 state = S_IDLE;
1336 while (CURRENT_VALID)
1337 end_request(0);
1338 return;
1339 }
1340 }
1341
1342 SET_REQ_TIMER(poll, HZ/100);
1343 }
1344
1345
1346 static void do_optcd_request(void)
1347 {
1348 DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
1349 CURRENT -> sector, CURRENT -> nr_sectors));
1350
1351 if (disk_info.audio) {
1352 printk("optcd: Error: tried to mount an Audio CD\n");
1353 end_request(0);
1354 return;
1355 }
1356
1357 transfer_is_active = 1;
1358 while (CURRENT_VALID) {
1359 if (CURRENT->bh) {
1360 if (!buffer_locked(CURRENT->bh))
1361 panic(DEVICE_NAME ": block not locked");
1362 }
1363 transfer();
1364 if (CURRENT -> nr_sectors == 0) {
1365 end_request(1);
1366 } else {
1367 buf_out = NOBUF;
1368 if (state == S_IDLE) {
1369
1370 if (update_toc() < 0) {
1371 while (CURRENT_VALID)
1372 end_request(0);
1373 break;
1374 }
1375
1376 state = S_START;
1377 timeout = READ_TIMEOUT;
1378 tries = 5;
1379
1380 SET_REQ_TIMER(poll, HZ/100);
1381 }
1382 break;
1383 }
1384 }
1385 transfer_is_active = 0;
1386
1387 DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d buf_out:%d buf_bn:%d",
1388 next_bn, buf_in, buf_out, buf_bn[buf_in]));
1389 DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
1390 }
1391
1392
1393
1394
1395 static char auto_eject = 0;
1396
1397 static int cdrompause(void)
1398 {
1399 int status;
1400
1401 if (audio_status != CDROM_AUDIO_PLAY)
1402 return -EINVAL;
1403
1404 status = exec_cmd(COMPAUSEON);
1405 if (status < 0) {
1406 DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
1407 return -EIO;
1408 }
1409 audio_status = CDROM_AUDIO_PAUSED;
1410 return 0;
1411 }
1412
1413
1414 static int cdromresume(void)
1415 {
1416 int status;
1417
1418 if (audio_status != CDROM_AUDIO_PAUSED)
1419 return -EINVAL;
1420
1421 status = exec_cmd(COMPAUSEOFF);
1422 if (status < 0) {
1423 DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
1424 audio_status = CDROM_AUDIO_ERROR;
1425 return -EIO;
1426 }
1427 audio_status = CDROM_AUDIO_PLAY;
1428 return 0;
1429 }
1430
1431
1432 static int cdromplaymsf(unsigned long arg)
1433 {
1434 int status;
1435 struct cdrom_msf msf;
1436
1437 status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
1438 if (status)
1439 return status;
1440 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1441
1442 bin2bcd(&msf);
1443 status = exec_long_cmd(COMPLAY, &msf);
1444 if (status < 0) {
1445 DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
1446 audio_status = CDROM_AUDIO_ERROR;
1447 return -EIO;
1448 }
1449
1450 audio_status = CDROM_AUDIO_PLAY;
1451 return 0;
1452 }
1453
1454
1455 static int cdromplaytrkind(unsigned long arg)
1456 {
1457 int status;
1458 struct cdrom_ti ti;
1459 struct cdrom_msf msf;
1460
1461 status = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
1462 if (status)
1463 return status;
1464 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
1465
1466 if (ti.cdti_trk0 < disk_info.first
1467 || ti.cdti_trk0 > disk_info.last
1468 || ti.cdti_trk1 < ti.cdti_trk0)
1469 return -EINVAL;
1470 if (ti.cdti_trk1 > disk_info.last)
1471 ti.cdti_trk1 = disk_info.last;
1472
1473 msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
1474 msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
1475 msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
1476 msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
1477 msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
1478 msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
1479
1480 DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
1481 msf.cdmsf_min0,
1482 msf.cdmsf_sec0,
1483 msf.cdmsf_frame0,
1484 msf.cdmsf_min1,
1485 msf.cdmsf_sec1,
1486 msf.cdmsf_frame1));
1487
1488 bin2bcd(&msf);
1489 status = exec_long_cmd(COMPLAY, &msf);
1490 if (status < 0) {
1491 DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
1492 audio_status = CDROM_AUDIO_ERROR;
1493 return -EIO;
1494 }
1495
1496 audio_status = CDROM_AUDIO_PLAY;
1497 return 0;
1498 }
1499
1500
1501 static int cdromreadtochdr(unsigned long arg)
1502 {
1503 int status;
1504 struct cdrom_tochdr tochdr;
1505
1506 status = verify_area(VERIFY_WRITE, (void *) arg, sizeof tochdr);
1507 if (status)
1508 return status;
1509
1510 tochdr.cdth_trk0 = disk_info.first;
1511 tochdr.cdth_trk1 = disk_info.last;
1512
1513 memcpy_tofs((void *) arg, &tochdr, sizeof tochdr);
1514 return 0;
1515 }
1516
1517
1518 static int cdromreadtocentry(unsigned long arg)
1519 {
1520 int status;
1521 struct cdrom_tocentry entry;
1522 struct cdrom_subchnl *tocptr;
1523
1524 status = verify_area(VERIFY_READ, (void *) arg, sizeof entry);
1525 if (status)
1526 return status;
1527 status = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
1528 if (status)
1529 return status;
1530 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
1531
1532 if (entry.cdte_track == CDROM_LEADOUT)
1533 tocptr = &toc[disk_info.last + 1];
1534 else if (entry.cdte_track > disk_info.last
1535 || entry.cdte_track < disk_info.first)
1536 return -EINVAL;
1537 else
1538 tocptr = &toc[entry.cdte_track];
1539
1540 entry.cdte_adr = tocptr->cdsc_adr;
1541 entry.cdte_ctrl = tocptr->cdsc_ctrl;
1542 entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
1543 entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
1544 entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
1545
1546
1547 if (entry.cdte_format == CDROM_LBA)
1548 msf2lba(&entry.cdte_addr);
1549 else if (entry.cdte_format != CDROM_MSF)
1550 return -EINVAL;
1551
1552 memcpy_tofs((void *) arg, &entry, sizeof entry);
1553 return 0;
1554 }
1555
1556
1557 static int cdromvolctrl(unsigned long arg)
1558 {
1559 int status;
1560 struct cdrom_volctrl volctrl;
1561 struct cdrom_msf msf;
1562
1563 status = verify_area(VERIFY_READ, (void *) arg, sizeof volctrl);
1564 if (status)
1565 return status;
1566 memcpy_fromfs(&volctrl, (char *) arg, sizeof volctrl);
1567
1568 msf.cdmsf_min0 = 0x10;
1569 msf.cdmsf_sec0 = 0x32;
1570 msf.cdmsf_frame0 = volctrl.channel0;
1571 msf.cdmsf_min1 = volctrl.channel1;
1572 msf.cdmsf_sec1 = volctrl.channel2;
1573 msf.cdmsf_frame1 = volctrl.channel3;
1574
1575 status = exec_long_cmd(COMCHCTRL, &msf);
1576 if (status < 0) {
1577 DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
1578 return -EIO;
1579 }
1580 return 0;
1581 }
1582
1583
1584 static int cdromsubchnl(unsigned long arg)
1585 {
1586 int status;
1587 struct cdrom_subchnl subchnl;
1588
1589 status = verify_area(VERIFY_READ, (void *) arg, sizeof subchnl);
1590 if (status)
1591 return status;
1592 status = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
1593 if (status)
1594 return status;
1595 memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
1596
1597 if (subchnl.cdsc_format != CDROM_LBA
1598 && subchnl.cdsc_format != CDROM_MSF)
1599 return -EINVAL;
1600
1601 status = get_q_channel(&subchnl);
1602 if (status < 0) {
1603 DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
1604 return -EIO;
1605 }
1606
1607 memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
1608 return 0;
1609 }
1610
1611
1612 static int cdromread(unsigned long arg, int blocksize, int cmd)
1613 {
1614 int status;
1615 struct cdrom_msf msf;
1616 char buf[CD_FRAMESIZE_RAWER];
1617
1618 status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
1619 if (status)
1620 return status;
1621 status = verify_area(VERIFY_WRITE, (void *) arg, blocksize);
1622 if (status)
1623 return status;
1624 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1625
1626 bin2bcd(&msf);
1627 msf.cdmsf_min1 = 0;
1628 msf.cdmsf_sec1 = 0;
1629 msf.cdmsf_frame1 = 1;
1630 status = exec_read_cmd(cmd, &msf);
1631
1632 DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
1633
1634 if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
1635 return -EIO;
1636 fetch_data(buf, blocksize);
1637
1638 memcpy_tofs((void *) arg, &buf, blocksize);
1639 return 0;
1640 }
1641
1642
1643 static int cdromseek(unsigned long arg)
1644 {
1645 int status;
1646 struct cdrom_msf msf;
1647
1648 status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
1649 if (status)
1650 return status;
1651 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1652
1653 bin2bcd(&msf);
1654 status = exec_seek_cmd(COMSEEK, &msf);
1655
1656 DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
1657
1658 if (status < 0)
1659 return -EIO;
1660 return 0;
1661 }
1662
1663
1664 #ifdef MULTISESSION
1665 static int cdrommultisession(unsigned long arg)
1666 {
1667 int status;
1668 struct cdrom_multisession ms;
1669
1670 status = verify_area(VERIFY_READ, (void*) arg, sizeof ms);
1671 if (status)
1672 return status;
1673 status = verify_area(VERIFY_WRITE, (void*) arg, sizeof ms);
1674 if (status)
1675 return status;
1676 memcpy_fromfs(&ms, (void*) arg, sizeof ms);
1677
1678 ms.addr.msf.minute = disk_info.last_session.minute;
1679 ms.addr.msf.second = disk_info.last_session.second;
1680 ms.addr.msf.frame = disk_info.last_session.frame;
1681
1682 if (ms.addr_format != CDROM_LBA
1683 && ms.addr_format != CDROM_MSF)
1684 return -EINVAL;
1685 if (ms.addr_format == CDROM_LBA)
1686 msf2lba(&ms.addr);
1687
1688 ms.xa_flag = disk_info.xa;
1689
1690 memcpy_tofs((void*) arg, &ms,
1691 sizeof(struct cdrom_multisession));
1692
1693 #if DEBUG_MULTIS
1694 if (ms.addr_format == CDROM_MSF)
1695 printk("optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
1696 ms.xa_flag,
1697 ms.addr.msf.minute,
1698 ms.addr.msf.second,
1699 ms.addr.msf.frame);
1700 else
1701 printk("optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
1702 ms.xa_flag,
1703 ms.addr.lba,
1704 disk_info.last_session.minute,
1705 disk_info.last_session.second,
1706 disk_info.last_session.frame);
1707 #endif DEBUG_MULTIS
1708
1709 return 0;
1710 }
1711 #endif MULTISESSION
1712
1713
1714 static int cdromreset(void)
1715 {
1716 if (state != S_IDLE) {
1717 error = 1;
1718 tries = 0;
1719 }
1720
1721 toc_uptodate = 0;
1722 disk_changed = 1;
1723 opt_invalidate_buffers();
1724 audio_status = CDROM_AUDIO_NO_STATUS;
1725
1726 if (!reset_drive())
1727 return -EIO;
1728 return 0;
1729 }
1730
1731
1732
1733
1734 static int opt_ioctl(struct inode *ip, struct file *fp,
1735 unsigned int cmd, unsigned long arg)
1736 {
1737 int status, err, retval = 0;
1738
1739 DEBUG((DEBUG_VFS, "starting opt_ioctl"));
1740
1741 if (!ip)
1742 return -EINVAL;
1743
1744 if (cmd == CDROMRESET)
1745 return cdromreset();
1746
1747
1748 if (state != S_IDLE || in_vfs)
1749 return -EBUSY;
1750
1751 in_vfs = 1;
1752
1753 status = drive_status();
1754 if (status < 0) {
1755 DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
1756 in_vfs = 0;
1757 return -EIO;
1758 }
1759
1760 if (status & ST_DOOR_OPEN)
1761 switch (cmd) {
1762 case CDROMCLOSETRAY:
1763
1764 err = exec_cmd(COMCLOSE);
1765 if (err < 0) {
1766 DEBUG((DEBUG_VFS,
1767 "exec_cmd COMCLOSE: %02x", -err));
1768 in_vfs = 0;
1769 return -EIO;
1770 }
1771 break;
1772 default: in_vfs = 0;
1773 return -EBUSY;
1774 }
1775
1776 err = update_toc();
1777 if (err < 0) {
1778 DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
1779 in_vfs = 0;
1780 return -EIO;
1781 }
1782
1783 DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
1784
1785 switch (cmd) {
1786 case CDROMPAUSE: retval = cdrompause(); break;
1787 case CDROMRESUME: retval = cdromresume(); break;
1788 case CDROMPLAYMSF: retval = cdromplaymsf(arg); break;
1789 case CDROMPLAYTRKIND: retval = cdromplaytrkind(arg); break;
1790 case CDROMREADTOCHDR: retval = cdromreadtochdr(arg); break;
1791 case CDROMREADTOCENTRY: retval = cdromreadtocentry(arg); break;
1792
1793 case CDROMSTOP: err = exec_cmd(COMSTOP);
1794 if (err < 0) {
1795 DEBUG((DEBUG_VFS,
1796 "exec_cmd COMSTOP: %02x",
1797 -err));
1798 retval = -EIO;
1799 } else
1800 audio_status = CDROM_AUDIO_NO_STATUS;
1801 break;
1802 case CDROMSTART: break;
1803 case CDROMEJECT: err = exec_cmd(COMUNLOCK);
1804 if (err < 0) {
1805 DEBUG((DEBUG_VFS,
1806 "exec_cmd COMUNLOCK: %02x",
1807 -err));
1808 retval = -EIO;
1809 break;
1810 }
1811 err = exec_cmd(COMOPEN);
1812 if (err < 0) {
1813 DEBUG((DEBUG_VFS,
1814 "exec_cmd COMOPEN: %02x",
1815 -err));
1816 retval = -EIO;
1817 }
1818 break;
1819
1820 case CDROMVOLCTRL: retval = cdromvolctrl(arg); break;
1821 case CDROMSUBCHNL: retval = cdromsubchnl(arg); break;
1822
1823
1824
1825 case CDROMREADMODE2: retval = -EINVAL; break;
1826 case CDROMREADMODE1: retval = -EINVAL; break;
1827
1828
1829 case CDROMREADAUDIO: retval = -EINVAL; break;
1830
1831 case CDROMEJECT_SW: auto_eject = (char) arg;
1832 break;
1833
1834 #ifdef MULTISESSION
1835 case CDROMMULTISESSION: retval = cdrommultisession(arg); break;
1836 #endif
1837
1838 case CDROM_GET_UPC: retval = -EINVAL; break;
1839 case CDROMVOLREAD: retval = -EINVAL; break;
1840
1841 case CDROMREADRAW:
1842
1843 retval = cdromread(arg, CD_FRAMESIZE_RAW1, COMREADRAW);
1844 break;
1845 case CDROMREADCOOKED:
1846 retval = cdromread(arg, CD_FRAMESIZE, COMREAD);
1847 break;
1848 case CDROMREADALL:
1849 retval = cdromread(arg, CD_FRAMESIZE_RAWER, COMREADALL);
1850 break;
1851
1852 case CDROMSEEK: retval = cdromseek(arg); break;
1853 case CDROMPLAYBLK: retval = -EINVAL; break;
1854 case CDROMCLOSETRAY: break;
1855 default: retval = -EINVAL;
1856 }
1857 in_vfs = 0;
1858 return retval;
1859 }
1860
1861
1862 static int open_count = 0;
1863
1864
1865 static int opt_open(struct inode *ip, struct file *fp)
1866 {
1867 DEBUG((DEBUG_VFS, "starting opt_open"));
1868
1869 if (!open_count && state == S_IDLE) {
1870 int status;
1871
1872 toc_uptodate = 0;
1873 opt_invalidate_buffers();
1874
1875 status = exec_cmd(COMCLOSE);
1876 if (status < 0) {
1877 DEBUG((DEBUG_VFS, "exec_cmd COMCLOSE: %02x", -status));
1878 }
1879
1880 status = drive_status();
1881 if (status < 0) {
1882 DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
1883 return -EIO;
1884 }
1885 DEBUG((DEBUG_VFS, "status: %02x", status));
1886 if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
1887 printk("optcd: no disk or door open\n");
1888 return -EIO;
1889 }
1890 status = exec_cmd(COMLOCK);
1891 if (status < 0) {
1892 DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
1893 }
1894 status = update_toc();
1895 if (status < 0) {
1896 DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
1897 status = exec_cmd(COMUNLOCK);
1898 if (status < 0) {
1899 DEBUG((DEBUG_VFS,
1900 "exec_cmd COMUNLOCK: %02x", -status));
1901 }
1902 return -EIO;
1903 }
1904 open_count++;
1905 }
1906 MOD_INC_USE_COUNT;
1907
1908 DEBUG((DEBUG_VFS, "exiting opt_open"));
1909
1910 return 0;
1911 }
1912
1913
1914
1915 static void opt_release(struct inode *ip, struct file *fp)
1916 {
1917 int status;
1918
1919 DEBUG((DEBUG_VFS, "executing opt_release"));
1920 DEBUG((DEBUG_VFS, "inode: %p, inode -> i_rdev: 0x%x, file: %p\n",
1921 ip, ip -> i_rdev, fp));
1922
1923 if (!--open_count) {
1924 toc_uptodate = 0;
1925 opt_invalidate_buffers();
1926 sync_dev(ip -> i_rdev);
1927 invalidate_buffers(ip -> i_rdev);
1928 status = exec_cmd(COMUNLOCK);
1929 if (status < 0) {
1930 DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
1931 }
1932 if (auto_eject) {
1933 status = exec_cmd(COMOPEN);
1934 DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
1935 }
1936 CLEAR_TIMER;
1937 CLEAR_REQ_TIMER;
1938 }
1939 MOD_DEC_USE_COUNT;
1940 }
1941
1942
1943
1944 static int opt_media_change(kdev_t dev)
1945 {
1946 DEBUG((DEBUG_VFS, "executing opt_media_change"));
1947 DEBUG((DEBUG_VFS, "dev: 0x%x; disk_changed = %d\n", dev, disk_changed));
1948
1949 if (disk_changed) {
1950 disk_changed = 0;
1951 return 1;
1952 }
1953 return 0;
1954 }
1955
1956
1957
1958
1959
1960
1961 static int version_ok(void)
1962 {
1963 char devname[100];
1964 int count, i, ch, status;
1965
1966 status = exec_cmd(COMVERSION);
1967 if (status < 0) {
1968 DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
1969 return 0;
1970 }
1971 if ((count = get_data(1)) < 0) {
1972 DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
1973 return 0;
1974 }
1975 for (i = 0, ch = -1; count > 0; count--) {
1976 if ((ch = get_data(1)) < 0) {
1977 DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
1978 break;
1979 }
1980 if (i < 99)
1981 devname[i++] = ch;
1982 }
1983 devname[i] = '\0';
1984 if (ch < 0)
1985 return 0;
1986
1987 printk("optcd: Device %s detected\n", devname);
1988 return ((devname[0] == 'D')
1989 && (devname[1] == 'O')
1990 && (devname[2] == 'L')
1991 && (devname[3] == 'P')
1992 && (devname[4] == 'H')
1993 && (devname[5] == 'I')
1994 && (devname[6] == 'N'));
1995 }
1996
1997
1998 static struct file_operations opt_fops = {
1999 NULL,
2000 block_read,
2001 block_write,
2002 NULL,
2003 NULL,
2004 opt_ioctl,
2005 NULL,
2006 opt_open,
2007 opt_release,
2008 NULL,
2009 NULL,
2010 opt_media_change,
2011 NULL
2012 };
2013
2014
2015
2016 void optcd_setup(char *str, int *ints)
2017 {
2018 if (ints[0] > 0)
2019 optcd_port = ints[1];
2020 }
2021
2022
2023
2024 int optcd_init(void)
2025 {
2026 int status;
2027
2028 if (optcd_port <= 0) {
2029 printk("optcd: no Optics Storage CDROM Initialization\n");
2030 return -EIO;
2031 }
2032 if (check_region(optcd_port, 4)) {
2033 printk("optcd: conflict, I/O port 0x%x already used\n",
2034 optcd_port);
2035 return -EIO;
2036 }
2037
2038 if (!reset_drive()) {
2039 printk("optcd: drive at 0x%x not ready\n", optcd_port);
2040 return -EIO;
2041 }
2042 if (!version_ok()) {
2043 printk("optcd: unknown drive detected; aborting\n");
2044 return -EIO;
2045 }
2046 status = exec_cmd(COMINITDOUBLE);
2047 if (status < 0) {
2048 printk("optcd: cannot init double speed mode\n");
2049 DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
2050 return -EIO;
2051 }
2052 if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0)
2053 {
2054 printk("optcd: unable to get major %d\n", MAJOR_NR);
2055 return -EIO;
2056 }
2057
2058 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
2059 read_ahead[MAJOR_NR] = 4;
2060 request_region(optcd_port, 4, "optcd");
2061
2062 printk("optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
2063 return 0;
2064 }
2065
2066
2067 #ifdef MODULE
2068 int init_module(void)
2069 {
2070 return optcd_init();
2071 }
2072
2073
2074 void cleanup_module(void)
2075 {
2076 if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
2077 printk("optcd: what's that: can't unregister\n");
2078 return;
2079 }
2080 release_region(optcd_port, 4);
2081 printk("optcd: module released.\n");
2082 }
2083 #endif MODULE