This source file includes following definitions.
- check_gscd_med_chg
- gscd_setup
- gscd_ioctl
- gscd_transfer
- do_gscd_request
- gscd_read_cmd
- gscd_open
- gscd_release
- get_status
- cc_invalidate
- clear_Audio
- wait_drv_ready
- cc_Ident
- cc_SetSpeed
- cc_Reset
- cmd_status
- cmd_out
- cmd_write_cmd
- cmd_unit_alive
- cmd_info_in
- cmd_read_b
- cmd_end
- cmd_read_w
- find_drives
- init_cd_drive
- update_state
- init_module
- cleanup_module
- gscd_init
- my_gscd_init
- gscd_hsg2msf
- gscd_bin2bcd
- gscd_msf2hsg
- gscd_bcd2bin
1 #define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
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 #define NO_GSCD_DEBUG
39 #define NO_IOCTL_DEBUG
40 #define NO_MODULE_DEBUG
41 #define NO_FUTURE_WORK
42
43
44 #include <linux/module.h>
45
46 #include <linux/malloc.h>
47 #include <linux/errno.h>
48 #include <linux/signal.h>
49 #include <linux/sched.h>
50 #include <linux/timer.h>
51 #include <linux/fs.h>
52 #include <linux/mm.h>
53 #include <linux/kernel.h>
54 #include <linux/cdrom.h>
55 #include <linux/ioport.h>
56 #include <linux/major.h>
57 #include <linux/string.h>
58
59 #include <asm/system.h>
60 #include <asm/io.h>
61 #include <asm/segment.h>
62
63 #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
64 #include <linux/blk.h>
65 #define gscd_port gscd
66 #include <linux/gscd.h>
67
68
69 static int gscdPresent = 0;
70
71 static unsigned char gscd_buf[2048];
72 static int gscd_bn = -1;
73 static short gscd_port = GSCD_BASE_ADDR;
74
75
76
77
78
79 static void gscd_transfer (void);
80 static void gscd_read_cmd (void);
81 static void gscd_hsg2msf (long hsg, struct msf *msf);
82 static void gscd_bin2bcd (unsigned char *p);
83
84
85
86 static void do_gscd_request (void);
87 static int gscd_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
88 static int gscd_open (struct inode *, struct file *);
89 static void gscd_release (struct inode *, struct file *);
90 static int check_gscd_med_chg (kdev_t);
91
92
93
94 static void cc_Reset (void);
95 static int wait_drv_ready (void);
96 static int find_drives (void);
97 static void cmd_out (int, char *, char *, int);
98 static void cmd_status (void);
99 static void cc_Ident (char *);
100 static void cc_SetSpeed (void);
101 static void init_cd_drive (int);
102
103 static int get_status (void);
104 static void clear_Audio (void);
105 static void cc_invalidate (void);
106
107
108 #ifdef FUTURE_WORK
109 static void update_state (void);
110 static long gscd_msf2hsg (struct msf *mp);
111 static int gscd_bcd2bin (unsigned char bcd);
112 #endif
113
114
115
116 static int my_gscd_init (void);
117
118
119
120
121 static void cmd_info_in ( char *, int );
122 static void cmd_end ( void );
123 static void cmd_read_b ( char *, int, int );
124 static void cmd_read_w ( char *, int, int );
125 static int cmd_unit_alive ( void );
126 static void cmd_write_cmd ( char * );
127
128
129
130
131 static int curr_drv_state;
132 static int drv_states[] = {0,0,0,0,0,0,0,0};
133 static int drv_mode;
134 static int disk_state;
135 static int speed;
136 static int ndrives;
137
138 static unsigned char drv_num_read;
139 static unsigned char f_dsk_valid;
140 static unsigned char current_drive;
141 static unsigned char f_drv_ok;
142
143
144 static char f_AudioPlay;
145 static char f_AudioPause;
146 static int AudioStart_m;
147 static int AudioStart_f;
148 static int AudioEnd_m;
149 static int AudioEnd_f;
150
151
152 static struct file_operations gscd_fops = {
153 NULL,
154 block_read,
155 block_write,
156 NULL,
157 NULL,
158 gscd_ioctl,
159 NULL,
160 gscd_open,
161 gscd_release,
162 NULL,
163 NULL,
164 check_gscd_med_chg,
165 NULL
166 };
167
168
169
170
171
172 static int check_gscd_med_chg (kdev_t full_dev)
173 {
174 int target;
175
176
177 target = MINOR(full_dev);
178
179 if (target > 0)
180 {
181 printk("GSCD: GoldStar CD-ROM request error: invalid device.\n");
182 return 0;
183 }
184
185 #ifdef GSCD_DEBUG
186 printk ("gscd: check_med_change\n");
187 #endif
188
189 return 0;
190 }
191
192
193 void gscd_setup (char *str, int *ints)
194 {
195 if (ints[0] > 0)
196 {
197 gscd_port = ints[1];
198 }
199 }
200
201
202 static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
203 {
204 unsigned char to_do[10];
205 unsigned char dummy;
206
207
208 switch (cmd)
209 {
210 case CDROMSTART:
211
212
213
214
215 return 0;
216
217 case CDROMRESUME:
218 return 0;
219
220
221 case CDROMEJECT:
222 cmd_status ();
223 to_do[0] = CMD_TRAY_CTL;
224 cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
225
226 return 0;
227
228 default:
229 return -EINVAL;
230 }
231
232 }
233
234
235
236
237
238
239
240 static void gscd_transfer (void)
241 {
242 long offs;
243
244 while (CURRENT -> nr_sectors > 0 && gscd_bn == CURRENT -> sector / 4)
245 {
246 offs = (CURRENT -> sector & 3) * 512;
247 memcpy(CURRENT -> buffer, gscd_buf + offs, 512);
248 CURRENT -> nr_sectors--;
249 CURRENT -> sector++;
250 CURRENT -> buffer += 512;
251 }
252 }
253
254
255
256
257
258
259 static void do_gscd_request (void)
260 {
261 unsigned int block,dev;
262 unsigned int nsect;
263
264 repeat:
265 if (!(CURRENT) || CURRENT->rq_status == RQ_INACTIVE) return;
266 INIT_REQUEST;
267 dev = MINOR(CURRENT->rq_dev);
268 block = CURRENT->sector;
269 nsect = CURRENT->nr_sectors;
270
271 if (CURRENT == NULL || CURRENT -> sector == -1)
272 return;
273
274 if (CURRENT -> cmd != READ)
275 {
276 printk("GSCD: bad cmd %d\n", CURRENT -> cmd);
277 end_request(0);
278 goto repeat;
279 }
280
281 if (MINOR(CURRENT -> rq_dev) != 0)
282 {
283 printk("GSCD: this version supports only one device\n");
284 end_request(0);
285 goto repeat;
286 }
287
288 gscd_transfer();
289
290
291
292 if (CURRENT -> nr_sectors == 0)
293 {
294 end_request(1);
295 goto repeat;
296 }
297
298 #ifdef GSCD_DEBUG
299 printk ("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect );
300 #endif
301
302 gscd_read_cmd ();
303 }
304
305
306
307
308
309
310
311
312 static void
313 gscd_read_cmd (void)
314 {
315 long block;
316 struct gscd_Play_msf gscdcmd;
317 char cmd[] = { CMD_READ, 0x80, 0,0,0, 0,1 };
318
319
320
321 cmd_status ();
322 if ( disk_state & (ST_NO_DISK | ST_DOOR_OPEN) )
323 {
324 printk ( "GSCD: no disk or door open\n" );
325 end_request (0);
326 }
327 else
328 {
329 if ( disk_state & ST_INVALID )
330 {
331 printk ( "GSCD: disk invalid\n" );
332 end_request (0);
333 }
334 else
335 {
336 gscd_bn = -1;
337 block = CURRENT -> sector / 4;
338 gscd_hsg2msf(block, &gscdcmd.start);
339
340 cmd[2] = gscdcmd.start.min;
341 cmd[3] = gscdcmd.start.sec;
342 cmd[4] = gscdcmd.start.frame;
343
344 #ifdef GSCD_DEBUG
345 printk ("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], cmd[4] );
346 #endif
347 cmd_out ( TYPE_DATA, (char *)&cmd, (char *)&gscd_buf[0], 1 );
348
349 gscd_bn = CURRENT -> sector / 4;
350 gscd_transfer();
351 end_request(1);
352 }
353 }
354 SET_TIMER(do_gscd_request, 1);
355 }
356
357
358
359
360
361
362 static int gscd_open (struct inode *ip, struct file *fp)
363 {
364 int st;
365
366 #ifdef GSCD_DEBUG
367 printk ( "GSCD: open\n" );
368 #endif
369
370 if (gscdPresent == 0)
371 return -ENXIO;
372
373 get_status ();
374 st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
375 if ( st )
376 {
377 printk ( "GSCD: no disk or door open\n" );
378 return -ENXIO;
379 }
380
381
382
383
384
385 MOD_INC_USE_COUNT;
386
387 return 0;
388 }
389
390
391
392
393
394
395 static void gscd_release (struct inode * inode, struct file * file)
396 {
397
398 #ifdef GSCD_DEBUG
399 printk ( "GSCD: release\n" );
400 #endif
401
402 gscd_bn = -1;
403 sync_dev(inode->i_rdev);
404 invalidate_buffers(inode -> i_rdev);
405
406 MOD_DEC_USE_COUNT;
407 }
408
409
410 int get_status (void)
411 {
412 int status;
413
414 cmd_status ();
415 status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
416
417 if ( status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01) )
418 {
419 cc_invalidate ();
420 return 1;
421 }
422 else
423 {
424 return 0;
425 }
426 }
427
428
429 void cc_invalidate (void)
430 {
431 drv_num_read = 0xFF;
432 f_dsk_valid = 0xFF;
433 current_drive = 0xFF;
434 f_drv_ok = 0xFF;
435
436 clear_Audio ();
437
438 }
439
440 void clear_Audio (void)
441 {
442
443 f_AudioPlay = 0;
444 f_AudioPause = 0;
445 AudioStart_m = 0;
446 AudioStart_f = 0;
447 AudioEnd_m = 0;
448 AudioEnd_f = 0;
449
450 }
451
452
453
454
455
456 int wait_drv_ready (void)
457 {
458 int found, read;
459
460 do
461 {
462 found = inb ( GSCDPORT(0) );
463 found &= 0x0f;
464 read = inb ( GSCDPORT(0) );
465 read &= 0x0f;
466 } while ( read != found );
467
468 #ifdef GSCD_DEBUG
469 printk ( "Wait for: %d\n", read );
470 #endif
471
472 return read;
473 }
474
475 void cc_Ident (char * respons)
476 {
477 char to_do [] = {CMD_IDENT, 0, 0};
478
479 cmd_out (TYPE_INFO, (char *)&to_do, (char *)respons, (int)0x1E );
480
481 }
482
483 void cc_SetSpeed (void)
484 {
485 char to_do [] = {CMD_SETSPEED, 0, 0};
486 char dummy;
487
488 if ( speed > 0 )
489 {
490 to_do[1] = speed & 0x0F;
491 cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
492 }
493 }
494
495
496 void cc_Reset (void)
497 {
498 char to_do [] = {CMD_RESET, 0};
499 char dummy;
500
501 cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
502 }
503
504
505
506 void cmd_status (void)
507 {
508 char to_do [] = {CMD_STATUS, 0};
509 char dummy;
510
511 cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
512
513 #ifdef GSCD_DEBUG
514 printk ("GSCD: Status: %d\n", disk_state );
515 #endif
516
517 }
518
519 void cmd_out ( int cmd_type, char * cmd, char * respo_buf, int respo_count )
520 {
521 int result;
522
523
524 result = wait_drv_ready ();
525 if ( result != drv_mode )
526 {
527 unsigned long test_loops = 0xFFFF;
528 int i,dummy;
529
530 outb ( curr_drv_state, GSCDPORT(0));
531
532
533 do
534 {
535 result = wait_drv_ready ();
536 test_loops--;
537 } while ( (result != drv_mode) && (test_loops > 0) );
538
539 if ( result != drv_mode )
540 {
541 disk_state = ST_x08 | ST_x04 | ST_INVALID;
542 return;
543 }
544
545
546 for ( i=1,dummy=1 ; i<0xFFFF ; i++ )
547 {
548 dummy *= i;
549 }
550 }
551
552
553
554
555 if ( cmd_unit_alive () != 0x08 )
556 {
557
558
559 disk_state = ST_x08 | ST_x04 | ST_INVALID;
560 return;
561 }
562
563
564 #ifdef GSCD_DEBUG
565 printk ("LOC_176 ");
566 #endif
567 if ( drv_mode == 0x09 )
568 {
569
570 printk ("GSCD: magic ...\n");
571 outb ( result, GSCDPORT(2));
572 }
573
574
575 cmd_write_cmd (cmd);
576
577
578 for (;;)
579 {
580 result = wait_drv_ready ();
581 if ( result != drv_mode )
582 {
583
584 if ( result == 0x04 )
585 {
586
587 #ifdef GSCD_DEBUG
588 printk ("LOC_205 ");
589 #endif
590 disk_state = inb ( GSCDPORT (2));
591
592 do
593 {
594 result = wait_drv_ready ();
595 } while ( result != drv_mode );
596 return;
597
598 }
599 else
600 {
601 if ( result == 0x06 )
602 {
603
604 #ifdef GSCD_DEBUG
605 printk ("LOC_181 ");
606 #endif
607
608 if (cmd_type == TYPE_DATA)
609 {
610
611
612 if ( drv_mode == 9 )
613 {
614
615
616
617 cmd_read_w ( respo_buf, respo_count, CD_FRAMESIZE/2 );
618 return;
619 }
620 else
621 {
622
623
624
625 cmd_read_b ( respo_buf, respo_count, CD_FRAMESIZE );
626 return;
627 }
628 }
629 else
630 {
631
632 cmd_info_in ( respo_buf, respo_count );
633 return;
634 }
635
636 return;
637 }
638 }
639
640 }
641 else
642 {
643 disk_state = ST_x08 | ST_x04 | ST_INVALID;
644 return;
645 }
646 }
647
648
649 #ifdef GSCD_DEBUG
650 printk ("\n");
651 #endif
652 }
653
654
655 static void cmd_write_cmd ( char *pstr )
656 {
657 int i,j;
658
659
660 #ifdef GSCD_DEBUG
661 printk ("LOC_177 ");
662 #endif
663
664
665 j = *pstr & 0x0F;
666
667
668 for ( i=0 ; i<j ; i++ )
669 {
670 outb ( *pstr, GSCDPORT(2) );
671 pstr++;
672 }
673 }
674
675
676 static int cmd_unit_alive ( void )
677 {
678 int result;
679 unsigned long max_test_loops;
680
681
682
683 #ifdef GSCD_DEBUG
684 printk ("LOC_172 ");
685 #endif
686
687 outb ( curr_drv_state, GSCDPORT(0));
688 max_test_loops = 0xFFFF;
689
690 do
691 {
692 result = wait_drv_ready ();
693 max_test_loops--;
694 } while ( (result != 0x08) && (max_test_loops > 0) );
695
696 return result;
697 }
698
699
700 static void cmd_info_in ( char *pb, int count )
701 {
702 int result;
703 char read;
704
705
706
707
708 #ifdef GSCD_DEBUG
709 printk ("LOC_182 ");
710 #endif
711
712 do
713 {
714 read = inb (GSCDPORT(2));
715 if ( count > 0 )
716 {
717 *pb = read;
718 pb++;
719 count--;
720 }
721
722
723 do
724 {
725 result = wait_drv_ready ();
726 } while ( result == 0x0E );
727 } while ( result == 6 );
728
729 cmd_end ();
730 return;
731 }
732
733
734 static void cmd_read_b ( char *pb, int count, int size )
735 {
736 int result;
737 int i;
738
739
740
741
742 #ifdef GSCD_DEBUG
743 printk ("LOC_189 ");
744 #endif
745
746 do
747 {
748 do
749 {
750 result = wait_drv_ready ();
751 } while ( result != 6 || result == 0x0E );
752
753 if ( result != 6 )
754 {
755 cmd_end ();
756 return;
757 }
758
759 #ifdef GSCD_DEBUG
760 printk ("LOC_191 ");
761 #endif
762
763 for ( i=0 ; i< size ; i++ )
764 {
765 *pb = inb (GSCDPORT(2));
766 pb++;
767 }
768 count--;
769 } while ( count > 0 );
770
771 cmd_end ();
772 return;
773 }
774
775
776 static void cmd_end (void)
777 {
778 int result;
779
780
781
782 #ifdef GSCD_DEBUG
783 printk ("LOC_204 ");
784 #endif
785
786 do
787 {
788 result = wait_drv_ready ();
789 if ( result == drv_mode )
790 {
791 return;
792 }
793 } while ( result != 4 );
794
795
796 #ifdef GSCD_DEBUG
797 printk ("LOC_205 ");
798 #endif
799
800 disk_state = inb ( GSCDPORT (2));
801
802 do
803 {
804 result = wait_drv_ready ();
805 } while ( result != drv_mode );
806 return;
807
808 }
809
810
811 static void cmd_read_w ( char *pb, int count, int size )
812 {
813 int result;
814 int i;
815
816
817 #ifdef GSCD_DEBUG
818 printk ("LOC_185 ");
819 #endif
820
821 do
822 {
823
824 do
825 {
826 result = wait_drv_ready ();
827 } while ( result != 6 || result == 0x0E );
828
829 if ( result != 6 )
830 {
831 cmd_end ();
832 return;
833 }
834
835 for ( i=0 ; i<size ; i++ )
836 {
837
838 *pb = inw(GSCDPORT(2));
839 pb++;
840 }
841 count--;
842 } while ( count > 0 );
843
844 cmd_end ();
845 return;
846 }
847
848 int find_drives (void)
849 {
850 int *pdrv;
851 int drvnum;
852 int subdrv;
853 int i;
854
855 speed = 0;
856 pdrv = (int *)&drv_states;
857 curr_drv_state = 0xFE;
858 subdrv = 0;
859 drvnum = 0;
860
861 for ( i=0 ; i<8 ; i++ )
862 {
863 subdrv++;
864 cmd_status ();
865 disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
866 if ( disk_state != (ST_x08 | ST_x04 | ST_INVALID) )
867 {
868
869 *pdrv = curr_drv_state;
870 init_cd_drive (drvnum);
871 pdrv++;
872 drvnum++;
873 }
874 else
875 {
876 if ( subdrv < 2 )
877 {
878 continue;
879 }
880 else
881 {
882 subdrv = 0;
883 }
884 }
885
886
887
888 curr_drv_state *= 2;
889 curr_drv_state |= 1;
890 #ifdef GSCD_DEBUG
891 printk ("DriveState: %d\n", curr_drv_state );
892 #endif
893 }
894
895 ndrives = drvnum;
896 return drvnum;
897 }
898
899 void init_cd_drive ( int num )
900 {
901 char resp [50];
902 int i;
903
904 printk ("GSCD: init unit %d\n", num );
905 cc_Ident ((char *)&resp);
906
907 printk ("GSCD: identification: ");
908 for ( i=0 ; i<0x1E; i++ )
909 {
910 printk ( "%c", resp[i] );
911 }
912 printk ("\n");
913
914 cc_SetSpeed ();
915
916 }
917
918 #ifdef FUTURE_WORK
919
920 static void update_state ( void )
921 {
922 unsigned int AX;
923
924
925 if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 )
926 {
927 if ( disk_state == (ST_x08 | ST_x04 | ST_INVALID))
928 {
929 AX = ST_INVALID;
930 }
931
932 if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 )
933 {
934 invalidate ();
935 f_drv_ok = 0;
936 }
937
938 AX |= 0x8000;
939 }
940
941 if ( disk_state & ST_PLAYING )
942 {
943 AX |= 0x200;
944 }
945
946 AX |= 0x100;
947
948
949 disk_state = 0;
950
951 }
952 #endif
953
954 #ifdef MODULE
955
956 int init_module (void)
957 {
958 long err;
959
960
961
962 err = my_gscd_init ( );
963
964 if ( err < 0 )
965 {
966 return err;
967 }
968 else
969 {
970 printk (KERN_INFO "Happy GoldStar !\n" );
971 return 0;
972 }
973 }
974
975 void cleanup_module (void)
976 {
977
978 if ((unregister_blkdev(MAJOR_NR, "gscd" ) == -EINVAL))
979 {
980 printk("What's that: can't unregister GoldStar-module\n" );
981 return;
982 }
983
984 release_region (gscd_port,4);
985 printk(KERN_INFO "GoldStar-module released.\n" );
986 }
987 #endif
988
989
990
991 int gscd_init (void)
992 {
993 return my_gscd_init ();
994 }
995
996
997
998
999 int my_gscd_init (void)
1000 {
1001 int i;
1002 int result;
1003
1004 printk (KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
1005 printk (KERN_INFO "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", gscd_port);
1006
1007 if (check_region(gscd_port, 4))
1008 {
1009 printk("GSCD: Init failed, I/O port (%X) already in use.\n", gscd_port);
1010 return -EIO;
1011 }
1012
1013
1014
1015 result = wait_drv_ready ();
1016 if ( result == 0x09 )
1017 {
1018 printk ("GSCD: DMA kann ich noch nicht!\n" );
1019 return -EIO;
1020 }
1021
1022 if ( result == 0x0b )
1023 {
1024 drv_mode = result;
1025 i = find_drives ();
1026 if ( i == 0 )
1027 {
1028 printk ( "GSCD: GoldStar CD-ROM Drive is not found.\n" );
1029 return -EIO;
1030 }
1031 }
1032
1033 if ( (result != 0x0b) && (result != 0x09) )
1034 {
1035 printk ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n" );
1036 return -EIO;
1037 }
1038
1039
1040 i = 0;
1041 while ( drv_states[i] != 0 )
1042 {
1043 curr_drv_state = drv_states[i];
1044 printk (KERN_INFO "GSCD: Reset unit %d ... ",i );
1045 cc_Reset ();
1046 printk ( "done\n" );
1047 i++;
1048 }
1049
1050 if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0)
1051 {
1052 printk("GSCD: Unable to get major %d for GoldStar CD-ROM\n",
1053 MAJOR_NR);
1054 return -EIO;
1055 }
1056
1057 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1058 read_ahead[MAJOR_NR] = 4;
1059
1060 disk_state = 0;
1061 gscdPresent = 1;
1062
1063 request_region(gscd_port, 4, "gscd");
1064
1065 printk (KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n" );
1066 return 0;
1067 }
1068
1069 static void gscd_hsg2msf (long hsg, struct msf *msf)
1070 {
1071 hsg += CD_BLOCK_OFFSET;
1072 msf -> min = hsg / (CD_FRAMES*CD_SECS);
1073 hsg %= CD_FRAMES*CD_SECS;
1074 msf -> sec = hsg / CD_FRAMES;
1075 msf -> frame = hsg % CD_FRAMES;
1076
1077 gscd_bin2bcd(&msf -> min);
1078 gscd_bin2bcd(&msf -> sec);
1079 gscd_bin2bcd(&msf -> frame);
1080 }
1081
1082
1083 static void gscd_bin2bcd (unsigned char *p)
1084 {
1085 int u, t;
1086
1087 u = *p % 10;
1088 t = *p / 10;
1089 *p = u | (t << 4);
1090 }
1091
1092
1093 #ifdef FUTURE_WORK
1094 static long gscd_msf2hsg (struct msf *mp)
1095 {
1096 return gscd_bcd2bin(mp -> frame)
1097 + gscd_bcd2bin(mp -> sec) * CD_FRAMES
1098 + gscd_bcd2bin(mp -> min) * CD_FRAMES * CD_SECS
1099 - CD_BLOCK_OFFSET;
1100 }
1101
1102 static int gscd_bcd2bin (unsigned char bcd)
1103 {
1104 return (bcd >> 4) * 10 + (bcd & 0xF);
1105 }
1106 #endif
1107
1108