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