Import 2.1.118
[davej-history.git] / drivers / cdrom / gscd.c
blobea3f9093c5afc35a5c13431ae0ce24abaf3082ad
1 #define GSCD_VERSION "0.4a Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>"
3 /*
4 linux/drivers/block/gscd.c - GoldStar R420 CDROM driver
6 Copyright (C) 1995 Oliver Raupach <raupach@nwfs1.rz.fh-hannover.de>
7 based upon pre-works by Eberhard Moenkeberg <emoenke@gwdg.de>
10 For all kind of other information about the GoldStar CDROM
11 and this Linux device driver I installed a WWW-URL:
12 http://linux.rz.fh-hannover.de/~raupach
15 If you are the editor of a Linux CD, you should
16 enable gscd.c within your boot floppy kernel and
17 send me one of your CDs for free.
20 --------------------------------------------------------------------
21 This program is free software; you can redistribute it and/or modify
22 it under the terms of the GNU General Public License as published by
23 the Free Software Foundation; either version 2, or (at your option)
24 any later version.
26 This program is distributed in the hope that it will be useful,
27 but WITHOUT ANY WARRANTY; without even the implied warranty of
28 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 GNU General Public License for more details.
31 You should have received a copy of the GNU General Public License
32 along with this program; if not, write to the Free Software
33 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
37 /* These settings are for various debug-level. Leave they untouched ... */
38 #define NO_GSCD_DEBUG
39 #define NO_IOCTL_DEBUG
40 #define NO_MODULE_DEBUG
41 #define NO_FUTURE_WORK
42 /*------------------------*/
44 #include <linux/module.h>
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 #include <linux/init.h>
60 #include <asm/system.h>
61 #include <asm/io.h>
62 #include <asm/uaccess.h>
64 #define MAJOR_NR GOLDSTAR_CDROM_MAJOR
65 #include <linux/blk.h>
66 #define gscd_port gscd /* for compatible parameter passing with "insmod" */
67 #include "gscd.h"
70 static int gscdPresent = 0;
72 static unsigned char gscd_buf[2048]; /* buffer for block size conversion */
73 static int gscd_bn = -1;
74 static short gscd_port = GSCD_BASE_ADDR;
75 MODULE_PARM(gscd, "h");
77 /* Kommt spaeter vielleicht noch mal dran ...
78 * static struct wait_queue *gscd_waitq = NULL;
79 */
81 static void gscd_transfer (void);
82 static void gscd_read_cmd (void);
83 static void gscd_hsg2msf (long hsg, struct msf *msf);
84 static void gscd_bin2bcd (unsigned char *p);
86 /* Schnittstellen zum Kern/FS */
88 static void do_gscd_request (void);
89 static int gscd_ioctl (struct inode *, struct file *, unsigned int, unsigned long);
90 static int gscd_open (struct inode *, struct file *);
91 static int gscd_release (struct inode *, struct file *);
92 static int check_gscd_med_chg (kdev_t);
94 /* GoldStar Funktionen */
96 static void cc_Reset (void);
97 static int wait_drv_ready (void);
98 static int find_drives (void);
99 static void cmd_out (int, char *, char *, int);
100 static void cmd_status (void);
101 static void cc_Ident (char *);
102 static void cc_SetSpeed (void);
103 static void init_cd_drive (int);
105 static int get_status (void);
106 static void clear_Audio (void);
107 static void cc_invalidate (void);
109 /* some things for the next version */
110 #ifdef FUTURE_WORK
111 static void update_state (void);
112 static long gscd_msf2hsg (struct msf *mp);
113 static int gscd_bcd2bin (unsigned char bcd);
114 #endif
116 /* common GoldStar Initialization */
118 static int my_gscd_init (void);
121 /* lo-level cmd-Funktionen */
123 static void cmd_info_in ( char *, int );
124 static void cmd_end ( void );
125 static void cmd_read_b ( char *, int, int );
126 static void cmd_read_w ( char *, int, int );
127 static int cmd_unit_alive ( void );
128 static void cmd_write_cmd ( char * );
131 /* GoldStar Variablen */
133 static int curr_drv_state;
134 static int drv_states[] = {0,0,0,0,0,0,0,0};
135 static int drv_mode;
136 static int disk_state;
137 static int speed;
138 static int ndrives;
140 static unsigned char drv_num_read;
141 static unsigned char f_dsk_valid;
142 static unsigned char current_drive;
143 static unsigned char f_drv_ok;
146 static char f_AudioPlay;
147 static char f_AudioPause;
148 static int AudioStart_m;
149 static int AudioStart_f;
150 static int AudioEnd_m;
151 static int AudioEnd_f;
154 static struct file_operations gscd_fops = {
155 NULL, /* lseek - default */
156 block_read, /* read - general block-dev read */
157 block_write, /* write - general block-dev write */
158 NULL, /* readdir - bad */
159 NULL, /* poll */
160 gscd_ioctl, /* ioctl */
161 NULL, /* mmap */
162 gscd_open, /* open */
163 NULL, /* flush */
164 gscd_release, /* release */
165 NULL, /* fsync */
166 NULL, /* fasync*/
167 check_gscd_med_chg, /* media change */
168 NULL /* revalidate */
172 * Checking if the media has been changed
173 * (not yet implemented)
175 static int check_gscd_med_chg (kdev_t full_dev)
177 int target;
180 target = MINOR(full_dev);
182 if (target > 0)
184 printk("GSCD: GoldStar CD-ROM request error: invalid device.\n");
185 return 0;
188 #ifdef GSCD_DEBUG
189 printk ("gscd: check_med_change\n");
190 #endif
192 return 0;
196 __initfunc(void gscd_setup (char *str, int *ints))
198 if (ints[0] > 0)
200 gscd_port = ints[1];
205 static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
207 unsigned char to_do[10];
208 unsigned char dummy;
211 switch (cmd)
213 case CDROMSTART: /* Spin up the drive */
214 /* Don't think we can do this. Even if we could,
215 * I think the drive times out and stops after a while
216 * anyway. For now, ignore it.
218 return 0;
220 case CDROMRESUME: /* keine Ahnung was das ist */
221 return 0;
224 case CDROMEJECT:
225 cmd_status ();
226 to_do[0] = CMD_TRAY_CTL;
227 cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
229 return 0;
231 default:
232 return -EINVAL;
239 * Take care of the different block sizes between cdrom and Linux.
240 * When Linux gets variable block sizes this will probably go away.
243 static void gscd_transfer (void)
245 long offs;
247 while (CURRENT -> nr_sectors > 0 && gscd_bn == CURRENT -> sector / 4)
249 offs = (CURRENT -> sector & 3) * 512;
250 memcpy(CURRENT -> buffer, gscd_buf + offs, 512);
251 CURRENT -> nr_sectors--;
252 CURRENT -> sector++;
253 CURRENT -> buffer += 512;
259 * I/O request routine called from Linux kernel.
262 static void do_gscd_request (void)
264 unsigned int block,dev;
265 unsigned int nsect;
267 repeat:
268 if (!(CURRENT) || CURRENT->rq_status == RQ_INACTIVE) return;
269 INIT_REQUEST;
270 dev = MINOR(CURRENT->rq_dev);
271 block = CURRENT->sector;
272 nsect = CURRENT->nr_sectors;
274 if (CURRENT == NULL || CURRENT -> sector == -1)
275 return;
277 if (CURRENT -> cmd != READ)
279 printk("GSCD: bad cmd %d\n", CURRENT -> cmd);
280 end_request(0);
281 goto repeat;
284 if (MINOR(CURRENT -> rq_dev) != 0)
286 printk("GSCD: this version supports only one device\n");
287 end_request(0);
288 goto repeat;
291 gscd_transfer();
293 /* if we satisfied the request from the buffer, we're done. */
295 if (CURRENT -> nr_sectors == 0)
297 end_request(1);
298 goto repeat;
301 #ifdef GSCD_DEBUG
302 printk ("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect );
303 #endif
305 gscd_read_cmd ();
311 * Check the result of the set-mode command. On success, send the
312 * read-data command.
315 static void
316 gscd_read_cmd (void)
318 long block;
319 struct gscd_Play_msf gscdcmd;
320 char cmd[] = { CMD_READ, 0x80, 0,0,0, 0,1 }; /* cmd mode M-S-F secth sectl */
324 cmd_status ();
325 if ( disk_state & (ST_NO_DISK | ST_DOOR_OPEN) )
327 printk ( "GSCD: no disk or door open\n" );
328 end_request (0);
330 else
332 if ( disk_state & ST_INVALID )
334 printk ( "GSCD: disk invalid\n" );
335 end_request (0);
337 else
339 gscd_bn = -1; /* purge our buffer */
340 block = CURRENT -> sector / 4;
341 gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */
343 cmd[2] = gscdcmd.start.min;
344 cmd[3] = gscdcmd.start.sec;
345 cmd[4] = gscdcmd.start.frame;
347 #ifdef GSCD_DEBUG
348 printk ("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], cmd[4] );
349 #endif
350 cmd_out ( TYPE_DATA, (char *)&cmd, (char *)&gscd_buf[0], 1 );
352 gscd_bn = CURRENT -> sector / 4;
353 gscd_transfer();
354 end_request(1);
357 SET_TIMER(do_gscd_request, 1);
362 * Open the device special file. Check that a disk is in.
365 static int gscd_open (struct inode *ip, struct file *fp)
367 int st;
369 #ifdef GSCD_DEBUG
370 printk ( "GSCD: open\n" );
371 #endif
373 if (gscdPresent == 0)
374 return -ENXIO; /* no hardware */
376 MOD_INC_USE_COUNT;
378 get_status ();
379 st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN);
380 if ( st )
382 printk ( "GSCD: no disk or door open\n" );
383 MOD_DEC_USE_COUNT;
384 return -ENXIO;
387 /* if (updateToc() < 0)
388 return -EIO;
391 return 0;
396 * On close, we flush all gscd blocks from the buffer cache.
399 static int gscd_release (struct inode * inode, struct file * file)
402 #ifdef GSCD_DEBUG
403 printk ( "GSCD: release\n" );
404 #endif
406 gscd_bn = -1;
407 sync_dev(inode->i_rdev);
408 invalidate_buffers(inode -> i_rdev);
410 MOD_DEC_USE_COUNT;
411 return 0;
415 int get_status (void)
417 int status;
419 cmd_status ();
420 status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01);
422 if ( status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01) )
424 cc_invalidate ();
425 return 1;
427 else
429 return 0;
434 void cc_invalidate (void)
436 drv_num_read = 0xFF;
437 f_dsk_valid = 0xFF;
438 current_drive = 0xFF;
439 f_drv_ok = 0xFF;
441 clear_Audio ();
445 void clear_Audio (void)
448 f_AudioPlay = 0;
449 f_AudioPause = 0;
450 AudioStart_m = 0;
451 AudioStart_f = 0;
452 AudioEnd_m = 0;
453 AudioEnd_f = 0;
458 * waiting ?
461 int wait_drv_ready (void)
463 int found, read;
467 found = inb ( GSCDPORT(0) );
468 found &= 0x0f;
469 read = inb ( GSCDPORT(0) );
470 read &= 0x0f;
471 } while ( read != found );
473 #ifdef GSCD_DEBUG
474 printk ( "Wait for: %d\n", read );
475 #endif
477 return read;
480 void cc_Ident (char * respons)
482 char to_do [] = {CMD_IDENT, 0, 0};
484 cmd_out (TYPE_INFO, (char *)&to_do, (char *)respons, (int)0x1E );
488 void cc_SetSpeed (void)
490 char to_do [] = {CMD_SETSPEED, 0, 0};
491 char dummy;
493 if ( speed > 0 )
495 to_do[1] = speed & 0x0F;
496 cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
501 void cc_Reset (void)
503 char to_do [] = {CMD_RESET, 0};
504 char dummy;
506 cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
511 void cmd_status (void)
513 char to_do [] = {CMD_STATUS, 0};
514 char dummy;
516 cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0);
518 #ifdef GSCD_DEBUG
519 printk ("GSCD: Status: %d\n", disk_state );
520 #endif
524 void cmd_out ( int cmd_type, char * cmd, char * respo_buf, int respo_count )
526 int result;
529 result = wait_drv_ready ();
530 if ( result != drv_mode )
532 unsigned long test_loops = 0xFFFF;
533 int i,dummy;
535 outb ( curr_drv_state, GSCDPORT(0));
537 /* LOCLOOP_170 */
540 result = wait_drv_ready ();
541 test_loops--;
542 } while ( (result != drv_mode) && (test_loops > 0) );
544 if ( result != drv_mode )
546 disk_state = ST_x08 | ST_x04 | ST_INVALID;
547 return;
550 /* ...and waiting */
551 for ( i=1,dummy=1 ; i<0xFFFF ; i++ )
553 dummy *= i;
557 /* LOC_172 */
558 /* check the unit */
559 /* and wake it up */
560 if ( cmd_unit_alive () != 0x08 )
562 /* LOC_174 */
563 /* game over for this unit */
564 disk_state = ST_x08 | ST_x04 | ST_INVALID;
565 return;
568 /* LOC_176 */
569 #ifdef GSCD_DEBUG
570 printk ("LOC_176 ");
571 #endif
572 if ( drv_mode == 0x09 )
574 /* magic... */
575 printk ("GSCD: magic ...\n");
576 outb ( result, GSCDPORT(2));
579 /* write the command to the drive */
580 cmd_write_cmd (cmd);
582 /* LOC_178 */
583 for (;;)
585 result = wait_drv_ready ();
586 if ( result != drv_mode )
588 /* LOC_179 */
589 if ( result == 0x04 ) /* Mode 4 */
591 /* LOC_205 */
592 #ifdef GSCD_DEBUG
593 printk ("LOC_205 ");
594 #endif
595 disk_state = inb ( GSCDPORT (2));
599 result = wait_drv_ready ();
600 } while ( result != drv_mode );
601 return;
604 else
606 if ( result == 0x06 ) /* Mode 6 */
608 /* LOC_181 */
609 #ifdef GSCD_DEBUG
610 printk ("LOC_181 ");
611 #endif
613 if (cmd_type == TYPE_DATA)
615 /* read data */
616 /* LOC_184 */
617 if ( drv_mode == 9 )
619 /* read the data to the buffer (word) */
621 /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */
622 cmd_read_w ( respo_buf, respo_count, CD_FRAMESIZE/2 );
623 return;
625 else
627 /* read the data to the buffer (byte) */
629 /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */
630 cmd_read_b ( respo_buf, respo_count, CD_FRAMESIZE );
631 return;
634 else
636 /* read the info to the buffer */
637 cmd_info_in ( respo_buf, respo_count );
638 return;
641 return;
646 else
648 disk_state = ST_x08 | ST_x04 | ST_INVALID;
649 return;
651 } /* for (;;) */
654 #ifdef GSCD_DEBUG
655 printk ("\n");
656 #endif
660 static void cmd_write_cmd ( char *pstr )
662 int i,j;
664 /* LOC_177 */
665 #ifdef GSCD_DEBUG
666 printk ("LOC_177 ");
667 #endif
669 /* calculate the number of parameter */
670 j = *pstr & 0x0F;
672 /* shift it out */
673 for ( i=0 ; i<j ; i++ )
675 outb ( *pstr, GSCDPORT(2) );
676 pstr++;
681 static int cmd_unit_alive ( void )
683 int result;
684 unsigned long max_test_loops;
687 /* LOC_172 */
688 #ifdef GSCD_DEBUG
689 printk ("LOC_172 ");
690 #endif
692 outb ( curr_drv_state, GSCDPORT(0));
693 max_test_loops = 0xFFFF;
697 result = wait_drv_ready ();
698 max_test_loops--;
699 } while ( (result != 0x08) && (max_test_loops > 0) );
701 return result;
705 static void cmd_info_in ( char *pb, int count )
707 int result;
708 char read;
711 /* read info */
712 /* LOC_182 */
713 #ifdef GSCD_DEBUG
714 printk ("LOC_182 ");
715 #endif
719 read = inb (GSCDPORT(2));
720 if ( count > 0 )
722 *pb = read;
723 pb++;
724 count--;
727 /* LOC_183 */
730 result = wait_drv_ready ();
731 } while ( result == 0x0E );
732 } while ( result == 6 );
734 cmd_end ();
735 return;
739 static void cmd_read_b ( char *pb, int count, int size )
741 int result;
742 int i;
745 /* LOC_188 */
746 /* LOC_189 */
747 #ifdef GSCD_DEBUG
748 printk ("LOC_189 ");
749 #endif
755 result = wait_drv_ready ();
756 } while ( result != 6 || result == 0x0E );
758 if ( result != 6 )
760 cmd_end ();
761 return;
764 #ifdef GSCD_DEBUG
765 printk ("LOC_191 ");
766 #endif
768 for ( i=0 ; i< size ; i++ )
770 *pb = inb (GSCDPORT(2));
771 pb++;
773 count--;
774 } while ( count > 0 );
776 cmd_end ();
777 return;
781 static void cmd_end (void)
783 int result;
786 /* LOC_204 */
787 #ifdef GSCD_DEBUG
788 printk ("LOC_204 ");
789 #endif
793 result = wait_drv_ready ();
794 if ( result == drv_mode )
796 return;
798 } while ( result != 4 );
800 /* LOC_205 */
801 #ifdef GSCD_DEBUG
802 printk ("LOC_205 ");
803 #endif
805 disk_state = inb ( GSCDPORT (2));
809 result = wait_drv_ready ();
810 } while ( result != drv_mode );
811 return;
816 static void cmd_read_w ( char *pb, int count, int size )
818 int result;
819 int i;
822 #ifdef GSCD_DEBUG
823 printk ("LOC_185 ");
824 #endif
828 /* LOC_185 */
831 result = wait_drv_ready ();
832 } while ( result != 6 || result == 0x0E );
834 if ( result != 6 )
836 cmd_end ();
837 return;
840 for ( i=0 ; i<size ; i++ )
842 /* na, hier muss ich noch mal drueber nachdenken */
843 *pb = inw(GSCDPORT(2));
844 pb++;
846 count--;
847 } while ( count > 0 );
849 cmd_end ();
850 return;
853 __initfunc(int find_drives (void))
855 int *pdrv;
856 int drvnum;
857 int subdrv;
858 int i;
860 speed = 0;
861 pdrv = (int *)&drv_states;
862 curr_drv_state = 0xFE;
863 subdrv = 0;
864 drvnum = 0;
866 for ( i=0 ; i<8 ; i++ )
868 subdrv++;
869 cmd_status ();
870 disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01;
871 if ( disk_state != (ST_x08 | ST_x04 | ST_INVALID) )
873 /* LOC_240 */
874 *pdrv = curr_drv_state;
875 init_cd_drive (drvnum);
876 pdrv++;
877 drvnum++;
879 else
881 if ( subdrv < 2 )
883 continue;
885 else
887 subdrv = 0;
891 /* curr_drv_state<<1; <-- das geht irgendwie nicht */
892 /* muss heissen: curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */
893 curr_drv_state *= 2;
894 curr_drv_state |= 1;
895 #ifdef GSCD_DEBUG
896 printk ("DriveState: %d\n", curr_drv_state );
897 #endif
900 ndrives = drvnum;
901 return drvnum;
904 __initfunc(void init_cd_drive ( int num ))
906 char resp [50];
907 int i;
909 printk ("GSCD: init unit %d\n", num );
910 cc_Ident ((char *)&resp);
912 printk ("GSCD: identification: ");
913 for ( i=0 ; i<0x1E; i++ )
915 printk ( "%c", resp[i] );
917 printk ("\n");
919 cc_SetSpeed ();
923 #ifdef FUTURE_WORK
924 /* return_done */
925 static void update_state ( void )
927 unsigned int AX;
930 if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 )
932 if ( disk_state == (ST_x08 | ST_x04 | ST_INVALID))
934 AX = ST_INVALID;
937 if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 )
939 invalidate ();
940 f_drv_ok = 0;
943 AX |= 0x8000;
946 if ( disk_state & ST_PLAYING )
948 AX |= 0x200;
951 AX |= 0x100;
952 /* pkt_esbx = AX; */
954 disk_state = 0;
957 #endif
959 #ifdef MODULE
960 /* Init for the Module-Version */
961 int init_module (void)
963 long err;
966 /* call the GoldStar-init */
967 err = my_gscd_init ( );
969 if ( err < 0 )
971 return err;
973 else
975 printk (KERN_INFO "Happy GoldStar !\n" );
976 return 0;
980 void cleanup_module (void)
983 if ((unregister_blkdev(MAJOR_NR, "gscd" ) == -EINVAL))
985 printk("What's that: can't unregister GoldStar-module\n" );
986 return;
989 release_region (gscd_port,4);
990 printk(KERN_INFO "GoldStar-module released.\n" );
992 #endif
995 /* Test for presence of drive and initialize it. Called only at boot time. */
996 __initfunc(int gscd_init (void))
998 return my_gscd_init ();
1002 /* This is the common initialisation for the GoldStar drive. */
1003 /* It is called at boot time AND for module init. */
1004 __initfunc(int my_gscd_init (void))
1006 int i;
1007 int result;
1009 printk (KERN_INFO "GSCD: version %s\n", GSCD_VERSION);
1010 printk (KERN_INFO "GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", gscd_port);
1012 if (check_region(gscd_port, 4))
1014 printk("GSCD: Init failed, I/O port (%X) already in use.\n", gscd_port);
1015 return -EIO;
1019 /* check for card */
1020 result = wait_drv_ready ();
1021 if ( result == 0x09 )
1023 printk ("GSCD: DMA kann ich noch nicht!\n" );
1024 return -EIO;
1027 if ( result == 0x0b )
1029 drv_mode = result;
1030 i = find_drives ();
1031 if ( i == 0 )
1033 printk ( "GSCD: GoldStar CD-ROM Drive is not found.\n" );
1034 return -EIO;
1038 if ( (result != 0x0b) && (result != 0x09) )
1040 printk ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n" );
1041 return -EIO;
1044 /* reset all drives */
1045 i = 0;
1046 while ( drv_states[i] != 0 )
1048 curr_drv_state = drv_states[i];
1049 printk (KERN_INFO "GSCD: Reset unit %d ... ",i );
1050 cc_Reset ();
1051 printk ( "done\n" );
1052 i++;
1055 if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0)
1057 printk("GSCD: Unable to get major %d for GoldStar CD-ROM\n",
1058 MAJOR_NR);
1059 return -EIO;
1062 blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST;
1063 read_ahead[MAJOR_NR] = 4;
1065 disk_state = 0;
1066 gscdPresent = 1;
1068 request_region(gscd_port, 4, "gscd");
1070 printk (KERN_INFO "GSCD: GoldStar CD-ROM Drive found.\n" );
1071 return 0;
1074 static void gscd_hsg2msf (long hsg, struct msf *msf)
1076 hsg += CD_MSF_OFFSET;
1077 msf -> min = hsg / (CD_FRAMES*CD_SECS);
1078 hsg %= CD_FRAMES*CD_SECS;
1079 msf -> sec = hsg / CD_FRAMES;
1080 msf -> frame = hsg % CD_FRAMES;
1082 gscd_bin2bcd(&msf -> min); /* convert to BCD */
1083 gscd_bin2bcd(&msf -> sec);
1084 gscd_bin2bcd(&msf -> frame);
1088 static void gscd_bin2bcd (unsigned char *p)
1090 int u, t;
1092 u = *p % 10;
1093 t = *p / 10;
1094 *p = u | (t << 4);
1098 #ifdef FUTURE_WORK
1099 static long gscd_msf2hsg (struct msf *mp)
1101 return gscd_bcd2bin(mp -> frame)
1102 + gscd_bcd2bin(mp -> sec) * CD_FRAMES
1103 + gscd_bcd2bin(mp -> min) * CD_FRAMES * CD_SECS
1104 - CD_MSF_OFFSET;
1107 static int gscd_bcd2bin (unsigned char bcd)
1109 return (bcd >> 4) * 10 + (bcd & 0xF);
1111 #endif