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
- 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 static void lba2msf(int lba, struct cdrom_msf *msf)
540 {
541 DEBUG((DEBUG_CONV, "lba2msf %d", lba));
542 lba += CD_MSF_OFFSET;
543 msf->cdmsf_min0 = lba / 4500; lba %= 4500;
544 msf->cdmsf_sec0 = lba / 75;
545 msf->cdmsf_frame0 = lba % 75;
546 msf->cdmsf_min1 = 0;
547 msf->cdmsf_sec1 = 0;
548 msf->cdmsf_frame1 = 0;
549 bin2bcd(msf);
550 }
551
552
553
554 inline static u_char bcd2bin(u_char bcd)
555 {
556 DEBUG((DEBUG_CONV, "bcd2bin %x%02x", bcd));
557 return (bcd >> 4) * 10 + (bcd & 0x0f);
558 }
559
560
561 union cd_addr {
562 struct {
563 u_char minute;
564 u_char second;
565 u_char frame;
566 } msf;
567 int lba;
568 };
569
570
571 static void msf2lba(union cd_addr *addr)
572 {
573 addr->lba = addr->msf.minute * 4500
574 + addr->msf.second * 75
575 + addr->msf.frame - CD_MSF_OFFSET;
576 }
577
578
579
580
581 static void msf_bcd2bin(union cd_addr *addr)
582 {
583 addr->msf.minute = bcd2bin(addr->msf.minute);
584 addr->msf.second = bcd2bin(addr->msf.second);
585 addr->msf.frame = bcd2bin(addr->msf.frame);
586 }
587
588
589
590
591 static int audio_status = CDROM_AUDIO_NO_STATUS;
592 static char toc_uptodate = 0;
593
594
595 static int drive_status(void)
596 {
597 int status;
598
599 status = exec_cmd(COMIOCTLISTAT);
600 DEBUG((DEBUG_DRIVE_IF, "IOCTLISTAT: %03x", status));
601 if (status < 0)
602 return status;
603 if (status == 0xff)
604 return -ERR_IF_NOSTAT;
605
606 if (((status & ST_MODE_BITS) != ST_M_AUDIO) &&
607 (audio_status == CDROM_AUDIO_PLAY)) {
608 audio_status = CDROM_AUDIO_COMPLETED;
609 }
610
611 if (status & ST_DSK_CHG) {
612 toc_uptodate = 0;
613 audio_status = CDROM_AUDIO_NO_STATUS;
614 }
615
616 return status;
617 }
618
619
620
621
622
623 static int get_q_channel(struct cdrom_subchnl *qp)
624 {
625 int status, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
626
627 status = drive_status();
628 if (status < 0)
629 return status;
630 qp->cdsc_audiostatus = audio_status;
631
632 status = exec_cmd(COMSUBQ);
633 if (status < 0)
634 return status;
635
636 d1 = get_data(0);
637 if (d1 < 0)
638 return d1;
639 qp->cdsc_adr = d1;
640 qp->cdsc_ctrl = d1 >> 4;
641
642 d2 = get_data(0);
643 if (d2 < 0)
644 return d2;
645 qp->cdsc_trk = bcd2bin(d2);
646
647 d3 = get_data(0);
648 if (d3 < 0)
649 return d3;
650 qp->cdsc_ind = bcd2bin(d3);
651
652 d4 = get_data(0);
653 if (d4 < 0)
654 return d4;
655 qp->cdsc_reladdr.msf.minute = d4;
656
657 d5 = get_data(0);
658 if (d5 < 0)
659 return d5;
660 qp->cdsc_reladdr.msf.second = d5;
661
662 d6 = get_data(0);
663 if (d6 < 0)
664 return d6;
665 qp->cdsc_reladdr.msf.frame = d6;
666
667 d7 = get_data(0);
668 if (d7 < 0)
669 return d7;
670
671
672 d8 = get_data(0);
673 if (d8 < 0)
674 return d8;
675 qp->cdsc_absaddr.msf.minute = d8;
676
677 d9 = get_data(0);
678 if (d9 < 0)
679 return d9;
680 qp->cdsc_absaddr.msf.second = d9;
681
682 d10 = get_data(0);
683 if (d10 < 0)
684 return d10;
685 qp->cdsc_absaddr.msf.frame = d10;
686
687 DEBUG((DEBUG_TOC, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
688 d1, d2, d3, d4, d5, d6, d7, d8, d9, d10));
689
690 msf_bcd2bin((union cd_addr *)&qp->cdsc_absaddr);
691 msf_bcd2bin((union cd_addr *)&qp->cdsc_reladdr);
692 if (qp->cdsc_format == CDROM_LBA) {
693 msf2lba((union cd_addr *)&qp->cdsc_absaddr);
694 msf2lba((union cd_addr *)&qp->cdsc_reladdr);
695 }
696
697 return 0;
698 }
699
700
701
702
703
704 #define ERR_TOC_MISSINGINFO 0x120
705 #define ERR_TOC_MISSINGENTRY 0x121
706
707
708 struct msf {
709 u_char minute;
710 u_char second;
711 u_char frame;
712 };
713
714 struct cdrom_disk_info {
715 unsigned char first;
716 unsigned char last;
717 struct msf disk_length;
718 struct msf first_track;
719
720 unsigned char next;
721 struct msf next_session;
722 struct msf last_session;
723 unsigned char multi;
724 unsigned char xa;
725 unsigned char audio;
726 };
727 static struct cdrom_disk_info disk_info;
728
729 #define MAX_TRACKS 111
730 static struct cdrom_subchnl toc[MAX_TRACKS];
731
732 #define QINFO_FIRSTTRACK 100
733 #define QINFO_LASTTRACK 101
734 #define QINFO_DISKLENGTH 102
735 #define QINFO_NEXTSESSION 110
736
737 #define I_FIRSTTRACK 0x01
738 #define I_LASTTRACK 0x02
739 #define I_DISKLENGTH 0x04
740 #define I_NEXTSESSION 0x08
741 #define I_ALL (I_FIRSTTRACK | I_LASTTRACK | I_DISKLENGTH)
742
743
744 #if DEBUG_TOC
745 void toc_debug_info(int i)
746 {
747 printk("#%3d ctl %1x, adr %1x, track %2d index %3d"
748 " %2d:%02d.%02d %2d:%02d.%02d\n",
749 i, toc[i].cdsc_ctrl, toc[i].cdsc_adr,
750 toc[i].cdsc_trk, toc[i].cdsc_ind,
751 toc[i].cdsc_reladdr.msf.minute,
752 toc[i].cdsc_reladdr.msf.second,
753 toc[i].cdsc_reladdr.msf.frame,
754 toc[i].cdsc_absaddr.msf.minute,
755 toc[i].cdsc_absaddr.msf.second,
756 toc[i].cdsc_absaddr.msf.frame);
757 }
758 #endif
759
760
761 static int read_toc(void)
762 {
763 int status, limit, count;
764 unsigned char got_info = 0;
765 struct cdrom_subchnl q_info;
766 #if DEBUG_TOC
767 int i;
768 #endif
769
770 DEBUG((DEBUG_TOC, "starting read_toc"));
771
772 count = 0;
773 for (limit = 60; limit > 0; limit--) {
774 int index;
775
776 q_info.cdsc_format = CDROM_MSF;
777 status = get_q_channel(&q_info);
778 if (status < 0)
779 return status;
780
781 index = q_info.cdsc_ind;
782 if (index > 0 && index < MAX_TRACKS
783 && q_info.cdsc_trk == 0 && toc[index].cdsc_ind == 0) {
784 toc[index] = q_info;
785 DEBUG((DEBUG_TOC, "got %d", index));
786 if (index < 100)
787 count++;
788
789 switch (q_info.cdsc_ind) {
790 case QINFO_FIRSTTRACK:
791 got_info |= I_FIRSTTRACK;
792 break;
793 case QINFO_LASTTRACK:
794 got_info |= I_LASTTRACK;
795 break;
796 case QINFO_DISKLENGTH:
797 got_info |= I_DISKLENGTH;
798 break;
799 case QINFO_NEXTSESSION:
800 got_info |= I_NEXTSESSION;
801 break;
802 }
803 }
804
805 if ((got_info & I_ALL) == I_ALL
806 && toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
807 >= toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
808 break;
809 }
810
811
812 if (disk_info.first == 0) {
813 disk_info.first = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
814 disk_info.first_track.minute =
815 toc[disk_info.first].cdsc_absaddr.msf.minute;
816 disk_info.first_track.second =
817 toc[disk_info.first].cdsc_absaddr.msf.second;
818 disk_info.first_track.frame =
819 toc[disk_info.first].cdsc_absaddr.msf.frame;
820 }
821 disk_info.last = toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute;
822 disk_info.disk_length.minute =
823 toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.minute;
824 disk_info.disk_length.second =
825 toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.second-2;
826 disk_info.disk_length.frame =
827 toc[QINFO_DISKLENGTH].cdsc_absaddr.msf.frame;
828 disk_info.next_session.minute =
829 toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.minute;
830 disk_info.next_session.second =
831 toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.second;
832 disk_info.next_session.frame =
833 toc[QINFO_NEXTSESSION].cdsc_reladdr.msf.frame;
834 disk_info.next = toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute;
835 disk_info.last_session.minute =
836 toc[disk_info.next].cdsc_absaddr.msf.minute;
837 disk_info.last_session.second =
838 toc[disk_info.next].cdsc_absaddr.msf.second;
839 disk_info.last_session.frame =
840 toc[disk_info.next].cdsc_absaddr.msf.frame;
841 toc[disk_info.last + 1].cdsc_absaddr.msf.minute =
842 disk_info.disk_length.minute;
843 toc[disk_info.last + 1].cdsc_absaddr.msf.second =
844 disk_info.disk_length.second;
845 toc[disk_info.last + 1].cdsc_absaddr.msf.frame =
846 disk_info.disk_length.frame;
847 #if DEBUG_TOC
848 for (i = 1; i <= disk_info.last + 1; i++)
849 toc_debug_info(i);
850 toc_debug_info(QINFO_FIRSTTRACK);
851 toc_debug_info(QINFO_LASTTRACK);
852 toc_debug_info(QINFO_DISKLENGTH);
853 toc_debug_info(QINFO_NEXTSESSION);
854 #endif
855
856 DEBUG((DEBUG_TOC, "exiting read_toc, got_info %x, count %d",
857 got_info, count));
858 if ((got_info & I_ALL) != I_ALL
859 || toc[QINFO_FIRSTTRACK].cdsc_absaddr.msf.minute + count
860 < toc[QINFO_LASTTRACK].cdsc_absaddr.msf.minute + 1)
861 return -ERR_TOC_MISSINGINFO;
862 return 0;
863 }
864
865
866 #ifdef MULTISESSION
867 static int get_multi_disk_info(void)
868 {
869 int sessions, status;
870 struct cdrom_msf multi_index;
871
872
873 for (sessions = 2; sessions < 10 ; sessions++) {
874 int count;
875
876 for (count = 100; count < MAX_TRACKS; count++)
877 toc[count].cdsc_ind = 0;
878
879 multi_index.cdmsf_min0 = disk_info.next_session.minute;
880 multi_index.cdmsf_sec0 = disk_info.next_session.second;
881 multi_index.cdmsf_frame0 = disk_info.next_session.frame;
882 if (multi_index.cdmsf_sec0 >= 20)
883 multi_index.cdmsf_sec0 -= 20;
884 else {
885 multi_index.cdmsf_sec0 += 40;
886 multi_index.cdmsf_min0--;
887 }
888 DEBUG((DEBUG_MULTIS, "Try %d: %2d:%02d.%02d", sessions,
889 multi_index.cdmsf_min0,
890 multi_index.cdmsf_sec0,
891 multi_index.cdmsf_frame0));
892 bin2bcd(&multi_index);
893 multi_index.cdmsf_min1 = 0;
894 multi_index.cdmsf_sec1 = 0;
895 multi_index.cdmsf_frame1 = 1;
896
897 status = exec_read_cmd(COMREAD, &multi_index);
898 if (status < 0) {
899 DEBUG((DEBUG_TOC, "exec_read_cmd COMREAD: %02x",
900 -status));
901 break;
902 }
903 status = sleep_flag_low(FL_DTEN, MULTI_SEEK_TIMEOUT) ?
904 0 : -ERR_TOC_MISSINGINFO;
905 flush_data();
906 if (status < 0) {
907 DEBUG((DEBUG_TOC, "sleep_flag_low: %02x", -status));
908 break;
909 }
910
911 status = read_toc();
912 if (status < 0) {
913 DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
914 break;
915 }
916
917 disk_info.multi = 1;
918 }
919
920 exec_cmd(COMSTOP);
921
922 if (status < 0)
923 return -EIO;
924 return 0;
925 }
926 #endif MULTISESSION
927
928
929 static int update_toc(void)
930 {
931 int status, count;
932
933 if (toc_uptodate)
934 return 0;
935
936 DEBUG((DEBUG_TOC, "starting update_toc"));
937
938 disk_info.first = 0;
939 for (count = 0; count < MAX_TRACKS; count++)
940 toc[count].cdsc_ind = 0;
941
942 status = exec_cmd(COMLEADIN);
943 if (status < 0)
944 return -EIO;
945
946 status = read_toc();
947 if (status < 0) {
948 DEBUG((DEBUG_TOC, "read_toc: %02x", -status));
949 return -EIO;
950 }
951
952
953 disk_info.audio =
954 (toc[disk_info.first].cdsc_ctrl & CDROM_DATA_TRACK) ? 0 : 1;
955
956
957 disk_info.xa = drive_status() & ST_MODE2TRACK;
958
959
960 disk_info.multi = 0;
961 #ifdef MULTISESSION
962 if (disk_info.xa)
963 get_multi_disk_info();
964 #endif MULTISESSION
965 if (disk_info.multi)
966 printk("optcd: Multisession support experimental, "
967 "see linux/Documentation/cdrom/optcd\n");
968
969 DEBUG((DEBUG_TOC, "exiting update_toc"));
970
971 toc_uptodate = 1;
972 return 0;
973 }
974
975
976
977
978 #define CURRENT_VALID \
979 (CURRENT && MAJOR(CURRENT -> rq_dev) == MAJOR_NR \
980 && CURRENT -> cmd == READ && CURRENT -> sector != -1)
981
982
983 #define BLOCKSIZE 2048
984 #define BLOCKSIZE_RAW 2336
985 #define BLOCKSIZE_ALL 2646
986 #define N_BUFS 16
987 #define NOBUF -1
988
989
990
991 static char buf[BLOCKSIZE * N_BUFS];
992 static volatile int buf_bn[N_BUFS], next_bn;
993 static volatile int buf_in = 0, buf_out = NOBUF;
994
995 inline static void opt_invalidate_buffers(void)
996 {
997 int i;
998
999 DEBUG((DEBUG_BUFFERS, "executing opt_invalidate_buffers"));
1000
1001 for (i = 0; i < N_BUFS; i++)
1002 buf_bn[i] = NOBUF;
1003 buf_out = NOBUF;
1004 }
1005
1006
1007
1008
1009 static void transfer(void)
1010 {
1011 #if DEBUG_BUFFERS | DEBUG_REQUEST
1012 printk("optcd: executing transfer\n");
1013 #endif
1014
1015 if (!CURRENT_VALID)
1016 return;
1017 while (CURRENT -> nr_sectors) {
1018 int bn = CURRENT -> sector / 4;
1019 int i, offs, nr_sectors;
1020 for (i = 0; i < N_BUFS && buf_bn[i] != bn; ++i);
1021
1022 DEBUG((DEBUG_REQUEST, "found %d", i));
1023
1024 if (i >= N_BUFS) {
1025 buf_out = NOBUF;
1026 break;
1027 }
1028
1029 offs = (i * 4 + (CURRENT -> sector & 3)) * 512;
1030 nr_sectors = 4 - (CURRENT -> sector & 3);
1031
1032 if (buf_out != i) {
1033 buf_out = i;
1034 if (buf_bn[i] != bn) {
1035 buf_out = NOBUF;
1036 continue;
1037 }
1038 }
1039
1040 if (nr_sectors > CURRENT -> nr_sectors)
1041 nr_sectors = CURRENT -> nr_sectors;
1042 memcpy(CURRENT -> buffer, buf + offs, nr_sectors * 512);
1043 CURRENT -> nr_sectors -= nr_sectors;
1044 CURRENT -> sector += nr_sectors;
1045 CURRENT -> buffer += nr_sectors * 512;
1046 }
1047 }
1048
1049
1050
1051
1052 enum state_e {
1053 S_IDLE,
1054 S_START,
1055 S_READ,
1056 S_DATA,
1057 S_STOP,
1058 S_STOPPING
1059 };
1060
1061 static volatile enum state_e state = S_IDLE;
1062 #if DEBUG_STATE
1063 static volatile enum state_e state_old = S_STOP;
1064 static volatile int flags_old = 0;
1065 static volatile long state_n = 0;
1066 #endif
1067
1068
1069 static volatile int transfer_is_active = 0;
1070 static volatile int error = 0;
1071 static int tries;
1072
1073 static void poll(void)
1074 {
1075 static int timeout;
1076 static volatile int read_count = 1;
1077 int flags;
1078 int loop_again = 1;
1079 int status = 0;
1080 int skip = 0;
1081
1082 if (error) {
1083 printk("optcd: I/O error 0x%02x\n", error);
1084 opt_invalidate_buffers();
1085 if (!tries--) {
1086 printk("optcd: read block %d failed; Giving up\n",
1087 next_bn);
1088 if (transfer_is_active)
1089 loop_again = 0;
1090 if (CURRENT_VALID)
1091 end_request(0);
1092 tries = 5;
1093 }
1094 error = 0;
1095 state = S_STOP;
1096 }
1097
1098 while (loop_again)
1099 {
1100 loop_again = 0;
1101
1102
1103 #if DEBUG_STATE
1104 if (state == state_old)
1105 state_n++;
1106 else {
1107 state_old = state;
1108 if (++state_n > 1)
1109 printk("optcd: %ld times in previous state\n",
1110 state_n);
1111 printk("optcd: state %d\n", state);
1112 state_n = 0;
1113 }
1114 #endif
1115
1116 switch (state) {
1117 case S_IDLE:
1118 return;
1119 case S_START:
1120 if (send_cmd(COMDRVST))
1121 return;
1122 state = S_READ;
1123 timeout = READ_TIMEOUT;
1124 break;
1125 case S_READ: {
1126 struct cdrom_msf msf;
1127 if (!skip) {
1128 status = fetch_status();
1129 if (status < 0)
1130 break;
1131 if (status & ST_DSK_CHG) {
1132 toc_uptodate = 0;
1133 opt_invalidate_buffers();
1134 }
1135 }
1136 skip = 0;
1137 if ((status & ST_DOOR_OPEN) || (status & ST_DRVERR)) {
1138 toc_uptodate = 0;
1139 printk((status & ST_DOOR_OPEN)
1140 ? "optcd: door open\n"
1141 : "optcd: disk removed\n");
1142 if (transfer_is_active) {
1143 state = S_START;
1144 loop_again = 1;
1145 break;
1146 }
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 BLOCKSIZE*buf_in,
1241 BLOCKSIZE);
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 return;
1295 state = S_STOPPING;
1296 timeout = STOP_TIMEOUT;
1297 break;
1298 case S_STOPPING:
1299 status = fetch_status();
1300 if (status < 0 && timeout)
1301 break;
1302 if ((status >= 0) && (status & ST_DSK_CHG)) {
1303 toc_uptodate = 0;
1304 opt_invalidate_buffers();
1305 }
1306 if (CURRENT_VALID) {
1307 if (status >= 0) {
1308 state = S_READ;
1309 loop_again = 1;
1310 skip = 1;
1311 break;
1312 } else {
1313 state = S_START;
1314 timeout = 1;
1315 }
1316 } else {
1317 state = S_IDLE;
1318 return;
1319 }
1320 break;
1321 default:
1322 printk("optcd: invalid state %d\n", state);
1323 return;
1324 }
1325 }
1326
1327 if (!timeout--) {
1328 printk("optcd: timeout in state %d\n", state);
1329 state = S_STOP;
1330 if (exec_cmd(COMSTOP) < 0)
1331 return;
1332 }
1333
1334 SET_TIMER(poll, HZ/100);
1335 }
1336
1337
1338 static void do_optcd_request(void)
1339 {
1340 DEBUG((DEBUG_REQUEST, "do_optcd_request(%ld+%ld)",
1341 CURRENT -> sector, CURRENT -> nr_sectors));
1342
1343 if (disk_info.audio) {
1344 printk("optcd: Error: tried to mount an Audio CD\n");
1345 end_request(0);
1346 return;
1347 }
1348
1349 transfer_is_active = 1;
1350 while (CURRENT_VALID) {
1351 if (CURRENT->bh) {
1352 if (!buffer_locked(CURRENT->bh))
1353 panic(DEVICE_NAME ": block not locked");
1354 }
1355 transfer();
1356 if (CURRENT -> nr_sectors == 0) {
1357 end_request(1);
1358 } else {
1359 buf_out = NOBUF;
1360 if (state == S_IDLE) {
1361
1362 if (update_toc() < 0) {
1363 while (CURRENT_VALID)
1364 end_request(0);
1365 break;
1366 }
1367
1368 state = S_START;
1369 tries = 5;
1370
1371 SET_TIMER(poll, HZ/100);
1372 }
1373 break;
1374 }
1375 }
1376 transfer_is_active = 0;
1377
1378 DEBUG((DEBUG_REQUEST, "next_bn:%d buf_in:%d buf_out:%d buf_bn:%d",
1379 next_bn, buf_in, buf_out, buf_bn[buf_in]));
1380 DEBUG((DEBUG_REQUEST, "do_optcd_request ends"));
1381 }
1382
1383
1384
1385
1386 static char auto_eject = 0;
1387
1388 static int cdrompause(void)
1389 {
1390 int status;
1391
1392 if (audio_status != CDROM_AUDIO_PLAY)
1393 return -EINVAL;
1394
1395 status = exec_cmd(COMPAUSEON);
1396 if (status < 0) {
1397 DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEON: %02x", -status));
1398 return -EIO;
1399 }
1400 audio_status = CDROM_AUDIO_PAUSED;
1401 return 0;
1402 }
1403
1404
1405 static int cdromresume(void)
1406 {
1407 int status;
1408
1409 if (audio_status != CDROM_AUDIO_PAUSED)
1410 return -EINVAL;
1411
1412 status = exec_cmd(COMPAUSEOFF);
1413 if (status < 0) {
1414 DEBUG((DEBUG_VFS, "exec_cmd COMPAUSEOFF: %02x", -status));
1415 audio_status = CDROM_AUDIO_ERROR;
1416 return -EIO;
1417 }
1418 audio_status = CDROM_AUDIO_PLAY;
1419 return 0;
1420 }
1421
1422
1423 static int cdromplaymsf(unsigned long arg)
1424 {
1425 int status;
1426 struct cdrom_msf msf;
1427
1428 status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
1429 if (status)
1430 return status;
1431 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1432
1433 bin2bcd(&msf);
1434 status = exec_long_cmd(COMPLAY, &msf);
1435 if (status < 0) {
1436 DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
1437 audio_status = CDROM_AUDIO_ERROR;
1438 return -EIO;
1439 }
1440
1441 audio_status = CDROM_AUDIO_PLAY;
1442 return 0;
1443 }
1444
1445
1446 static int cdromplaytrkind(unsigned long arg)
1447 {
1448 int status;
1449 struct cdrom_ti ti;
1450 struct cdrom_msf msf;
1451
1452 status = verify_area(VERIFY_READ, (void *) arg, sizeof ti);
1453 if (status)
1454 return status;
1455 memcpy_fromfs(&ti, (void *) arg, sizeof ti);
1456
1457 if (ti.cdti_trk0 < disk_info.first
1458 || ti.cdti_trk0 > disk_info.last
1459 || ti.cdti_trk1 < ti.cdti_trk0)
1460 return -EINVAL;
1461 if (ti.cdti_trk1 > disk_info.last)
1462 ti.cdti_trk1 = disk_info.last;
1463
1464 msf.cdmsf_min0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.minute;
1465 msf.cdmsf_sec0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.second;
1466 msf.cdmsf_frame0 = toc[ti.cdti_trk0].cdsc_absaddr.msf.frame;
1467 msf.cdmsf_min1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.minute;
1468 msf.cdmsf_sec1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.second;
1469 msf.cdmsf_frame1 = toc[ti.cdti_trk1 + 1].cdsc_absaddr.msf.frame;
1470
1471 DEBUG((DEBUG_VFS, "play %02d:%02d.%02d to %02d:%02d.%02d",
1472 msf.cdmsf_min0,
1473 msf.cdmsf_sec0,
1474 msf.cdmsf_frame0,
1475 msf.cdmsf_min1,
1476 msf.cdmsf_sec1,
1477 msf.cdmsf_frame1));
1478
1479 bin2bcd(&msf);
1480 status = exec_long_cmd(COMPLAY, &msf);
1481 if (status < 0) {
1482 DEBUG((DEBUG_VFS, "exec_long_cmd COMPLAY: %02x", -status));
1483 audio_status = CDROM_AUDIO_ERROR;
1484 return -EIO;
1485 }
1486
1487 audio_status = CDROM_AUDIO_PLAY;
1488 return 0;
1489 }
1490
1491
1492 static int cdromreadtochdr(unsigned long arg)
1493 {
1494 int status;
1495 struct cdrom_tochdr tochdr;
1496
1497 status = verify_area(VERIFY_WRITE, (void *) arg, sizeof tochdr);
1498 if (status)
1499 return status;
1500
1501 tochdr.cdth_trk0 = disk_info.first;
1502 tochdr.cdth_trk1 = disk_info.last;
1503
1504 memcpy_tofs((void *) arg, &tochdr, sizeof tochdr);
1505 return 0;
1506 }
1507
1508
1509 static int cdromreadtocentry(unsigned long arg)
1510 {
1511 int status;
1512 struct cdrom_tocentry entry;
1513 struct cdrom_subchnl *tocptr;
1514
1515 status = verify_area(VERIFY_READ, (void *) arg, sizeof entry);
1516 if (status)
1517 return status;
1518 status = verify_area(VERIFY_WRITE, (void *) arg, sizeof entry);
1519 if (status)
1520 return status;
1521 memcpy_fromfs(&entry, (void *) arg, sizeof entry);
1522
1523 if (entry.cdte_track == CDROM_LEADOUT)
1524 tocptr = &toc[disk_info.last + 1];
1525 else if (entry.cdte_track > disk_info.last
1526 || entry.cdte_track < disk_info.first)
1527 return -EINVAL;
1528 else
1529 tocptr = &toc[entry.cdte_track];
1530
1531 entry.cdte_adr = tocptr->cdsc_adr;
1532 entry.cdte_ctrl = tocptr->cdsc_ctrl;
1533 entry.cdte_addr.msf.minute = tocptr->cdsc_absaddr.msf.minute;
1534 entry.cdte_addr.msf.second = tocptr->cdsc_absaddr.msf.second;
1535 entry.cdte_addr.msf.frame = tocptr->cdsc_absaddr.msf.frame;
1536
1537
1538 if (entry.cdte_format == CDROM_LBA)
1539 msf2lba((union cd_addr *)&entry.cdte_addr);
1540 else if (entry.cdte_format != CDROM_MSF)
1541 return -EINVAL;
1542
1543 memcpy_tofs((void *) arg, &entry, sizeof entry);
1544 return 0;
1545 }
1546
1547
1548 static int cdromvolctrl(unsigned long arg)
1549 {
1550 int status;
1551 struct cdrom_volctrl volctrl;
1552 struct cdrom_msf msf;
1553
1554 status = verify_area(VERIFY_READ, (void *) arg, sizeof volctrl);
1555 if (status)
1556 return status;
1557 memcpy_fromfs(&volctrl, (char *) arg, sizeof volctrl);
1558
1559 msf.cdmsf_min0 = 0x10;
1560 msf.cdmsf_sec0 = 0x32;
1561 msf.cdmsf_frame0 = volctrl.channel0;
1562 msf.cdmsf_min1 = volctrl.channel1;
1563 msf.cdmsf_sec1 = volctrl.channel2;
1564 msf.cdmsf_frame1 = volctrl.channel3;
1565
1566 status = exec_long_cmd(COMCHCTRL, &msf);
1567 if (status < 0) {
1568 DEBUG((DEBUG_VFS, "exec_long_cmd COMCHCTRL: %02x", -status));
1569 return -EIO;
1570 }
1571 return 0;
1572 }
1573
1574
1575 static int cdromsubchnl(unsigned long arg)
1576 {
1577 int status;
1578 struct cdrom_subchnl subchnl;
1579
1580 status = verify_area(VERIFY_READ, (void *) arg, sizeof subchnl);
1581 if (status)
1582 return status;
1583 status = verify_area(VERIFY_WRITE, (void *) arg, sizeof subchnl);
1584 if (status)
1585 return status;
1586 memcpy_fromfs(&subchnl, (void *) arg, sizeof subchnl);
1587
1588 if (subchnl.cdsc_format != CDROM_LBA
1589 && subchnl.cdsc_format != CDROM_MSF)
1590 return -EINVAL;
1591
1592 status = get_q_channel(&subchnl);
1593 if (status < 0) {
1594 DEBUG((DEBUG_VFS, "get_q_channel: %02x", -status));
1595 return -EIO;
1596 }
1597
1598 memcpy_tofs((void *) arg, &subchnl, sizeof subchnl);
1599 return 0;
1600 }
1601
1602
1603 static int cdromread(unsigned long arg, int blocksize, int cmd)
1604 {
1605 int status;
1606 struct cdrom_msf msf;
1607 char buf[BLOCKSIZE_ALL];
1608
1609 status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
1610 if (status)
1611 return status;
1612 status = verify_area(VERIFY_WRITE, (void *) arg, blocksize);
1613 if (status)
1614 return status;
1615 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1616
1617 bin2bcd(&msf);
1618 msf.cdmsf_min1 = 0;
1619 msf.cdmsf_sec1 = 0;
1620 msf.cdmsf_frame1 = 1;
1621 status = exec_read_cmd(cmd, &msf);
1622
1623 DEBUG((DEBUG_VFS, "read cmd status 0x%x", status));
1624
1625 if (!sleep_flag_low(FL_DTEN, SLEEP_TIMEOUT))
1626 return -EIO;
1627 fetch_data(buf, blocksize);
1628
1629 memcpy_tofs((void *) arg, &buf, blocksize);
1630 return 0;
1631 }
1632
1633
1634 static int cdromseek(unsigned long arg)
1635 {
1636 int status;
1637 struct cdrom_msf msf;
1638
1639 status = verify_area(VERIFY_READ, (void *) arg, sizeof msf);
1640 if (status)
1641 return status;
1642 memcpy_fromfs(&msf, (void *) arg, sizeof msf);
1643
1644 bin2bcd(&msf);
1645 status = exec_seek_cmd(COMSEEK, &msf);
1646
1647 DEBUG((DEBUG_VFS, "COMSEEK status 0x%x", status));
1648
1649 if (status < 0)
1650 return -EIO;
1651 return 0;
1652 }
1653
1654
1655 #ifdef MULTISESSION
1656 static int cdrommultisession(unsigned long arg)
1657 {
1658 int status;
1659 struct cdrom_multisession ms;
1660
1661 status = verify_area(VERIFY_READ, (void*) arg, sizeof ms);
1662 if (status)
1663 return status;
1664 status = verify_area(VERIFY_WRITE, (void*) arg, sizeof ms);
1665 if (status)
1666 return status;
1667 memcpy_fromfs(&ms, (void*) arg, sizeof ms);
1668
1669 ms.addr.msf.minute = disk_info.last_session.minute;
1670 ms.addr.msf.second = disk_info.last_session.second;
1671 ms.addr.msf.frame = disk_info.last_session.frame;
1672
1673 if (ms.addr_format != CDROM_LBA
1674 && ms.addr_format != CDROM_MSF)
1675 return -EINVAL;
1676 if (ms.addr_format == CDROM_LBA)
1677 msf2lba((union cd_addr *)&ms.addr);
1678
1679 ms.xa_flag = disk_info.xa;
1680
1681 memcpy_tofs((void*) arg, &ms,
1682 sizeof(struct cdrom_multisession));
1683
1684 #if DEBUG_MULTIS
1685 if (ms.addr_format == CDROM_MSF)
1686 printk("optcd: multisession xa:%d, msf:%02d:%02d.%02d\n",
1687 ms.xa_flag,
1688 ms.addr.msf.minute,
1689 ms.addr.msf.second,
1690 ms.addr.msf.frame);
1691 else
1692 printk("optcd: multisession %d, lba:0x%08x [%02d:%02d.%02d])\n",
1693 ms.xa_flag,
1694 ms.addr.lba,
1695 disk_info.last_session.minute,
1696 disk_info.last_session.second,
1697 disk_info.last_session.frame);
1698 #endif DEBUG_MULTIS
1699
1700 return 0;
1701 }
1702 #endif MULTISESSION
1703
1704
1705 static int cdromreset(void)
1706 {
1707 if (state != S_IDLE) {
1708 error = 1;
1709 tries = 0;
1710 }
1711
1712 toc_uptodate = 0;
1713 opt_invalidate_buffers();
1714 audio_status = CDROM_AUDIO_NO_STATUS;
1715
1716 if (!reset_drive())
1717 return -EIO;
1718 return 0;
1719 }
1720
1721
1722
1723
1724 static int opt_ioctl(struct inode *ip, struct file *fp,
1725 unsigned int cmd, unsigned long arg)
1726 {
1727 int err;
1728
1729 DEBUG((DEBUG_VFS, "starting opt_ioctl"));
1730
1731 if (!ip)
1732 return -EINVAL;
1733
1734 if (cmd == CDROMRESET)
1735 return cdromreset();
1736
1737 if (state != S_IDLE)
1738 return -EBUSY;
1739
1740 err = drive_status();
1741 if (err < 0) {
1742 DEBUG((DEBUG_VFS, "drive_status: %02x", -err));
1743 return -EIO;
1744 }
1745 err = update_toc();
1746 if (err < 0) {
1747 DEBUG((DEBUG_VFS, "update_toc: %02x", -err));
1748 return -EIO;
1749 }
1750
1751 DEBUG((DEBUG_VFS, "ioctl cmd 0x%x", cmd));
1752
1753 switch (cmd) {
1754 case CDROMPAUSE: return cdrompause();
1755 case CDROMRESUME: return cdromresume();
1756 case CDROMPLAYMSF: return cdromplaymsf(arg);
1757 case CDROMPLAYTRKIND: return cdromplaytrkind(arg);
1758 case CDROMREADTOCHDR: return cdromreadtochdr(arg);
1759 case CDROMREADTOCENTRY: return cdromreadtocentry(arg);
1760
1761 case CDROMSTOP: err = exec_cmd(COMSTOP);
1762 if (err < 0) {
1763 DEBUG((DEBUG_VFS,
1764 "exec_cmd COMSTOP: %02x",
1765 -err));
1766 return -EIO;
1767 }
1768 audio_status = CDROM_AUDIO_NO_STATUS;
1769 break;
1770 case CDROMSTART: err = exec_cmd(COMCLOSE);
1771 if (err < 0) {
1772 DEBUG((DEBUG_VFS,
1773 "exec_cmd COMCLOSE: %02x",
1774 -err));
1775 return -EIO;
1776 }
1777 break;
1778 case CDROMEJECT: err = exec_cmd(COMUNLOCK);
1779 if (err < 0) {
1780 DEBUG((DEBUG_VFS,
1781 "exec_cmd COMUNLOCK: %02x",
1782 -err));
1783 return -EIO;
1784 }
1785 err = exec_cmd(COMOPEN);
1786 if (err < 0) {
1787 DEBUG((DEBUG_VFS,
1788 "exec_cmd COMOPEN: %02x",
1789 -err));
1790 return -EIO;
1791 }
1792 break;
1793
1794 case CDROMVOLCTRL: return cdromvolctrl(arg);
1795 case CDROMSUBCHNL: return cdromsubchnl(arg);
1796
1797 case CDROMREADAUDIO: return -EINVAL;
1798 case CDROMEJECT_SW: auto_eject = (char) arg;
1799 break;
1800
1801 #ifdef MULTISESSION
1802 case CDROMMULTISESSION: return cdrommultisession(arg);
1803 #endif
1804
1805 case CDROM_GET_UPC: return -EINVAL;
1806 case CDROMVOLREAD: return -EINVAL;
1807
1808 case CDROMREADRAW:
1809 return cdromread(arg, BLOCKSIZE_RAW, COMREADRAW);
1810 case CDROMREADCOOKED:
1811 return cdromread(arg, BLOCKSIZE, COMREAD);
1812 case CDROMSEEK: return cdromseek(arg);
1813 case CDROMPLAYBLK: return -EINVAL;
1814 default: return -EINVAL;
1815 }
1816 return 0;
1817 }
1818
1819
1820 static int open_count = 0;
1821
1822
1823 static int opt_open(struct inode *ip, struct file *fp)
1824 {
1825 DEBUG((DEBUG_VFS, "starting opt_open"));
1826
1827 if (!open_count++ && state == S_IDLE) {
1828 int status;
1829
1830 opt_invalidate_buffers();
1831 status = drive_status();
1832 if (status < 0) {
1833 DEBUG((DEBUG_VFS, "drive_status: %02x", -status));
1834 return -EIO;
1835 }
1836 DEBUG((DEBUG_VFS, "status: %02x", status));
1837 if (status & ST_DOOR_OPEN) {
1838 status = exec_cmd(COMCLOSE);
1839 if (status < 0) {
1840 DEBUG((DEBUG_VFS,
1841 "exec_cmd COMCLOSE: %02x", -status));
1842 }
1843 status = drive_status();
1844 if (status < 0) {
1845 DEBUG((DEBUG_VFS,
1846 "drive_status: %02x", -status));
1847 return -EIO;
1848 }
1849 DEBUG((DEBUG_VFS, "status: %02x", status));
1850 }
1851 if (status & (ST_DOOR_OPEN|ST_DRVERR)) {
1852 printk("optcd: no disk or door open\n");
1853 return -EIO;
1854 }
1855 status = exec_cmd(COMLOCK);
1856 if (status < 0) {
1857 DEBUG((DEBUG_VFS, "exec_cmd COMLOCK: %02x", -status));
1858 }
1859 status = update_toc();
1860 if (status < 0) {
1861 DEBUG((DEBUG_VFS, "update_toc: %02x", -status));
1862 return -EIO;
1863 }
1864 }
1865 MOD_INC_USE_COUNT;
1866
1867 DEBUG((DEBUG_VFS, "exiting opt_open"));
1868
1869 return 0;
1870 }
1871
1872
1873
1874 static void opt_release(struct inode *ip, struct file *fp)
1875 {
1876 int status;
1877
1878 DEBUG((DEBUG_VFS, "executing opt_release"));
1879 DEBUG((DEBUG_VFS, "inode: %p, inode -> i_rdev: 0x%x, file: %p\n",
1880 ip, ip -> i_rdev, fp));
1881
1882 if (!--open_count) {
1883 opt_invalidate_buffers();
1884 sync_dev(ip -> i_rdev);
1885 invalidate_buffers(ip -> i_rdev);
1886 status = exec_cmd(COMUNLOCK);
1887 if (status < 0) {
1888 DEBUG((DEBUG_VFS, "exec_cmd COMUNLOCK: %02x", -status));
1889 }
1890 if (auto_eject) {
1891 status = exec_cmd(COMOPEN);
1892 DEBUG((DEBUG_VFS, "exec_cmd COMOPEN: %02x", -status));
1893 }
1894 CLEAR_TIMER;
1895 }
1896 MOD_DEC_USE_COUNT;
1897 }
1898
1899
1900
1901
1902
1903
1904 static int version_ok(void)
1905 {
1906 char devname[100];
1907 int count, i, ch, status;
1908
1909 status = exec_cmd(COMVERSION);
1910 if (status < 0) {
1911 DEBUG((DEBUG_VFS, "exec_cmd COMVERSION: %02x", -status));
1912 return 0;
1913 }
1914 if ((count = get_data(1)) < 0) {
1915 DEBUG((DEBUG_VFS, "get_data(1): %02x", -count));
1916 return 0;
1917 }
1918 for (i = 0, ch = -1; count > 0; count--) {
1919 if ((ch = get_data(1)) < 0) {
1920 DEBUG((DEBUG_VFS, "get_data(1): %02x", -ch));
1921 break;
1922 }
1923 if (i < 99)
1924 devname[i++] = ch;
1925 }
1926 devname[i] = '\0';
1927 if (ch < 0)
1928 return 0;
1929
1930 printk("optcd: Device %s detected\n", devname);
1931 return ((devname[0] == 'D')
1932 && (devname[1] == 'O')
1933 && (devname[2] == 'L')
1934 && (devname[3] == 'P')
1935 && (devname[4] == 'H')
1936 && (devname[5] == 'I')
1937 && (devname[6] == 'N'));
1938 }
1939
1940
1941 static struct file_operations opt_fops = {
1942 NULL,
1943 block_read,
1944 block_write,
1945 NULL,
1946 NULL,
1947 opt_ioctl,
1948 NULL,
1949 opt_open,
1950 opt_release,
1951 NULL,
1952 NULL,
1953 NULL,
1954 NULL
1955 };
1956
1957
1958
1959 void optcd_setup(char *str, int *ints)
1960 {
1961 if (ints[0] > 0)
1962 optcd_port = ints[1];
1963 }
1964
1965
1966
1967 int optcd_init(void)
1968 {
1969 int status;
1970
1971 if (optcd_port <= 0) {
1972 printk("optcd: no Optics Storage CDROM Initialization\n");
1973 return -EIO;
1974 }
1975 if (check_region(optcd_port, 4)) {
1976 printk("optcd: conflict, I/O port 0x%x already used\n",
1977 optcd_port);
1978 return -EIO;
1979 }
1980
1981 if (!reset_drive()) {
1982 printk("optcd: drive at 0x%x not ready\n", optcd_port);
1983 return -EIO;
1984 }
1985 if (!version_ok()) {
1986 printk("optcd: unknown drive detected; aborting\n");
1987 return -EIO;
1988 }
1989 status = exec_cmd(COMINITDOUBLE);
1990 if (status < 0) {
1991 printk("optcd: cannot init double speed mode\n");
1992 DEBUG((DEBUG_VFS, "exec_cmd COMINITDOUBLE: %02x", -status));
1993 return -EIO;
1994 }
1995 if (register_blkdev(MAJOR_NR, "optcd", &opt_fops) != 0)
1996 {
1997 printk("optcd: unable to get major %d\n", MAJOR_NR);
1998 return -EIO;
1999 }
2000
2001 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
2002 read_ahead[MAJOR_NR] = 4;
2003 request_region(optcd_port, 4, "optcd");
2004
2005 printk("optcd: DOLPHIN 8000 AT CDROM at 0x%x\n", optcd_port);
2006 return 0;
2007 }
2008
2009
2010 #ifdef MODULE
2011 int init_module(void)
2012 {
2013 return optcd_init();
2014 }
2015
2016
2017 void cleanup_module(void)
2018 {
2019 if (unregister_blkdev(MAJOR_NR, "optcd") == -EINVAL) {
2020 printk("optcd: what's that: can't unregister\n");
2021 return;
2022 }
2023 release_region(optcd_port, 4);
2024 printk("optcd: module released.\n");
2025 }
2026 #endif MODULE