This source file includes following definitions.
- cdu535_check_media_change
- enable_interrupts
- disable_interrupts
- cdu535_interrupt
- sony_sleep
- select_unit
- read_result_reg
- read_exec_status
- check_drive_status
- do_sony_cmd
- set_drive_mode
- seek_and_read_N_blocks
- request_toc_data
- spin_up_drive
- int_to_bcd
- bcd_to_int
- log_to_msf
- msf_to_log
- size_to_buf
- do_cdu535_request
- sony_get_toc
- find_track
- read_subcode
- sony_get_subchnl_info
- cdu_ioctl
- cdu_open
- cdu_release
- sony535_init
- sonycd535_setup
- 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
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 # include <linux/module.h>
111
112 #include <linux/errno.h>
113 #include <linux/signal.h>
114 #include <linux/sched.h>
115 #include <linux/timer.h>
116 #include <linux/fs.h>
117 #include <linux/kernel.h>
118 #include <linux/ioport.h>
119 #include <linux/hdreg.h>
120 #include <linux/genhd.h>
121 #include <linux/mm.h>
122 #include <linux/malloc.h>
123
124 #define REALLY_SLOW_IO
125 #include <asm/system.h>
126 #include <asm/io.h>
127 #include <asm/segment.h>
128
129 #include <linux/cdrom.h>
130
131 #define MAJOR_NR CDU535_CDROM_MAJOR
132 # include <linux/blk.h>
133 #define sony535_cd_base_io sonycd535
134 #include <linux/sonycd535.h>
135
136
137
138
139
140
141
142 #ifndef CDU535_ADDRESS
143 # define CDU535_ADDRESS 0x340
144 #endif
145 #ifndef CDU535_INTERRUPT
146 # define CDU535_INTERRUPT 0
147 #endif
148 #ifndef CDU535_HANDLE
149 # define CDU535_HANDLE "cdu535"
150 #endif
151 #ifndef CDU535_MESSAGE_NAME
152 # define CDU535_MESSAGE_NAME "Sony CDU-535"
153 #endif
154
155 #ifndef MAX_SPINUP_RETRY
156 # define MAX_SPINUP_RETRY 3
157 #endif
158 #ifndef RETRY_FOR_BAD_STATUS
159 # define RETRY_FOR_BAD_STATUS 100
160 #endif
161
162 #ifndef DEBUG
163 # define DEBUG 1
164 #endif
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180 #define SONY535_BUFFER_SIZE (64*1024)
181
182
183
184
185
186 #ifndef NO_LOCK_DOORS
187 # define LOCK_DOORS
188 #endif
189
190 static int read_subcode(void);
191 static void sony_get_toc(void);
192 static int cdu_open(struct inode *inode, struct file *filp);
193 static inline unsigned int int_to_bcd(unsigned int val);
194 static unsigned int bcd_to_int(unsigned int bcd);
195 static int do_sony_cmd(Byte * cmd, int nCmd, Byte status[2],
196 Byte * response, int n_response, int ignoreStatusBit7);
197
198
199
200 static unsigned int sony535_cd_base_io = CDU535_ADDRESS;
201
202
203
204
205
206 static unsigned short select_unit_reg;
207 static unsigned short result_reg;
208 static unsigned short command_reg;
209 static unsigned short read_status_reg;
210 static unsigned short data_reg;
211
212 static int initialized = 0;
213 static int sony_disc_changed = 1;
214
215 static int sony_toc_read = 0;
216
217 static unsigned int sony_buffer_size;
218
219 static unsigned int sony_buffer_sectors;
220
221 static unsigned int sony_usage = 0;
222
223
224 static int sony_first_block = -1;
225
226 static int sony_last_block = -1;
227
228
229 static struct s535_sony_toc *sony_toc;
230
231
232 static struct s535_sony_subcode *last_sony_subcode;
233
234 static Byte **sony_buffer;
235
236
237 static int sony_inuse = 0;
238
239
240
241
242
243
244 static int sony_audio_status = CDROM_AUDIO_NO_STATUS;
245
246
247
248
249
250
251
252
253
254
255 static Byte cur_pos_msf[3] = {0, 0, 0};
256 static Byte final_pos_msf[3] = {0, 0, 0};
257
258
259 static int sony535_irq_used = CDU535_INTERRUPT;
260
261
262 static struct wait_queue *cdu535_irq_wait = NULL;
263
264
265
266
267
268
269 static int
270 cdu535_check_media_change(kdev_t full_dev)
271 {
272 int retval;
273
274 if (MINOR(full_dev) != 0) {
275 printk(CDU535_MESSAGE_NAME " request error: invalid device.\n");
276 return 0;
277 }
278
279
280 retval = initialized ? sony_disc_changed : 0;
281 sony_disc_changed = 0;
282 return retval;
283 }
284
285 static inline void
286 enable_interrupts(void)
287 {
288 #ifdef USE_IRQ
289
290
291
292 curr_control_reg |= ( SONY_ATTN_INT_EN_BIT
293 | SONY_RES_RDY_INT_EN_BIT
294 | SONY_DATA_RDY_INT_EN_BIT);
295 outb(curr_control_reg, sony_cd_control_reg);
296 #endif
297 }
298
299 static inline void
300 disable_interrupts(void)
301 {
302 #ifdef USE_IRQ
303
304
305
306 curr_control_reg &= ~(SONY_ATTN_INT_EN_BIT
307 | SONY_RES_RDY_INT_EN_BIT
308 | SONY_DATA_RDY_INT_EN_BIT);
309 outb(curr_control_reg, sony_cd_control_reg);
310 #endif
311 }
312
313 static void
314 cdu535_interrupt(int irq, struct pt_regs *regs)
315 {
316 disable_interrupts();
317 if (cdu535_irq_wait != NULL)
318 wake_up(&cdu535_irq_wait);
319 else
320 printk(CDU535_MESSAGE_NAME
321 ": Got an interrupt but nothing was waiting\n");
322 }
323
324
325
326
327
328
329
330 static inline void
331 sony_sleep(void)
332 {
333 if (sony535_irq_used <= 0) {
334 current->state = TASK_INTERRUPTIBLE;
335 current->timeout = jiffies;
336 schedule();
337 } else {
338 cli();
339 enable_interrupts();
340 interruptible_sleep_on(&cdu535_irq_wait);
341 sti();
342 }
343 }
344
345
346
347
348
349
350
351
352 static void
353 select_unit(int unit_no)
354 {
355 unsigned int select_mask = ~(1 << unit_no);
356 outb(select_mask, select_unit_reg);
357 }
358
359
360
361
362
363
364
365
366 static int
367 read_result_reg(Byte *data_ptr)
368 {
369 int retry_count;
370 int read_status;
371
372 retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
373 while (jiffies < retry_count) {
374 if (((read_status = inb(read_status_reg)) & SONY535_RESULT_NOT_READY_BIT) == 0) {
375 #if DEBUG > 1
376 printk(CDU535_MESSAGE_NAME
377 ": read_result_reg(): readStatReg = 0x%x\n", read_status);
378 #endif
379 *data_ptr = inb(result_reg);
380 return 0;
381 } else {
382 sony_sleep();
383 }
384 }
385 printk(CDU535_MESSAGE_NAME " read_result_reg: TIME OUT!\n");
386 return TIME_OUT;
387 }
388
389
390
391
392
393
394
395
396 static int
397 read_exec_status(Byte status[2])
398 {
399 status[1] = 0;
400 if (read_result_reg(&(status[0])) != 0)
401 return TIME_OUT;
402 if ((status[0] & 0x80) != 0) {
403 if (read_result_reg(&(status[1])) != 0)
404 return TIME_OUT;
405 }
406 #if DEBUG > 1
407 printk(CDU535_MESSAGE_NAME ": read_exec_status: read 0x%x 0x%x\n",
408 status[0], status[1]);
409 #endif
410 return 0;
411 }
412
413
414
415
416
417
418
419
420 static int
421 check_drive_status(void)
422 {
423 Byte status, e_status[2];
424 int CDD, ATN;
425 Byte cmd;
426
427 select_unit(0);
428 if (sony_audio_status == CDROM_AUDIO_PLAY) {
429 outb(SONY535_REQUEST_AUDIO_STATUS, command_reg);
430 if (read_result_reg(&status) == 0) {
431 switch (status) {
432 case 0x0:
433 break;
434 case 0x1:
435 break;
436 case 0x3:
437 case 0x5:
438 sony_audio_status = CDROM_AUDIO_COMPLETED;
439 read_subcode();
440 break;
441 case 0x4:
442 sony_audio_status = CDROM_AUDIO_ERROR;
443 break;
444 }
445 }
446 }
447
448 outb(SONY535_REQUEST_DRIVE_STATUS_2, command_reg);
449 if (read_result_reg(&status) != 0)
450 return TIME_OUT;
451
452 #if DEBUG > 1
453 printk(CDU535_MESSAGE_NAME ": check_drive_status() got 0x%x\n", status);
454 #endif
455
456 if (status == 0)
457 return 0;
458
459 ATN = status & 0xf;
460 CDD = (status >> 4) & 0xf;
461
462 switch (ATN) {
463 case 0x0:
464 break;
465 case SONY535_ATN_BUSY:
466 if (initialized)
467 printk(CDU535_MESSAGE_NAME " error: drive busy\n");
468 return CD_BUSY;
469 case SONY535_ATN_EJECT_IN_PROGRESS:
470 printk(CDU535_MESSAGE_NAME " error: eject in progress\n");
471 sony_audio_status = CDROM_AUDIO_INVALID;
472 return CD_BUSY;
473 case SONY535_ATN_RESET_OCCURRED:
474 case SONY535_ATN_DISC_CHANGED:
475 case SONY535_ATN_RESET_AND_DISC_CHANGED:
476 #if DEBUG > 0
477 printk(CDU535_MESSAGE_NAME " notice: reset occurred or disc changed\n");
478 #endif
479 sony_disc_changed = 1;
480 sony_toc_read = 0;
481 sony_audio_status = CDROM_AUDIO_NO_STATUS;
482 sony_first_block = -1;
483 sony_last_block = -1;
484 if (initialized) {
485 cmd = SONY535_SPIN_UP;
486 do_sony_cmd(&cmd, 1, e_status, NULL, 0, 0);
487 sony_get_toc();
488 }
489 return 0;
490 default:
491 printk(CDU535_MESSAGE_NAME " error: drive busy (ATN=0x%x)\n", ATN);
492 return CD_BUSY;
493 }
494 switch (CDD) {
495 case 0x0:
496 case 0x2:
497 case 0xa:
498 break;
499 case 0xc:
500 printk(CDU535_MESSAGE_NAME
501 ": check_drive_status(): CDD = 0xc! Not properly handled!\n");
502 return CD_BUSY;
503 default:
504 return CD_BUSY;
505 }
506 return 0;
507 }
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525 static int
526 do_sony_cmd(Byte * cmd, int n_cmd, Byte status[2],
527 Byte * response, int n_response, int ignore_status_bit7)
528 {
529 int i;
530
531
532 for (i = 0; i < n_cmd; i++)
533 outb(cmd[i], command_reg);
534
535
536 if (read_result_reg(status) != 0)
537 return TIME_OUT;
538 if (!ignore_status_bit7 && ((status[0] & 0x80) != 0)) {
539
540 if (read_result_reg(status + 1) != 0)
541 return TIME_OUT;
542 } else {
543 status[1] = 0;
544 }
545 #if DEBUG > 2
546 printk(CDU535_MESSAGE_NAME ": do_sony_cmd %x: %x %x\n",
547 *cmd, status[0], status[1]);
548 #endif
549
550
551 if ((status[0] & ((ignore_status_bit7 ? 0x7f : 0xff) & 0x8f)) != 0)
552 return 0;
553
554
555 for (i = 0; 0 < n_response; n_response--, i++)
556 if (read_result_reg(response + i) != 0)
557 return TIME_OUT;
558 return 0;
559 }
560
561
562
563
564
565
566
567 static int
568 set_drive_mode(int mode, Byte status[2])
569 {
570 Byte cmd_buff[2];
571 Byte ret_buff[1];
572
573 cmd_buff[0] = SONY535_SET_DRIVE_MODE;
574 cmd_buff[1] = mode;
575 return do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1);
576 }
577
578
579
580
581
582
583
584
585
586
587
588
589
590 static int
591 seek_and_read_N_blocks(Byte params[], int n_blocks, Byte status[2],
592 Byte **buff, int buf_size)
593 {
594 const int block_size = 2048;
595 Byte cmd_buff[7];
596 int i;
597 int read_status;
598 int retry_count;
599 Byte *data_buff;
600 int sector_count = 0;
601
602 if (buf_size < ((long)block_size) * n_blocks)
603 return NO_ROOM;
604
605 set_drive_mode(SONY535_CDROM_DRIVE_MODE, status);
606
607
608 cmd_buff[0] = SONY535_SEEK_AND_READ_N_BLOCKS_1;
609 for (i = 0; i < 6; i++)
610 cmd_buff[i + 1] = params[i];
611 for (i = 0; i < 7; i++)
612 outb(cmd_buff[i], command_reg);
613
614
615 while (0 < n_blocks--) {
616
617 retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
618 while (jiffies < retry_count) {
619 read_status = inb(read_status_reg);
620 if ((read_status & SONY535_RESULT_NOT_READY_BIT) == 0) {
621 read_exec_status(status);
622 return BAD_STATUS;
623 }
624 if ((read_status & SONY535_DATA_NOT_READY_BIT) == 0) {
625
626 data_buff = buff[sector_count++];
627 for (i = 0; i < block_size; i++)
628 *data_buff++ = inb(data_reg);
629 break;
630 }
631 sony_sleep();
632 }
633 if (retry_count <= jiffies)
634 return TIME_OUT;
635 }
636
637
638 if ((i = read_exec_status(status)) != 0)
639 return i;
640 return block_size * sector_count;
641 }
642
643
644
645
646
647
648
649 static int
650 request_toc_data(Byte status[2], struct s535_sony_toc *toc)
651 {
652 int to_status;
653 int i, j, n_tracks, track_no;
654 int first_track_num, last_track_num;
655 Byte cmd_no = 0xb2;
656 Byte track_address_buffer[5];
657
658
659 if ((to_status = do_sony_cmd(&cmd_no, 1, status, (Byte *) toc, 15, 1)) != 0)
660 return to_status;
661
662
663 first_track_num = bcd_to_int(toc->first_track_num);
664 last_track_num = bcd_to_int(toc->last_track_num);
665 n_tracks = last_track_num - first_track_num + 1;
666
667
668 for (i = 0; i < n_tracks; i++) {
669
670 for (j = 0; j < 5; j++) {
671 if (read_result_reg(track_address_buffer + j) != 0)
672 return TIME_OUT;
673 if (j == 1)
674 track_no = bcd_to_int(track_address_buffer[j]);
675 }
676
677 memcpy(toc->tracks + i, track_address_buffer, 5);
678 }
679 return 0;
680 }
681
682
683
684
685
686
687 static int
688 spin_up_drive(Byte status[2])
689 {
690 Byte cmd;
691
692
693 cmd = SONY535_REQUEST_DRIVE_STATUS_1;
694 if (do_sony_cmd(&cmd, 1, status, NULL, 0, 0) != 0)
695 return TIME_OUT;
696 if ((status[0] & SONY535_STATUS1_NOT_SPINNING) == 0)
697 return 0;
698
699
700 cmd = SONY535_SPIN_UP;
701 return do_sony_cmd(&cmd, 1, status, NULL, 0, 0);
702 }
703
704
705
706
707 static inline unsigned int
708 int_to_bcd(unsigned int val)
709 {
710 int retval;
711
712 retval = (val / 10) << 4;
713 retval = retval | val % 10;
714 return retval;
715 }
716
717
718
719 static unsigned int
720 bcd_to_int(unsigned int bcd)
721 {
722 return (((bcd >> 4) & 0x0f) * 10) + (bcd & 0x0f);
723 }
724
725
726
727
728
729
730 static void
731 log_to_msf(unsigned int log, Byte *msf)
732 {
733 log = log + LOG_START_OFFSET;
734 msf[0] = int_to_bcd(log / 4500);
735 log = log % 4500;
736 msf[1] = int_to_bcd(log / 75);
737 msf[2] = int_to_bcd(log % 75);
738 }
739
740
741
742
743
744 static unsigned int
745 msf_to_log(Byte *msf)
746 {
747 unsigned int log;
748
749
750 log = bcd_to_int(msf[2]);
751 log += bcd_to_int(msf[1]) * 75;
752 log += bcd_to_int(msf[0]) * 4500;
753 log = log - LOG_START_OFFSET;
754
755 return log;
756 }
757
758
759
760
761
762
763 static void
764 size_to_buf(unsigned int size, Byte *buf)
765 {
766 buf[0] = size / 65536;
767 size = size % 65536;
768 buf[1] = size / 256;
769 buf[2] = size % 256;
770 }
771
772
773
774
775
776
777
778
779
780 static void
781 do_cdu535_request(void)
782 {
783 unsigned int dev;
784 unsigned int read_size;
785 int block;
786 int nsect;
787 int copyoff;
788 int spin_up_retry;
789 Byte params[10];
790 Byte status[2];
791 Byte cmd[2];
792
793 if (!sony_inuse) {
794 cdu_open(NULL, NULL);
795 }
796 while (1) {
797
798
799
800
801 if (!(CURRENT) || CURRENT->rq_status == RQ_INACTIVE) {
802 return;
803 }
804 INIT_REQUEST;
805 dev = MINOR(CURRENT->rq_dev);
806 block = CURRENT->sector;
807 nsect = CURRENT->nr_sectors;
808 if (dev != 0) {
809 end_request(0);
810 continue;
811 }
812 switch (CURRENT->cmd) {
813 case READ:
814
815
816
817
818
819 if (sony_toc->lead_out_start_lba <= (block / 4)) {
820 end_request(0);
821 return;
822 }
823 if (sony_toc->lead_out_start_lba <= ((block + nsect) / 4)) {
824 end_request(0);
825 return;
826 }
827 while (0 < nsect) {
828
829
830
831
832 if ((block < sony_first_block) || (sony_last_block < block)) {
833 sony_first_block = (block / 4) * 4;
834 log_to_msf(block / 4, params);
835
836
837
838
839
840 if (sony_toc->lead_out_start_lba <= ((block / 4) + sony_buffer_sectors)) {
841 sony_last_block = (sony_toc->lead_out_start_lba * 4) - 1;
842 read_size = sony_toc->lead_out_start_lba - (block / 4);
843 } else {
844 sony_last_block = sony_first_block + (sony_buffer_sectors * 4) - 1;
845 read_size = sony_buffer_sectors;
846 }
847 size_to_buf(read_size, ¶ms[3]);
848
849
850
851
852
853 for (spin_up_retry=0 ;; ++spin_up_retry) {
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873 int readStatus = seek_and_read_N_blocks(params, read_size,
874 status, sony_buffer, (read_size * 2048));
875 if (0 <= readStatus)
876 break;
877 if (readStatus == NO_ROOM || spin_up_retry == MAX_SPINUP_RETRY) {
878
879 if (readStatus == NO_ROOM)
880 printk(CDU535_MESSAGE_NAME " No room to read from CD\n");
881 else
882 printk(CDU535_MESSAGE_NAME " Read error: 0x%.2x\n",
883 status[0]);
884 sony_first_block = -1;
885 sony_last_block = -1;
886 end_request(0);
887 return;
888 }
889 if (readStatus == BAD_STATUS) {
890
891 current->state = TASK_INTERRUPTIBLE;
892 current->timeout = jiffies + RETRY_FOR_BAD_STATUS;
893 schedule();
894 }
895 #if DEBUG > 0
896 printk(CDU535_MESSAGE_NAME
897 " debug: calling spin up when reading data!\n");
898 #endif
899 cmd[0] = SONY535_SPIN_UP;
900 do_sony_cmd(cmd, 1, status, NULL, 0, 0);
901 }
902 }
903
904
905
906
907 copyoff = block - sony_first_block;
908 memcpy(CURRENT->buffer,
909 sony_buffer[copyoff / 4] + 512 * (copyoff % 4), 512);
910
911 block += 1;
912 nsect -= 1;
913 CURRENT->buffer += 512;
914 }
915
916 end_request(1);
917 break;
918
919 case WRITE:
920 end_request(0);
921 break;
922
923 default:
924 panic("Unknown SONY CD cmd");
925 }
926 }
927 }
928
929
930
931
932
933
934 static void
935 sony_get_toc(void)
936 {
937 Byte status[2];
938 if (!sony_toc_read) {
939
940 if (request_toc_data(status, sony_toc) < 0)
941 return;
942 sony_toc->lead_out_start_lba = msf_to_log(sony_toc->lead_out_start_msf);
943 sony_toc_read = 1;
944 }
945 }
946
947
948
949
950
951
952 static int
953 find_track(int track)
954 {
955 int i;
956 int num_tracks;
957
958
959 num_tracks = bcd_to_int(sony_toc->last_track_num) -
960 bcd_to_int(sony_toc->first_track_num) + 1;
961 for (i = 0; i < num_tracks; i++) {
962 if (sony_toc->tracks[i].track == track) {
963 return i;
964 }
965 }
966
967 return -1;
968 }
969
970
971
972
973 static int
974 read_subcode(void)
975 {
976 Byte cmd = SONY535_REQUEST_SUB_Q_DATA;
977 Byte status[2];
978 int dsc_status;
979
980 if (check_drive_status() != 0)
981 return -EIO;
982
983 if ((dsc_status = do_sony_cmd(&cmd, 1, status, (Byte *) last_sony_subcode,
984 sizeof(struct s535_sony_subcode), 1)) != 0) {
985 printk(CDU535_MESSAGE_NAME " error 0x%.2x, %d (read_subcode)\n",
986 status[0], dsc_status);
987 return -EIO;
988 }
989 return 0;
990 }
991
992
993
994
995
996
997
998
999
1000 static int
1001 sony_get_subchnl_info(long arg)
1002 {
1003 struct cdrom_subchnl schi;
1004 int err;
1005
1006
1007 if (check_drive_status() != 0)
1008 return -EIO;
1009
1010 sony_get_toc();
1011 if (!sony_toc_read) {
1012 return -EIO;
1013 }
1014 err = verify_area(VERIFY_WRITE , (char *)arg, sizeof schi);
1015 if (err)
1016 return err;
1017
1018 memcpy_fromfs(&schi, (char *)arg, sizeof schi);
1019
1020 switch (sony_audio_status) {
1021 case CDROM_AUDIO_PLAY:
1022 if (read_subcode() < 0) {
1023 return -EIO;
1024 }
1025 break;
1026
1027 case CDROM_AUDIO_PAUSED:
1028 case CDROM_AUDIO_COMPLETED:
1029 break;
1030
1031 case CDROM_AUDIO_NO_STATUS:
1032 schi.cdsc_audiostatus = sony_audio_status;
1033 memcpy_tofs((char *)arg, &schi, sizeof schi);
1034 return 0;
1035 break;
1036
1037 case CDROM_AUDIO_INVALID:
1038 case CDROM_AUDIO_ERROR:
1039 default:
1040 return -EIO;
1041 }
1042
1043 schi.cdsc_audiostatus = sony_audio_status;
1044 schi.cdsc_adr = last_sony_subcode->address;
1045 schi.cdsc_ctrl = last_sony_subcode->control;
1046 schi.cdsc_trk = bcd_to_int(last_sony_subcode->track_num);
1047 schi.cdsc_ind = bcd_to_int(last_sony_subcode->index_num);
1048 if (schi.cdsc_format == CDROM_MSF) {
1049 schi.cdsc_absaddr.msf.minute = bcd_to_int(last_sony_subcode->abs_msf[0]);
1050 schi.cdsc_absaddr.msf.second = bcd_to_int(last_sony_subcode->abs_msf[1]);
1051 schi.cdsc_absaddr.msf.frame = bcd_to_int(last_sony_subcode->abs_msf[2]);
1052
1053 schi.cdsc_reladdr.msf.minute = bcd_to_int(last_sony_subcode->rel_msf[0]);
1054 schi.cdsc_reladdr.msf.second = bcd_to_int(last_sony_subcode->rel_msf[1]);
1055 schi.cdsc_reladdr.msf.frame = bcd_to_int(last_sony_subcode->rel_msf[2]);
1056 } else if (schi.cdsc_format == CDROM_LBA) {
1057 schi.cdsc_absaddr.lba = msf_to_log(last_sony_subcode->abs_msf);
1058 schi.cdsc_reladdr.lba = msf_to_log(last_sony_subcode->rel_msf);
1059 }
1060 memcpy_tofs((char *)arg, &schi, sizeof schi);
1061 return 0;
1062 }
1063
1064
1065
1066
1067
1068 static int
1069 cdu_ioctl(struct inode *inode,
1070 struct file *file,
1071 unsigned int cmd,
1072 unsigned long arg)
1073 {
1074 unsigned int dev;
1075 Byte status[2];
1076 Byte cmd_buff[10], params[10];
1077 int i;
1078 int dsc_status;
1079 int err;
1080
1081 if (!inode) {
1082 return -EINVAL;
1083 }
1084 dev = MINOR(inode->i_rdev) >> 6;
1085 if (dev != 0) {
1086 return -EINVAL;
1087 }
1088 if (check_drive_status() != 0)
1089 return -EIO;
1090
1091 switch (cmd) {
1092 case CDROMSTART:
1093 if (spin_up_drive(status) < 0) {
1094 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTART)\n",
1095 status[0]);
1096 return -EIO;
1097 }
1098 return 0;
1099 break;
1100
1101 case CDROMSTOP:
1102 cmd_buff[0] = SONY535_HOLD;
1103 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1104
1105
1106
1107
1108
1109 sony_audio_status = CDROM_AUDIO_NO_STATUS;
1110 cmd_buff[0] = SONY535_SPIN_DOWN;
1111 dsc_status = do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1112 if (((dsc_status < 0) && (dsc_status != BAD_STATUS)) ||
1113 ((status[0] & ~(SONY535_STATUS1_NOT_SPINNING)) != 0)) {
1114 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMSTOP)\n",
1115 status[0]);
1116 return -EIO;
1117 }
1118 return 0;
1119 break;
1120
1121 case CDROMPAUSE:
1122 cmd_buff[0] = SONY535_HOLD;
1123 if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
1124 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPAUSE)\n",
1125 status[0]);
1126 return -EIO;
1127 }
1128
1129 if (read_subcode() < 0) {
1130 return -EIO;
1131 }
1132 cur_pos_msf[0] = last_sony_subcode->abs_msf[0];
1133 cur_pos_msf[1] = last_sony_subcode->abs_msf[1];
1134 cur_pos_msf[2] = last_sony_subcode->abs_msf[2];
1135 sony_audio_status = CDROM_AUDIO_PAUSED;
1136 return 0;
1137 break;
1138
1139 case CDROMRESUME:
1140 set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1141
1142 if (sony_audio_status != CDROM_AUDIO_PAUSED) {
1143 return -EINVAL;
1144 }
1145 spin_up_drive(status);
1146
1147
1148 cmd_buff[0] = SONY535_PLAY_AUDIO;
1149 cmd_buff[1] = 0;
1150 cmd_buff[2] = cur_pos_msf[0];
1151 cmd_buff[3] = cur_pos_msf[1];
1152 cmd_buff[4] = cur_pos_msf[2];
1153 cmd_buff[5] = SONY535_PLAY_AUDIO;
1154 cmd_buff[6] = 2;
1155 cmd_buff[7] = final_pos_msf[0];
1156 cmd_buff[8] = final_pos_msf[1];
1157 cmd_buff[9] = final_pos_msf[2];
1158 if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1159 (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1160 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMRESUME)\n",
1161 status[0]);
1162 return -EIO;
1163 }
1164 sony_audio_status = CDROM_AUDIO_PLAY;
1165 return 0;
1166 break;
1167
1168 case CDROMPLAYMSF:
1169 err = verify_area(VERIFY_READ, (char *)arg, 6);
1170 if (err)
1171 return err;
1172 spin_up_drive(status);
1173 set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1174 memcpy_fromfs(params, (void *)arg, 6);
1175
1176
1177 for (i = 0; i < 3; i++) {
1178 cmd_buff[2 + i] = int_to_bcd(params[i]);
1179 cmd_buff[7 + i] = int_to_bcd(params[i + 3]);
1180 }
1181 cmd_buff[0] = SONY535_PLAY_AUDIO;
1182 cmd_buff[1] = 0;
1183
1184 cmd_buff[5] = SONY535_PLAY_AUDIO;
1185 cmd_buff[6] = 2;
1186
1187 if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1188 (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1189 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYMSF)\n",
1190 status[0]);
1191 return -EIO;
1192 }
1193
1194 final_pos_msf[0] = cmd_buff[7];
1195 final_pos_msf[1] = cmd_buff[8];
1196 final_pos_msf[2] = cmd_buff[9];
1197 sony_audio_status = CDROM_AUDIO_PLAY;
1198 return 0;
1199 break;
1200
1201 case CDROMREADTOCHDR:
1202 {
1203 struct cdrom_tochdr *hdr;
1204 struct cdrom_tochdr loc_hdr;
1205
1206 sony_get_toc();
1207 if (!sony_toc_read)
1208 return -EIO;
1209 hdr = (struct cdrom_tochdr *)arg;
1210 err = verify_area(VERIFY_WRITE, hdr, sizeof *hdr);
1211 if (err)
1212 return err;
1213 loc_hdr.cdth_trk0 = bcd_to_int(sony_toc->first_track_num);
1214 loc_hdr.cdth_trk1 = bcd_to_int(sony_toc->last_track_num);
1215 memcpy_tofs(hdr, &loc_hdr, sizeof *hdr);
1216 }
1217 return 0;
1218 break;
1219
1220 case CDROMREADTOCENTRY:
1221 {
1222 struct cdrom_tocentry *entry;
1223 struct cdrom_tocentry loc_entry;
1224 int track_idx;
1225 Byte *msf_val = NULL;
1226
1227 sony_get_toc();
1228 if (!sony_toc_read) {
1229 return -EIO;
1230 }
1231 entry = (struct cdrom_tocentry *)arg;
1232 err = verify_area(VERIFY_WRITE , entry, sizeof *entry);
1233 if (err)
1234 return err;
1235
1236 memcpy_fromfs(&loc_entry, entry, sizeof loc_entry);
1237
1238
1239 if (loc_entry.cdte_track == CDROM_LEADOUT) {
1240 loc_entry.cdte_adr = 0 ;
1241 loc_entry.cdte_ctrl = sony_toc->control2;
1242 msf_val = sony_toc->lead_out_start_msf;
1243 } else {
1244 track_idx = find_track(int_to_bcd(loc_entry.cdte_track));
1245 if (track_idx < 0)
1246 return -EINVAL;
1247 loc_entry.cdte_adr = 0 ;
1248 loc_entry.cdte_ctrl = sony_toc->tracks[track_idx].control;
1249 msf_val = sony_toc->tracks[track_idx].track_start_msf;
1250 }
1251
1252
1253 if (loc_entry.cdte_format == CDROM_LBA) {
1254 loc_entry.cdte_addr.lba = msf_to_log(msf_val);
1255 } else if (loc_entry.cdte_format == CDROM_MSF) {
1256 loc_entry.cdte_addr.msf.minute = bcd_to_int(*msf_val);
1257 loc_entry.cdte_addr.msf.second = bcd_to_int(*(msf_val + 1));
1258 loc_entry.cdte_addr.msf.frame = bcd_to_int(*(msf_val + 2));
1259 }
1260 memcpy_tofs(entry, &loc_entry, sizeof *entry);
1261 }
1262 return 0;
1263 break;
1264
1265 case CDROMPLAYTRKIND:
1266 {
1267 struct cdrom_ti ti;
1268 int track_idx;
1269
1270 sony_get_toc();
1271 if (!sony_toc_read)
1272 return -EIO;
1273 err = verify_area(VERIFY_READ, (char *)arg, sizeof ti);
1274 if (err)
1275 return err;
1276
1277 memcpy_fromfs(&ti, (char *)arg, sizeof ti);
1278 if ((ti.cdti_trk0 < sony_toc->first_track_num)
1279 || (sony_toc->last_track_num < ti.cdti_trk0)
1280 || (ti.cdti_trk1 < ti.cdti_trk0)) {
1281 return -EINVAL;
1282 }
1283 track_idx = find_track(int_to_bcd(ti.cdti_trk0));
1284 if (track_idx < 0)
1285 return -EINVAL;
1286 params[1] = sony_toc->tracks[track_idx].track_start_msf[0];
1287 params[2] = sony_toc->tracks[track_idx].track_start_msf[1];
1288 params[3] = sony_toc->tracks[track_idx].track_start_msf[2];
1289
1290
1291
1292
1293 if (bcd_to_int(sony_toc->last_track_num) <= ti.cdti_trk1) {
1294 log_to_msf(msf_to_log(sony_toc->lead_out_start_msf) - 1,
1295 &(params[4]));
1296 } else {
1297 track_idx = find_track(int_to_bcd(ti.cdti_trk1 + 1));
1298 if (track_idx < 0)
1299 return -EINVAL;
1300 log_to_msf(msf_to_log(sony_toc->tracks[track_idx].track_start_msf) - 1,
1301 &(params[4]));
1302 }
1303 params[0] = 0x03;
1304
1305 spin_up_drive(status);
1306
1307 set_drive_mode(SONY535_AUDIO_DRIVE_MODE, status);
1308
1309
1310 cmd_buff[0] = SONY535_PLAY_AUDIO;
1311 cmd_buff[1] = 0;
1312 cmd_buff[2] = params[1];
1313 cmd_buff[3] = params[2];
1314 cmd_buff[4] = params[3];
1315 cmd_buff[5] = SONY535_PLAY_AUDIO;
1316 cmd_buff[6] = 2;
1317 cmd_buff[7] = params[4];
1318 cmd_buff[8] = params[5];
1319 cmd_buff[9] = params[6];
1320 if ((do_sony_cmd(cmd_buff, 5, status, NULL, 0, 0) != 0) ||
1321 (do_sony_cmd(cmd_buff + 5, 5, status, NULL, 0, 0) != 0)) {
1322 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMPLAYTRKIND)\n",
1323 status[0]);
1324 printk("... Params: %x %x %x %x %x %x %x\n",
1325 params[0], params[1], params[2],
1326 params[3], params[4], params[5], params[6]);
1327 return -EIO;
1328 }
1329
1330 final_pos_msf[0] = params[4];
1331 final_pos_msf[1] = params[5];
1332 final_pos_msf[2] = params[6];
1333 sony_audio_status = CDROM_AUDIO_PLAY;
1334 return 0;
1335 }
1336
1337 case CDROMSUBCHNL:
1338 return sony_get_subchnl_info(arg);
1339
1340 case CDROMVOLCTRL:
1341 {
1342 struct cdrom_volctrl volctrl;
1343
1344 err = verify_area(VERIFY_READ, (char *)arg, sizeof volctrl);
1345 if (err)
1346 return err;
1347
1348 memcpy_fromfs(&volctrl, (char *)arg, sizeof volctrl);
1349 cmd_buff[0] = SONY535_SET_VOLUME;
1350 cmd_buff[1] = volctrl.channel0;
1351 cmd_buff[2] = volctrl.channel1;
1352 if (do_sony_cmd(cmd_buff, 3, status, NULL, 0, 0) != 0) {
1353 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMVOLCTRL)\n",
1354 status[0]);
1355 return -EIO;
1356 }
1357 }
1358 return 0;
1359
1360 case CDROMEJECT:
1361 cmd_buff[0] = SONY535_STOP;
1362 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1363 cmd_buff[0] = SONY535_SPIN_DOWN;
1364 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1365
1366 sony_audio_status = CDROM_AUDIO_INVALID;
1367 cmd_buff[0] = SONY535_EJECT_CADDY;
1368 if (do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0) != 0) {
1369 printk(CDU535_MESSAGE_NAME " error 0x%.2x (CDROMEJECT)\n",
1370 status[0]);
1371 return -EIO;
1372 }
1373 return 0;
1374 break;
1375
1376 default:
1377 return -EINVAL;
1378 }
1379 }
1380
1381
1382
1383
1384
1385
1386 static int
1387 cdu_open(struct inode *inode,
1388 struct file *filp)
1389 {
1390 Byte status[2], cmd_buff[2];
1391
1392
1393 if (sony_inuse)
1394 return -EBUSY;
1395 if (check_drive_status() != 0)
1396 return -EIO;
1397 sony_inuse = 1;
1398 MOD_INC_USE_COUNT;
1399
1400 if (spin_up_drive(status) != 0) {
1401 printk(CDU535_MESSAGE_NAME " error 0x%.2x (cdu_open, spin up)\n",
1402 status[0]);
1403 sony_inuse = 0;
1404 MOD_DEC_USE_COUNT;
1405 return -EIO;
1406 }
1407 sony_get_toc();
1408 if (!sony_toc_read) {
1409 cmd_buff[0] = SONY535_SPIN_DOWN;
1410 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1411 sony_inuse = 0;
1412 MOD_DEC_USE_COUNT;
1413 return -EIO;
1414 }
1415 if (inode) {
1416 check_disk_change(inode->i_rdev);
1417 }
1418 sony_usage++;
1419
1420 #ifdef LOCK_DOORS
1421
1422 cmd_buff[0] = SONY535_DISABLE_EJECT_BUTTON;
1423 do_sony_cmd(cmd_buff, 1, status, NULL, 0, 0);
1424 #endif
1425
1426 return 0;
1427 }
1428
1429
1430
1431
1432
1433
1434 static void
1435 cdu_release(struct inode *inode,
1436 struct file *filp)
1437 {
1438 Byte status[2], cmd_no;
1439
1440 sony_inuse = 0;
1441 MOD_DEC_USE_COUNT;
1442
1443 if (0 < sony_usage) {
1444 sony_usage--;
1445 }
1446 if (sony_usage == 0) {
1447 sync_dev(inode->i_rdev);
1448 check_drive_status();
1449
1450 if (sony_audio_status != CDROM_AUDIO_PLAY) {
1451 cmd_no = SONY535_SPIN_DOWN;
1452 do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
1453 }
1454 #ifdef LOCK_DOORS
1455
1456 cmd_no = SONY535_ENABLE_EJECT_BUTTON;
1457 do_sony_cmd(&cmd_no, 1, status, NULL, 0, 0);
1458 #endif
1459 }
1460 }
1461
1462
1463 static struct file_operations cdu_fops =
1464 {
1465 NULL,
1466 block_read,
1467 block_write,
1468 NULL,
1469 NULL,
1470 cdu_ioctl,
1471 NULL,
1472 cdu_open,
1473 cdu_release,
1474 NULL,
1475 NULL,
1476 cdu535_check_media_change,
1477 NULL
1478 };
1479
1480
1481
1482
1483 int
1484 sony535_init(void)
1485 {
1486 struct s535_sony_drive_config drive_config;
1487 Byte cmd_buff[3];
1488 Byte ret_buff[2];
1489 Byte status[2];
1490 int retry_count;
1491 int tmp_irq;
1492 int i;
1493
1494
1495 if ((sony535_cd_base_io == 0xffff)||(sony535_cd_base_io == 0))
1496 return 0;
1497
1498
1499 result_reg = sony535_cd_base_io;
1500 command_reg = sony535_cd_base_io;
1501 data_reg = sony535_cd_base_io + 1;
1502 read_status_reg = sony535_cd_base_io + 2;
1503 select_unit_reg = sony535_cd_base_io + 3;
1504
1505 #ifndef USE_IRQ
1506 sony535_irq_used = 0;
1507 #endif
1508
1509 tmp_irq = sony535_irq_used;
1510 sony535_irq_used = 0;
1511
1512 #if DEBUG > 0
1513 printk(CDU535_MESSAGE_NAME ": probing base address %03X\n",
1514 sony535_cd_base_io);
1515 #endif
1516 if (check_region(sony535_cd_base_io,4)) {
1517 printk(CDU535_MESSAGE_NAME ": my base address is not free!\n");
1518 return -EIO;
1519 }
1520
1521 inb(select_unit_reg);
1522 retry_count = jiffies + 2 * HZ;
1523 while (jiffies < retry_count)
1524 sony_sleep();
1525 inb(result_reg);
1526
1527 outb(0, read_status_reg);
1528 retry_count = jiffies + SONY_JIFFIES_TIMEOUT;
1529 while (jiffies < retry_count) {
1530 select_unit(0);
1531 if (inb(result_reg) != 0xff)
1532 break;
1533 sony_sleep();
1534 }
1535
1536 if ((jiffies < retry_count) && (check_drive_status() != TIME_OUT)) {
1537
1538 cmd_buff[0] = SONY535_INQUIRY;
1539 if (do_sony_cmd(cmd_buff, 1, status,
1540 (Byte *)&drive_config, 28, 1) == 0) {
1541
1542
1543
1544 #if DEBUG > 0
1545
1546 if ( (status[0] & 0x7f) != 0 && (status[0] & 0x7f) != 0x50 )
1547 printk(CDU535_MESSAGE_NAME
1548 "Inquiry command returned status = 0x%x\n", status[0]);
1549 #endif
1550
1551 sony535_irq_used = tmp_irq;
1552 #ifndef MODULE
1553
1554
1555
1556
1557 if (sony535_irq_used < 0) {
1558 autoirq_setup(0);
1559 enable_interrupts();
1560 outb(0, read_status_reg);
1561 sony535_irq_used = autoirq_report(10);
1562 disable_interrupts();
1563 }
1564 #endif
1565 if (sony535_irq_used > 0) {
1566 if (request_irq(sony535_irq_used, cdu535_interrupt,
1567 SA_INTERRUPT, CDU535_HANDLE)) {
1568 printk("Unable to grab IRQ%d for the " CDU535_MESSAGE_NAME
1569 " driver; polling instead.\n", sony535_irq_used);
1570 sony535_irq_used = 0;
1571 }
1572 }
1573 cmd_buff[0] = SONY535_SET_DRIVE_MODE;
1574 cmd_buff[1] = 0x0;
1575 if (do_sony_cmd(cmd_buff, 2, status, ret_buff, 1, 1) == 0) {
1576
1577 sony_buffer_size = SONY535_BUFFER_SIZE;
1578 sony_buffer_sectors = sony_buffer_size / 2048;
1579
1580 printk(CDU535_MESSAGE_NAME " I/F CDROM : %8.8s %16.16s %4.4s",
1581 drive_config.vendor_id,
1582 drive_config.product_id,
1583 drive_config.product_rev_level);
1584 printk(" base address %03X, ", sony535_cd_base_io);
1585 if (tmp_irq > 0)
1586 printk("IRQ%d, ", tmp_irq);
1587 printk("using %d byte buffer\n", sony_buffer_size);
1588
1589 if (register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) {
1590 printk("Unable to get major %d for %s\n",
1591 MAJOR_NR, CDU535_MESSAGE_NAME);
1592 return -EIO;
1593 }
1594 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1595 read_ahead[MAJOR_NR] = 8;
1596
1597 sony_toc = (struct s535_sony_toc *)
1598 kmalloc(sizeof *sony_toc, GFP_KERNEL);
1599 if (sony_toc == NULL)
1600 return -ENOMEM;
1601 last_sony_subcode = (struct s535_sony_subcode *)
1602 kmalloc(sizeof *last_sony_subcode, GFP_KERNEL);
1603 if (last_sony_subcode == NULL) {
1604 kfree(sony_toc);
1605 return -ENOMEM;
1606 }
1607 sony_buffer = (Byte **)
1608 kmalloc(4 * sony_buffer_sectors, GFP_KERNEL);
1609 if (sony_buffer == NULL) {
1610 kfree(sony_toc);
1611 kfree(last_sony_subcode);
1612 return -ENOMEM;
1613 }
1614 for (i = 0; i < sony_buffer_sectors; i++) {
1615 sony_buffer[i] = (Byte *)kmalloc(2048, GFP_KERNEL);
1616 if (sony_buffer[i] == NULL) {
1617 while (--i>=0)
1618 kfree(sony_buffer[i]);
1619 kfree(sony_buffer);
1620 kfree(sony_toc);
1621 kfree(last_sony_subcode);
1622 return -ENOMEM;
1623 }
1624 }
1625 initialized = 1;
1626 }
1627 }
1628 }
1629
1630 if (!initialized) {
1631 printk("Did not find a " CDU535_MESSAGE_NAME " drive\n");
1632 return -EIO;
1633 }
1634 request_region(sony535_cd_base_io, 4, CDU535_HANDLE);
1635 return 0;
1636 }
1637
1638 #ifndef MODULE
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648 void
1649 sonycd535_setup(char *strings, int *ints)
1650 {
1651
1652
1653
1654 if (ints[0] > 0)
1655 if (ints[0] != 0)
1656 sony535_cd_base_io = ints[1];
1657 if (ints[0] > 1)
1658 sony535_irq_used = ints[2];
1659 if ((strings != NULL) && (*strings != '\0'))
1660 printk(CDU535_MESSAGE_NAME
1661 ": Warning: Unknown interface type: %s\n", strings);
1662 }
1663
1664 #else
1665
1666 int init_module(void)
1667 {
1668 return sony535_init();
1669 }
1670
1671 void
1672 cleanup_module(void)
1673 {
1674 int i;
1675
1676 release_region(sony535_cd_base_io, 4);
1677 for (i = 0; i < sony_buffer_sectors; i++)
1678 kfree_s(sony_buffer[i], 2048);
1679 kfree_s(sony_buffer, 4 * sony_buffer_sectors);
1680 kfree_s(last_sony_subcode, sizeof *last_sony_subcode);
1681 kfree_s(sony_toc, sizeof *sony_toc);
1682 if (unregister_blkdev(MAJOR_NR, CDU535_HANDLE) == -EINVAL)
1683 printk("Uh oh, couldn't unregister " CDU535_HANDLE "\n");
1684 else
1685 printk(CDU535_HANDLE " module released\n");
1686 }
1687 #endif