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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179#define REVISION "$Revision: 1.5 $"
180
181#include <linux/module.h>
182
183#include <linux/errno.h>
184#include <linux/delay.h>
185#include <linux/string.h>
186#include <linux/sched.h>
187#include <linux/interrupt.h>
188#include <linux/timer.h>
189#include <linux/cdrom.h>
190#include <linux/devfs_fs_kernel.h>
191#include <linux/ioport.h>
192#include <linux/mm.h>
193#include <linux/slab.h>
194#include <linux/init.h>
195
196
197
198#include <asm/io.h>
199
200#define MAJOR_NR CM206_CDROM_MAJOR
201
202#include <linux/blkdev.h>
203
204#undef DEBUG
205#define STATISTICS
206#define AUTO_PROBE_MODULE
207#define USE_INSW
208
209#include "cm206.h"
210
211
212
213
214
215static int auto_probe = 1;
216
217static int cm206_base = CM206_BASE;
218static int cm206_irq = CM206_IRQ;
219#ifdef MODULE
220static int cm206[2] = { 0, 0 };
221#endif
222
223MODULE_PARM(cm206_base, "i");
224MODULE_PARM(cm206_irq, "i");
225MODULE_PARM(cm206, "1-2i");
226MODULE_PARM(auto_probe, "i");
227MODULE_LICENSE("GPL");
228
229#define POLLOOP 100
230#define READ_AHEAD 1
231#define BACK_AHEAD 1
232#define DATA_TIMEOUT (3*HZ)
233#define UART_TIMEOUT (5*HZ/100)
234#define DSB_TIMEOUT (7*HZ)
235#define UR_SIZE 4
236
237#define LINUX_BLOCK_SIZE 512
238#define RAW_SECTOR_SIZE 2352
239#define ISO_SECTOR_SIZE 2048
240#define BLOCKS_ISO (ISO_SECTOR_SIZE/LINUX_BLOCK_SIZE)
241#define CD_SYNC_HEAD 16
242
243#ifdef STATISTICS
244#define stats(i) { ++cd->stats[st_ ## i]; \
245 cd->last_stat[st_ ## i] = cd->stat_counter++; \
246 }
247#else
248#define stats(i) (void) 0;
249#endif
250
251#define Debug(a) {printk (KERN_DEBUG); printk a;}
252#ifdef DEBUG
253#define debug(a) Debug(a)
254#else
255#define debug(a) (void) 0;
256#endif
257
258typedef unsigned char uch;
259typedef unsigned short ush;
260
261struct toc_struct {
262 uch track, fsm[3], q0;
263};
264
265struct cm206_struct {
266 volatile ush intr_ds;
267 volatile ush intr_ls;
268 volatile uch ur[UR_SIZE];
269 volatile uch ur_w, ur_r;
270 volatile uch dsb, cc;
271 int command;
272 int openfiles;
273 ush sector[READ_AHEAD * RAW_SECTOR_SIZE / 2];
274 int sector_first, sector_last;
275 wait_queue_head_t uart;
276 wait_queue_head_t data;
277 struct timer_list timer;
278 char timed_out;
279 signed char max_sectors;
280 char wait_back;
281 char background;
282 int adapter_first;
283 int adapter_last;
284 char fifo_overflowed;
285 uch disc_status[7];
286#ifdef STATISTICS
287 int stats[NR_STATS];
288 int last_stat[NR_STATS];
289 int stat_counter;
290#endif
291 struct toc_struct toc[101];
292 uch q[10];
293 uch audio_status[5];
294 uch media_changed;
295};
296
297#define DISC_STATUS cd->disc_status[0]
298#define FIRST_TRACK cd->disc_status[1]
299#define LAST_TRACK cd->disc_status[2]
300#define PAUSED cd->audio_status[0]
301#define PLAY_TO cd->toc[0]
302
303static struct cm206_struct *cd;
304static struct request_queue *cm206_queue;
305static spinlock_t cm206_lock = SPIN_LOCK_UNLOCKED;
306
307
308
309
310void send_command_polled(int command)
311{
312 int loop = POLLOOP;
313 while (!(inw(r_line_status) & ls_transmitter_buffer_empty)
314 && loop > 0) {
315 mdelay(1);
316 --loop;
317 }
318 outw(command, r_uart_transmit);
319}
320
321uch receive_echo_polled(void)
322{
323 int loop = POLLOOP;
324 while (!(inw(r_line_status) & ls_receive_buffer_full) && loop > 0) {
325 mdelay(1);
326 --loop;
327 }
328 return ((uch) inw(r_uart_receive));
329}
330
331uch send_receive_polled(int command)
332{
333 send_command_polled(command);
334 return receive_echo_polled();
335}
336
337inline void clear_ur(void)
338{
339 if (cd->ur_r != cd->ur_w) {
340 debug(("Deleting bytes from fifo:"));
341 for (; cd->ur_r != cd->ur_w;
342 cd->ur_r++, cd->ur_r %= UR_SIZE)
343 debug((" 0x%x", cd->ur[cd->ur_r]));
344 debug(("\n"));
345 }
346}
347
348static struct tasklet_struct cm206_tasklet;
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363static irqreturn_t cm206_interrupt(int sig, void *dev_id, struct pt_regs *regs)
364{
365 volatile ush fool;
366 cd->intr_ds = inw(r_data_status);
367
368
369 cd->intr_ls = inw(r_line_status);
370 debug(("Intr, 0x%x 0x%x, %d\n", cd->intr_ds, cd->intr_ls,
371 cd->background));
372 if (cd->intr_ls & ls_attention)
373 stats(attention);
374
375 if (cd->intr_ls & ls_receive_buffer_full) {
376 cd->ur[cd->ur_w] = inb(r_uart_receive);
377 cd->intr_ls = inw(r_line_status);
378 debug(("receiving #%d: 0x%x\n", cd->ur_w,
379 cd->ur[cd->ur_w]));
380 cd->ur_w++;
381 cd->ur_w %= UR_SIZE;
382 if (cd->ur_w == cd->ur_r)
383 debug(("cd->ur overflow!\n"));
384 if (waitqueue_active(&cd->uart) && cd->background < 2) {
385 del_timer(&cd->timer);
386 wake_up_interruptible(&cd->uart);
387 }
388 }
389
390 else if (cd->intr_ds & ds_data_ready) {
391 if (cd->background)
392 ++cd->adapter_last;
393 if (waitqueue_active(&cd->data)
394 && (cd->wait_back || !cd->background)) {
395 del_timer(&cd->timer);
396 wake_up_interruptible(&cd->data);
397 }
398 stats(data_ready);
399 }
400
401 else if (cd->command && cd->intr_ls & ls_transmitter_buffer_empty) {
402 outw(dc_normal | (inw(r_data_status) & 0x7f),
403 r_data_control);
404 outw(cd->command, r_uart_transmit);
405 cd->command = 0;
406 if (!cd->background)
407 wake_up_interruptible(&cd->uart);
408 }
409
410 else if (cd->intr_ds & ds_fifo_overflow) {
411 debug(("Fifo overflow at sectors 0x%x\n",
412 cd->sector_first));
413 fool = inw(r_fifo_output_buffer);
414 cd->fifo_overflowed = 1;
415 stats(fifo_overflow);
416 } else if (cd->intr_ds & ds_data_error) {
417 debug(("Data error at sector 0x%x\n", cd->sector_first));
418 stats(data_error);
419 } else if (cd->intr_ds & ds_crc_error) {
420 debug(("CRC error at sector 0x%x\n", cd->sector_first));
421 stats(crc_error);
422 } else if (cd->intr_ds & ds_sync_error) {
423 debug(("Sync at sector 0x%x\n", cd->sector_first));
424 stats(sync_error);
425 } else if (cd->intr_ds & ds_toc_ready) {
426
427 }
428
429 else {
430 outw(dc_normal | READ_AHEAD, r_data_control);
431 stats(lost_intr);
432 }
433 if (cd->background
434 && (cd->adapter_last - cd->adapter_first == cd->max_sectors
435 || cd->fifo_overflowed))
436 tasklet_schedule(&cm206_tasklet);
437 stats(interrupt);
438 return IRQ_HANDLED;
439}
440
441
442void cm206_timeout(unsigned long who)
443{
444 cd->timed_out = 1;
445 debug(("Timing out\n"));
446 wake_up_interruptible((wait_queue_head_t *) who);
447}
448
449
450
451int sleep_or_timeout(wait_queue_head_t * wait, int timeout)
452{
453 cd->timed_out = 0;
454 init_timer(&cd->timer);
455 cd->timer.data = (unsigned long) wait;
456 cd->timer.expires = jiffies + timeout;
457 add_timer(&cd->timer);
458 debug(("going to sleep\n"));
459 interruptible_sleep_on(wait);
460 del_timer(&cd->timer);
461 if (cd->timed_out) {
462 cd->timed_out = 0;
463 return 1;
464 } else
465 return 0;
466}
467
468void cm206_delay(int nr_jiffies)
469{
470 DECLARE_WAIT_QUEUE_HEAD(wait);
471 sleep_or_timeout(&wait, nr_jiffies);
472}
473
474void send_command(int command)
475{
476 debug(("Sending 0x%x\n", command));
477 if (!(inw(r_line_status) & ls_transmitter_buffer_empty)) {
478 cd->command = command;
479 cli();
480 outw(dc_mask_sync_error | dc_no_stop_on_error |
481 (inw(r_data_status) & 0x7f), r_data_control);
482
483 if (sleep_or_timeout(&cd->uart, UART_TIMEOUT)) {
484 debug(("Time out on write-buffer\n"));
485 stats(write_timeout);
486 outw(command, r_uart_transmit);
487 }
488 debug(("Write commmand delayed\n"));
489 } else
490 outw(command, r_uart_transmit);
491}
492
493uch receive_byte(int timeout)
494{
495 uch ret;
496 cli();
497 debug(("cli\n"));
498 ret = cd->ur[cd->ur_r];
499 if (cd->ur_r != cd->ur_w) {
500 sti();
501 debug(("returning #%d: 0x%x\n", cd->ur_r,
502 cd->ur[cd->ur_r]));
503 cd->ur_r++;
504 cd->ur_r %= UR_SIZE;
505 return ret;
506 } else if (sleep_or_timeout(&cd->uart, timeout)) {
507 debug(("Time out on receive-buffer\n"));
508#ifdef STATISTICS
509 if (timeout == UART_TIMEOUT)
510 stats(receive_timeout)
511 else
512 stats(dsb_timeout);
513#endif
514 return 0xda;
515 }
516 ret = cd->ur[cd->ur_r];
517 debug(("slept; returning #%d: 0x%x\n", cd->ur_r,
518 cd->ur[cd->ur_r]));
519 cd->ur_r++;
520 cd->ur_r %= UR_SIZE;
521 return ret;
522}
523
524inline uch receive_echo(void)
525{
526 return receive_byte(UART_TIMEOUT);
527}
528
529inline uch send_receive(int command)
530{
531 send_command(command);
532 return receive_echo();
533}
534
535inline uch wait_dsb(void)
536{
537 return receive_byte(DSB_TIMEOUT);
538}
539
540int type_0_command(int command, int expect_dsb)
541{
542 int e;
543 clear_ur();
544 if (command != (e = send_receive(command))) {
545 debug(("command 0x%x echoed as 0x%x\n", command, e));
546 stats(echo);
547 return -1;
548 }
549 if (expect_dsb) {
550 cd->dsb = wait_dsb();
551 }
552 return 0;
553}
554
555int type_1_command(int command, int bytes, uch * status)
556{
557 int i;
558 if (type_0_command(command, 0))
559 return -1;
560 for (i = 0; i < bytes; i++)
561 status[i] = send_receive(c_gimme);
562 return 0;
563}
564
565
566
567void reset_cm260(void)
568{
569 outw(dc_normal | dc_initialize | READ_AHEAD, r_data_control);
570 udelay(10);
571 outw(dc_normal | READ_AHEAD, r_data_control);
572}
573
574
575void fsm(int lba, uch * fsm)
576{
577 fsm[0] = lba % 75;
578 lba /= 75;
579 lba += 2;
580 fsm[1] = lba % 60;
581 fsm[2] = lba / 60;
582}
583
584inline int fsm2lba(uch * fsm)
585{
586 return fsm[0] + 75 * (fsm[1] - 2 + 60 * fsm[2]);
587}
588
589inline int f_s_m2lba(uch f, uch s, uch m)
590{
591 return f + 75 * (s - 2 + 60 * m);
592}
593
594int start_read(int start)
595{
596 uch read_sector[4] = { c_read_data, };
597 int i, e;
598
599 fsm(start, &read_sector[1]);
600 clear_ur();
601 for (i = 0; i < 4; i++)
602 if (read_sector[i] != (e = send_receive(read_sector[i]))) {
603 debug(("read_sector: %x echoes %x\n",
604 read_sector[i], e));
605 stats(echo);
606 if (e == 0xff) {
607 e = receive_echo();
608 debug(("Second try %x\n", e));
609 if (e != read_sector[i])
610 return -1;
611 }
612 }
613 return 0;
614}
615
616int stop_read(void)
617{
618 int e;
619 type_0_command(c_stop, 0);
620 if ((e = receive_echo()) != 0xff) {
621 debug(("c_stop didn't send 0xff, but 0x%x\n", e));
622 stats(stop_0xff);
623 return -1;
624 }
625 return 0;
626}
627
628
629
630
631
632
633int read_background(int start, int reading)
634{
635 if (cd->background)
636 return -1;
637 outw(dc_normal | BACK_AHEAD, r_data_control);
638 if (!reading && start_read(start))
639 return -2;
640 cd->adapter_first = cd->adapter_last = start;
641 cd->background = 1;
642 return 0;
643}
644
645#ifdef USE_INSW
646#define transport_data insw
647#else
648
649
650void transport_data(int port, ush * dest, int count)
651{
652 int i;
653 ush *d;
654 for (i = 0, d = dest; i < count; i++, d++)
655 *d = inw(port);
656}
657#endif
658
659
660#define MAX_TRIES 100
661int read_sector(int start)
662{
663 int tries = 0;
664 if (cd->background) {
665 cd->background = 0;
666 cd->adapter_last = -1;
667 stop_read();
668 }
669 cd->fifo_overflowed = 0;
670 reset_cm260();
671 if (start_read(start))
672 return -1;
673 do {
674 if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
675 debug(("Read timed out sector 0x%x\n", start));
676 stats(read_timeout);
677 stop_read();
678 return -3;
679 }
680 tries++;
681 } while (cd->intr_ds & ds_fifo_empty && tries < MAX_TRIES);
682 if (tries > 1)
683 debug(("Took me some tries\n"))
684 else
685 if (tries == MAX_TRIES)
686 debug(("MAX_TRIES tries for read sector\n"));
687 transport_data(r_fifo_output_buffer, cd->sector,
688 READ_AHEAD * RAW_SECTOR_SIZE / 2);
689 if (read_background(start + READ_AHEAD, 1))
690 stats(read_background);
691 cd->sector_first = start;
692 cd->sector_last = start + READ_AHEAD;
693 stats(read_restarted);
694 return 0;
695}
696
697
698
699
700
701
702
703
704
705
706
707static void cm206_tasklet_func(unsigned long ignore)
708{
709 debug(("bh: %d\n", cd->background));
710 switch (cd->background) {
711 case 1:
712 stats(bh);
713 if (!(cd->intr_ls & ls_transmitter_buffer_empty)) {
714 cd->command = c_stop;
715 outw(dc_mask_sync_error | dc_no_stop_on_error |
716 (inw(r_data_status) & 0x7f), r_data_control);
717 cd->background = 2;
718 break;
719 } else
720 outw(c_stop, r_uart_transmit);
721
722 case 2:
723
724 cd->background = 3;
725 break;
726 case 3:
727 if (cd->ur_r != cd->ur_w) {
728 if (cd->ur[cd->ur_r] != c_stop) {
729 debug(("cm206_bh: c_stop echoed 0x%x\n",
730 cd->ur[cd->ur_r]));
731 stats(echo);
732 }
733 cd->ur_r++;
734 cd->ur_r %= UR_SIZE;
735 }
736 cd->background++;
737 break;
738 case 4:
739 if (cd->ur_r != cd->ur_w) {
740 if (cd->ur[cd->ur_r] != 0xff) {
741 debug(("cm206_bh: c_stop reacted with 0x%x\n", cd->ur[cd->ur_r]));
742 stats(stop_0xff);
743 }
744 cd->ur_r++;
745 cd->ur_r %= UR_SIZE;
746 }
747 cd->background = 0;
748 }
749}
750
751static DECLARE_TASKLET(cm206_tasklet, cm206_tasklet_func, 0);
752
753
754
755
756void get_drive_status(void)
757{
758 uch status[2];
759 type_1_command(c_drive_status, 2, status);
760 cd->dsb = status[0];
761 cd->cc = status[1];
762 cd->media_changed |=
763 !!(cd->dsb & (dsb_possible_media_change |
764 dsb_drive_not_ready | dsb_tray_not_closed));
765}
766
767void get_disc_status(void)
768{
769 if (type_1_command(c_disc_status, 7, cd->disc_status)) {
770 debug(("get_disc_status: error\n"));
771 }
772}
773
774
775
776static int cm206_open(struct cdrom_device_info *cdi, int purpose)
777{
778 if (!cd->openfiles) {
779 cd->background = 0;
780 reset_cm260();
781 cd->adapter_last = -1;
782 cd->sector_last = -1;
783 }
784 ++cd->openfiles;
785 stats(open);
786 return 0;
787}
788
789static void cm206_release(struct cdrom_device_info *cdi)
790{
791 if (cd->openfiles == 1) {
792 if (cd->background) {
793 cd->background = 0;
794 stop_read();
795 }
796 cd->sector_last = -1;
797 FIRST_TRACK = 0;
798 }
799 --cd->openfiles;
800}
801
802
803
804void empty_buffer(int sectors)
805{
806 while (sectors >= 0) {
807 transport_data(r_fifo_output_buffer,
808 cd->sector + cd->fifo_overflowed,
809 RAW_SECTOR_SIZE / 2 - cd->fifo_overflowed);
810 --sectors;
811 ++cd->adapter_first;
812 cd->fifo_overflowed = 0;
813 stats(sector_transferred);
814 }
815 cd->sector_first = cd->adapter_first - 1;
816 cd->sector_last = cd->adapter_first;
817}
818
819
820
821
822int try_adapter(int sector)
823{
824 if (cd->adapter_first <= sector && sector < cd->adapter_last) {
825
826 empty_buffer(sector - cd->adapter_first);
827 return 0;
828 } else if (cd->background == 1 && cd->adapter_first <= sector
829 && sector < cd->adapter_first + cd->max_sectors) {
830
831 cd->wait_back = 1;
832 while (sector >= cd->adapter_last) {
833 if (sleep_or_timeout(&cd->data, DATA_TIMEOUT)) {
834 debug(("Timed out during background wait: %d %d %d %d\n", sector, cd->adapter_last, cd->adapter_first, cd->background));
835 stats(back_read_timeout);
836 cd->wait_back = 0;
837 return -1;
838 }
839 }
840 cd->wait_back = 0;
841 empty_buffer(sector - cd->adapter_first);
842 return 0;
843 } else
844 return -2;
845}
846
847
848
849
850static void do_cm206_request(request_queue_t * q)
851{
852 long int i, cd_sec_no;
853 int quarter, error;
854 uch *source, *dest;
855 struct request *req;
856
857 while (1) {
858 req = elv_next_request(q);
859 if (!req)
860 return;
861
862 if (req->cmd != READ) {
863 debug(("Non-read command %d on cdrom\n", req->cmd));
864 end_request(req, 0);
865 continue;
866 }
867 spin_unlock_irq(q->queue_lock);
868 error = 0;
869 for (i = 0; i < req->nr_sectors; i++) {
870 int e1, e2;
871 cd_sec_no = (req->sector + i) / BLOCKS_ISO;
872 quarter = (req->sector + i) % BLOCKS_ISO;
873 dest = req->buffer + i * LINUX_BLOCK_SIZE;
874
875 if (cd->sector_first <= cd_sec_no
876 && cd_sec_no < cd->sector_last) {
877 source =
878 ((uch *) cd->sector) + 16 +
879 quarter * LINUX_BLOCK_SIZE +
880 (cd_sec_no -
881 cd->sector_first) * RAW_SECTOR_SIZE;
882 memcpy(dest, source, LINUX_BLOCK_SIZE);
883 } else if (!(e1 = try_adapter(cd_sec_no)) ||
884 !(e2 = read_sector(cd_sec_no))) {
885 source =
886 ((uch *) cd->sector) + 16 +
887 quarter * LINUX_BLOCK_SIZE;
888 memcpy(dest, source, LINUX_BLOCK_SIZE);
889 } else {
890 error = 1;
891 debug(("cm206_request: %d %d\n", e1, e2));
892 }
893 }
894 spin_lock_irq(q->queue_lock);
895 end_request(req, !error);
896 }
897}
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913void seek(int lba)
914{
915 int i;
916 uch seek_command[4] = { c_seek, };
917
918 fsm(lba, &seek_command[1]);
919 for (i = 0; i < 4; i++)
920 type_0_command(seek_command[i], 0);
921 cd->dsb = wait_dsb();
922}
923
924uch bcdbin(unsigned char bcd)
925{
926 return (bcd >> 4) * 10 + (bcd & 0xf);
927}
928
929inline uch normalize_track(uch track)
930{
931 if (track < 1)
932 return 1;
933 if (track > LAST_TRACK)
934 return LAST_TRACK + 1;
935 return track;
936}
937
938
939
940
941
942int get_toc_lba(uch track)
943{
944 int max = 74 * 60 * 75 - 150, min = fsm2lba(cd->toc[1].fsm);
945 int i, lba, l, old_lba = 0;
946 uch *q = cd->q;
947 uch ct;
948 int binary = 0;
949 const int skip = 3 * 60 * 75;
950
951 for (i = track; i > 0; i--)
952 if (cd->toc[i].track) {
953 min = fsm2lba(cd->toc[i].fsm);
954 break;
955 }
956 lba = min + skip;
957 do {
958 seek(lba);
959 type_1_command(c_read_current_q, 10, q);
960 ct = normalize_track(q[1]);
961 if (!cd->toc[ct].track) {
962 l = q[9] - bcdbin(q[5]) + 75 * (q[8] -
963 bcdbin(q[4]) - 2 +
964 60 * (q[7] -
965 bcdbin(q
966 [3])));
967 cd->toc[ct].track = q[1];
968 fsm(l, cd->toc[ct].fsm);
969 cd->toc[ct].q0 = q[0];
970 if (ct == track)
971 return l;
972 }
973 old_lba = lba;
974 if (binary) {
975 if (ct < track)
976 min = lba;
977 else
978 max = lba;
979 lba = (min + max) / 2;
980 } else {
981 if (ct < track)
982 lba += skip;
983 else {
984 binary = 1;
985 max = lba;
986 min = lba - skip;
987 lba = (min + max) / 2;
988 }
989 }
990 } while (lba != old_lba);
991 return lba;
992}
993
994void update_toc_entry(uch track)
995{
996 track = normalize_track(track);
997 if (!cd->toc[track].track)
998 get_toc_lba(track);
999}
1000
1001
1002int read_toc_header(struct cdrom_tochdr *hp)
1003{
1004 if (!FIRST_TRACK)
1005 get_disc_status();
1006 if (hp) {
1007 int i;
1008 hp->cdth_trk0 = FIRST_TRACK;
1009 hp->cdth_trk1 = LAST_TRACK;
1010
1011 for (i = 0; i < 3; i++)
1012 cd->toc[1].fsm[i] = cd->disc_status[3 + i];
1013 update_toc_entry(LAST_TRACK + 1);
1014 return 0;
1015 }
1016 return -1;
1017}
1018
1019void play_from_to_msf(struct cdrom_msf *msfp)
1020{
1021 uch play_command[] = { c_play,
1022 msfp->cdmsf_frame0, msfp->cdmsf_sec0, msfp->cdmsf_min0,
1023 msfp->cdmsf_frame1, msfp->cdmsf_sec1, msfp->cdmsf_min1, 2,
1024 2
1025 };
1026 int i;
1027 for (i = 0; i < 9; i++)
1028 type_0_command(play_command[i], 0);
1029 for (i = 0; i < 3; i++)
1030 PLAY_TO.fsm[i] = play_command[i + 4];
1031 PLAY_TO.track = 0;
1032 cd->dsb = wait_dsb();
1033}
1034
1035void play_from_to_track(int from, int to)
1036{
1037 uch play_command[8] = { c_play, };
1038 int i;
1039
1040 if (from == 0) {
1041 for (i = 0; i < 3; i++) {
1042 play_command[i + 1] = cd->audio_status[i + 2];
1043 play_command[i + 4] = PLAY_TO.fsm[i];
1044 }
1045 } else {
1046 update_toc_entry(from);
1047 update_toc_entry(to + 1);
1048 for (i = 0; i < 3; i++) {
1049 play_command[i + 1] = cd->toc[from].fsm[i];
1050 PLAY_TO.fsm[i] = play_command[i + 4] =
1051 cd->toc[to + 1].fsm[i];
1052 }
1053 PLAY_TO.track = to;
1054 }
1055 for (i = 0; i < 7; i++)
1056 type_0_command(play_command[i], 0);
1057 for (i = 0; i < 2; i++)
1058 type_0_command(0x2, 0);
1059 cd->dsb = wait_dsb();
1060}
1061
1062int get_current_q(struct cdrom_subchnl *qp)
1063{
1064 int i;
1065 uch *q = cd->q;
1066 if (type_1_command(c_read_current_q, 10, q))
1067 return 0;
1068
1069 for (i = 2; i < 6; i++)
1070 q[i] = bcdbin(q[i]);
1071 qp->cdsc_adr = q[0] & 0xf;
1072 qp->cdsc_ctrl = q[0] >> 4;
1073 qp->cdsc_trk = q[1];
1074 qp->cdsc_ind = q[2];
1075 if (qp->cdsc_format == CDROM_MSF) {
1076 qp->cdsc_reladdr.msf.minute = q[3];
1077 qp->cdsc_reladdr.msf.second = q[4];
1078 qp->cdsc_reladdr.msf.frame = q[5];
1079 qp->cdsc_absaddr.msf.minute = q[7];
1080 qp->cdsc_absaddr.msf.second = q[8];
1081 qp->cdsc_absaddr.msf.frame = q[9];
1082 } else {
1083 qp->cdsc_reladdr.lba = f_s_m2lba(q[5], q[4], q[3]);
1084 qp->cdsc_absaddr.lba = f_s_m2lba(q[9], q[8], q[7]);
1085 }
1086 get_drive_status();
1087 if (cd->dsb & dsb_play_in_progress)
1088 qp->cdsc_audiostatus = CDROM_AUDIO_PLAY;
1089 else if (PAUSED)
1090 qp->cdsc_audiostatus = CDROM_AUDIO_PAUSED;
1091 else
1092 qp->cdsc_audiostatus = CDROM_AUDIO_NO_STATUS;
1093 return 0;
1094}
1095
1096void invalidate_toc(void)
1097{
1098 memset(cd->toc, 0, sizeof(cd->toc));
1099 memset(cd->disc_status, 0, sizeof(cd->disc_status));
1100}
1101
1102
1103void get_toc_entry(struct cdrom_tocentry *ep)
1104{
1105 uch track = normalize_track(ep->cdte_track);
1106 update_toc_entry(track);
1107 ep->cdte_addr.msf.frame = cd->toc[track].fsm[0];
1108 ep->cdte_addr.msf.second = cd->toc[track].fsm[1];
1109 ep->cdte_addr.msf.minute = cd->toc[track].fsm[2];
1110 ep->cdte_adr = cd->toc[track].q0 & 0xf;
1111 ep->cdte_ctrl = cd->toc[track].q0 >> 4;
1112 ep->cdte_datamode = 0;
1113}
1114
1115
1116
1117
1118
1119
1120int cm206_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
1121 void *arg)
1122{
1123 switch (cmd) {
1124 case CDROMREADTOCHDR:
1125 return read_toc_header((struct cdrom_tochdr *) arg);
1126 case CDROMREADTOCENTRY:
1127 get_toc_entry((struct cdrom_tocentry *) arg);
1128 return 0;
1129 case CDROMPLAYMSF:
1130 play_from_to_msf((struct cdrom_msf *) arg);
1131 return 0;
1132 case CDROMPLAYTRKIND:
1133 play_from_to_track(((struct cdrom_ti *) arg)->cdti_trk0,
1134 ((struct cdrom_ti *) arg)->cdti_trk1);
1135 return 0;
1136 case CDROMSTOP:
1137 PAUSED = 0;
1138 if (cd->dsb & dsb_play_in_progress)
1139 return type_0_command(c_stop, 1);
1140 else
1141 return 0;
1142 case CDROMPAUSE:
1143 get_drive_status();
1144 if (cd->dsb & dsb_play_in_progress) {
1145 type_0_command(c_stop, 1);
1146 type_1_command(c_audio_status, 5,
1147 cd->audio_status);
1148 PAUSED = 1;
1149 }
1150 return 0;
1151 case CDROMRESUME:
1152 if (PAUSED)
1153 play_from_to_track(0, 0);
1154 PAUSED = 0;
1155 return 0;
1156 case CDROMSTART:
1157 case CDROMVOLCTRL:
1158 return 0;
1159 case CDROMSUBCHNL:
1160 return get_current_q((struct cdrom_subchnl *) arg);
1161 default:
1162 return -EINVAL;
1163 }
1164}
1165
1166
1167
1168
1169
1170static int cm206_ioctl(struct cdrom_device_info *cdi, unsigned int cmd,
1171 unsigned long arg)
1172{
1173 switch (cmd) {
1174#ifdef STATISTICS
1175 case CM206CTL_GET_STAT:
1176 if (arg >= NR_STATS)
1177 return -EINVAL;
1178 else
1179 return cd->stats[arg];
1180 case CM206CTL_GET_LAST_STAT:
1181 if (arg >= NR_STATS)
1182 return -EINVAL;
1183 else
1184 return cd->last_stat[arg];
1185#endif
1186 default:
1187 debug(("Unknown ioctl call 0x%x\n", cmd));
1188 return -EINVAL;
1189 }
1190}
1191
1192int cm206_media_changed(struct cdrom_device_info *cdi, int disc_nr)
1193{
1194 if (cd != NULL) {
1195 int r;
1196 get_drive_status();
1197 r = cd->media_changed;
1198 cd->media_changed = 0;
1199 return r;
1200 } else
1201 return -EIO;
1202}
1203
1204
1205
1206
1207
1208int cm206_open_files(struct cdrom_device_info *cdi)
1209{
1210 if (cd)
1211 return cd->openfiles;
1212 return -1;
1213}
1214
1215
1216int cm206_tray_move(struct cdrom_device_info *cdi, int position)
1217{
1218 if (position) {
1219 type_0_command(c_open_tray, 1);
1220 invalidate_toc();
1221 } else
1222 type_0_command(c_close_tray, 1);
1223 return 0;
1224}
1225
1226
1227int cm206_drive_status(struct cdrom_device_info *cdi, int slot_nr)
1228{
1229 get_drive_status();
1230 if (cd->dsb & dsb_tray_not_closed)
1231 return CDS_TRAY_OPEN;
1232 if (!(cd->dsb & dsb_disc_present))
1233 return CDS_NO_DISC;
1234 if (cd->dsb & dsb_drive_not_ready)
1235 return CDS_DRIVE_NOT_READY;
1236 return CDS_DISC_OK;
1237}
1238
1239
1240int cm206_lock_door(struct cdrom_device_info *cdi, int lock)
1241{
1242 uch command = (lock) ? c_lock_tray : c_unlock_tray;
1243 type_0_command(command, 1);
1244
1245 return lock ^ ((cd->dsb & dsb_tray_locked) != 0);
1246}
1247
1248
1249
1250
1251int cm206_get_last_session(struct cdrom_device_info *cdi,
1252 struct cdrom_multisession *mssp)
1253{
1254 if (!FIRST_TRACK)
1255 get_disc_status();
1256 if (mssp != NULL) {
1257 if (DISC_STATUS & cds_multi_session) {
1258 mssp->addr.msf.frame = cd->disc_status[3];
1259 mssp->addr.msf.second = cd->disc_status[4];
1260 mssp->addr.msf.minute = cd->disc_status[5];
1261 mssp->addr_format = CDROM_MSF;
1262 mssp->xa_flag = 1;
1263 } else {
1264 mssp->xa_flag = 0;
1265 }
1266 return 1;
1267 }
1268 return 0;
1269}
1270
1271int cm206_get_upc(struct cdrom_device_info *cdi, struct cdrom_mcn *mcn)
1272{
1273 uch upc[10];
1274 char *ret = mcn->medium_catalog_number;
1275 int i;
1276
1277 if (type_1_command(c_read_upc, 10, upc))
1278 return -EIO;
1279 for (i = 0; i < 13; i++) {
1280 int w = i / 2 + 1, r = i % 2;
1281 if (r)
1282 ret[i] = 0x30 | (upc[w] & 0x0f);
1283 else
1284 ret[i] = 0x30 | ((upc[w] >> 4) & 0x0f);
1285 }
1286 ret[13] = '\0';
1287 return 0;
1288}
1289
1290int cm206_reset(struct cdrom_device_info *cdi)
1291{
1292 stop_read();
1293 reset_cm260();
1294 outw(dc_normal | dc_break | READ_AHEAD, r_data_control);
1295 mdelay(1);
1296 outw(dc_normal | READ_AHEAD, r_data_control);
1297 cd->sector_last = -1;
1298 cd->adapter_last = -1;
1299 invalidate_toc();
1300 return 0;
1301}
1302
1303int cm206_select_speed(struct cdrom_device_info *cdi, int speed)
1304{
1305 int r;
1306 switch (speed) {
1307 case 0:
1308 r = type_0_command(c_auto_mode, 1);
1309 break;
1310 case 1:
1311 r = type_0_command(c_force_1x, 1);
1312 break;
1313 case 2:
1314 r = type_0_command(c_force_2x, 1);
1315 break;
1316 default:
1317 return -1;
1318 }
1319 if (r < 0)
1320 return r;
1321 else
1322 return 1;
1323}
1324
1325static struct cdrom_device_ops cm206_dops = {
1326 .open = cm206_open,
1327 .release = cm206_release,
1328 .drive_status = cm206_drive_status,
1329 .media_changed = cm206_media_changed,
1330 .tray_move = cm206_tray_move,
1331 .lock_door = cm206_lock_door,
1332 .select_speed = cm206_select_speed,
1333 .get_last_session = cm206_get_last_session,
1334 .get_mcn = cm206_get_upc,
1335 .reset = cm206_reset,
1336 .audio_ioctl = cm206_audio_ioctl,
1337 .dev_ioctl = cm206_ioctl,
1338 .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK |
1339 CDC_MULTI_SESSION | CDC_MEDIA_CHANGED |
1340 CDC_MCN | CDC_PLAY_AUDIO | CDC_SELECT_SPEED |
1341 CDC_IOCTLS | CDC_DRIVE_STATUS,
1342 .n_minors = 1,
1343};
1344
1345
1346static struct cdrom_device_info cm206_info = {
1347 .ops = &cm206_dops,
1348 .speed = 2,
1349 .capacity = 1,
1350 .name = "cm206",
1351};
1352
1353static int cm206_block_open(struct inode *inode, struct file *file)
1354{
1355 return cdrom_open(&cm206_info, inode, file);
1356}
1357
1358static int cm206_block_release(struct inode *inode, struct file *file)
1359{
1360 return cdrom_release(&cm206_info, file);
1361}
1362
1363static int cm206_block_ioctl(struct inode *inode, struct file *file,
1364 unsigned cmd, unsigned long arg)
1365{
1366 return cdrom_ioctl(file, &cm206_info, inode, cmd, arg);
1367}
1368
1369static int cm206_block_media_changed(struct gendisk *disk)
1370{
1371 return cdrom_media_changed(&cm206_info);
1372}
1373
1374static struct block_device_operations cm206_bdops =
1375{
1376 .owner = THIS_MODULE,
1377 .open = cm206_block_open,
1378 .release = cm206_block_release,
1379 .ioctl = cm206_block_ioctl,
1380 .media_changed = cm206_block_media_changed,
1381};
1382
1383static struct gendisk *cm206_gendisk;
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395int __init probe_base_port(int base)
1396{
1397 int b = 0x300, e = 0x370;
1398 volatile int fool, i;
1399
1400 if (base)
1401 b = e = base;
1402 for (base = b; base <= e; base += 0x10) {
1403 if (!request_region(base, 0x10,"cm206"))
1404 continue;
1405 for (i = 0; i < 3; i++)
1406 fool = inw(base + 2);
1407 if ((inw(base + 6) & 0xffef) != 0x0001 ||
1408 (inw(base) & 0xad00) != 0) {
1409 release_region(base,0x10);
1410 continue;
1411 }
1412 return (base);
1413 }
1414 return 0;
1415}
1416
1417#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1418
1419int __init probe_irq(int nr)
1420{
1421 int irqs, irq;
1422 outw(dc_normal | READ_AHEAD, r_data_control);
1423 sti();
1424 irqs = probe_irq_on();
1425 reset_cm260();
1426 udelay(100);
1427 irq = probe_irq_off(irqs);
1428 outw(dc_normal | READ_AHEAD, r_data_control);
1429 if (nr && irq != nr && irq > 0)
1430 return 0;
1431 else
1432 return irq;
1433}
1434#endif
1435
1436int __init cm206_init(void)
1437{
1438 uch e = 0;
1439 long int size = sizeof(struct cm206_struct);
1440 struct gendisk *disk;
1441
1442 printk(KERN_INFO "cm206 cdrom driver " REVISION);
1443 cm206_base = probe_base_port(auto_probe ? 0 : cm206_base);
1444 if (!cm206_base) {
1445 printk(" can't find adapter!\n");
1446 return -EIO;
1447 }
1448 printk(" adapter at 0x%x", cm206_base);
1449 cd = (struct cm206_struct *) kmalloc(size, GFP_KERNEL);
1450 if (!cd)
1451 goto out_base;
1452
1453
1454
1455#if !defined(MODULE) || defined(AUTO_PROBE_MODULE)
1456 cm206_irq = probe_irq(auto_probe ? 0 : cm206_irq);
1457 if (cm206_irq <= 0) {
1458 printk("can't find IRQ!\n");
1459 goto out_probe;
1460 } else
1461 printk(" IRQ %d found\n", cm206_irq);
1462#else
1463 cli();
1464 reset_cm260();
1465
1466
1467
1468 mdelay(1);
1469 outw(dc_normal | READ_AHEAD, r_data_control);
1470 sti();
1471 printk(" using IRQ %d\n", cm206_irq);
1472#endif
1473 if (send_receive_polled(c_drive_configuration) !=
1474 c_drive_configuration) {
1475 printk(KERN_INFO " drive not there\n");
1476 goto out_probe;
1477 }
1478 e = send_receive_polled(c_gimme);
1479 printk(KERN_INFO "Firmware revision %d", e & dcf_revision_code);
1480 if (e & dcf_transfer_rate)
1481 printk(" double");
1482 else
1483 printk(" single");
1484 printk(" speed drive");
1485 if (e & dcf_motorized_tray)
1486 printk(", motorized tray");
1487 if (request_irq(cm206_irq, cm206_interrupt, 0, "cm206", NULL)) {
1488 printk("\nUnable to reserve IRQ---aborted\n");
1489 goto out_probe;
1490 }
1491 printk(".\n");
1492
1493 if (register_blkdev(MAJOR_NR, "cm206"))
1494 goto out_blkdev;
1495
1496 disk = alloc_disk(1);
1497 if (!disk)
1498 goto out_disk;
1499 disk->major = MAJOR_NR;
1500 disk->first_minor = 0;
1501 sprintf(disk->disk_name, "cm206cd");
1502 disk->fops = &cm206_bdops;
1503 disk->flags = GENHD_FL_CD;
1504 cm206_gendisk = disk;
1505 if (register_cdrom(&cm206_info) != 0) {
1506 printk(KERN_INFO "Cannot register for cdrom %d!\n", MAJOR_NR);
1507 goto out_cdrom;
1508 }
1509 cm206_queue = blk_init_queue(do_cm206_request, &cm206_lock);
1510 if (!cm206_queue)
1511 goto out_queue;
1512
1513 blk_queue_hardsect_size(cm206_queue, 2048);
1514 disk->queue = cm206_queue;
1515 add_disk(disk);
1516
1517 memset(cd, 0, sizeof(*cd));
1518 cd->sector_last = -1;
1519 cd->adapter_last = -1;
1520 init_timer(&cd->timer);
1521 cd->timer.function = cm206_timeout;
1522 cd->max_sectors = (inw(r_data_status) & ds_ram_size) ? 24 : 97;
1523 printk(KERN_INFO "%d kB adapter memory available, "
1524 " %ld bytes kernel memory used.\n", cd->max_sectors * 2,
1525 size);
1526 return 0;
1527
1528out_queue:
1529 unregister_cdrom(&cm206_info);
1530out_cdrom:
1531 put_disk(disk);
1532out_disk:
1533 unregister_blkdev(MAJOR_NR, "cm206");
1534out_blkdev:
1535 free_irq(cm206_irq, NULL);
1536out_probe:
1537 kfree(cd);
1538out_base:
1539 release_region(cm206_base, 16);
1540 return -EIO;
1541}
1542
1543#ifdef MODULE
1544
1545
1546static void __init parse_options(void)
1547{
1548 int i;
1549 for (i = 0; i < 2; i++) {
1550 if (0x300 <= cm206[i] && i <= 0x370
1551 && cm206[i] % 0x10 == 0) {
1552 cm206_base = cm206[i];
1553 auto_probe = 0;
1554 } else if (3 <= cm206[i] && cm206[i] <= 15) {
1555 cm206_irq = cm206[i];
1556 auto_probe = 0;
1557 }
1558 }
1559}
1560
1561int __cm206_init(void)
1562{
1563 parse_options();
1564#if !defined(AUTO_PROBE_MODULE)
1565 auto_probe = 0;
1566#endif
1567 return cm206_init();
1568}
1569
1570void __exit cm206_exit(void)
1571{
1572 del_gendisk(cm206_gendisk);
1573 put_disk(cm206_gendisk);
1574 if (unregister_cdrom(&cm206_info)) {
1575 printk("Can't unregister cdrom cm206\n");
1576 return;
1577 }
1578 if (unregister_blkdev(MAJOR_NR, "cm206")) {
1579 printk("Can't unregister major cm206\n");
1580 return;
1581 }
1582 blk_cleanup_queue(cm206_queue);
1583 free_irq(cm206_irq, NULL);
1584 kfree(cd);
1585 release_region(cm206_base, 16);
1586 printk(KERN_INFO "cm206 removed\n");
1587}
1588
1589module_init(__cm206_init);
1590module_exit(cm206_exit);
1591
1592#else
1593
1594
1595
1596
1597static int __init cm206_setup(char *s)
1598{
1599 int i, p[4];
1600
1601 (void) get_options(s, ARRAY_SIZE(p), p);
1602
1603 if (!strcmp(s, "auto"))
1604 auto_probe = 1;
1605 for (i = 1; i <= p[0]; i++) {
1606 if (0x300 <= p[i] && i <= 0x370 && p[i] % 0x10 == 0) {
1607 cm206_base = p[i];
1608 auto_probe = 0;
1609 } else if (3 <= p[i] && p[i] <= 15) {
1610 cm206_irq = p[i];
1611 auto_probe = 0;
1612 }
1613 }
1614 return 1;
1615}
1616
1617__setup("cm206=", cm206_setup);
1618
1619#endif
1620MODULE_ALIAS_BLOCKDEV_MAJOR(CM206_CDROM_MAJOR);
1621
1622
1623
1624
1625
1626
1627