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