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