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