--- linux/drivers/block/blk.h.old Thu Apr 6 23:05:23 1995 +++ linux/drivers/block/blk.h Mon Apr 17 21:43:09 1995 @@ -54,6 +54,9 @@ #ifdef CONFIG_SBPCD extern unsigned long sbpcd_init(unsigned long, unsigned long); #endif CONFIG_SBPCD +#ifdef CONFIG_GSCD +extern unsigned long gscd_init(unsigned long, unsigned long); +#endif CONFIG_GSCD extern void set_device_ro(int dev,int flag); extern void floppy_init(void); @@ -216,6 +219,13 @@ #define DEVICE_NAME "Matsushita CD-ROM controller #4" #define DEVICE_REQUEST do_sbpcd4_request +#define DEVICE_NR(device) (MINOR(device)) +#define DEVICE_ON(device) +#define DEVICE_OFF(device) + +#elif (MAJOR_NR == GOLDSTAR_CDROM_MAJOR) +#define DEVICE_NAME "Goldstar R420" +#define DEVICE_REQUEST do_gscd_request #define DEVICE_NR(device) (MINOR(device)) #define DEVICE_ON(device) #define DEVICE_OFF(device) --- linux/arch/i386/config.in.old Wed Apr 19 20:38:29 1995 +++ linux/arch/i386/config.in Mon Apr 17 21:45:19 1995 @@ -195,6 +195,7 @@ fi bool 'Aztech/Orchid/Okano/Wearnes (non IDE) CDROM support' CONFIG_AZTCD n bool 'Sony CDU535 CDROM driver support' CONFIG_CDU535 n +bool 'Goldstar R420 CDROM driver support' CONFIG_GSCD n comment 'Filesystems' --- linux/drivers/block/gscd.c.old Wed Apr 19 21:04:36 1995 +++ linux/drivers/block/gscd.c Fri Apr 28 12:43:48 1995 @@ -0,0 +1,1128 @@ +#define GSCD_VERSION "0.4a Oliver Raupach " + +/* + linux/drivers/block/gscd.c - GoldStar R420 CDROM driver + + Copyright (C) 1995 Oliver Raupach + with pre-works by Eberhard Moenkeberg + + + For all kind of other information about the GoldStar CDROM + and this Linux device driver I installed a WWW-URL: + http://linux.rz.fh-hannover.de/~raupach + + + If you are the editor of a Linux CD, you should + enable gscd.c within your boot floppy kernel and + send me one of your CDs for free. + + + -------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +/* These settings are for various debug-level. Leave they untouched ... */ +#define NO_GSCD_DEBUG +#define NO_IOCTL_DEBUG +#define NO_MODULE_DEBUG +#define NO_FUTURE_WORK +/*------------------------*/ + +#include + +#ifdef MODULE +#include +#include +#include +#ifndef CONFIG_MODVERSIONS +char kernel_version[] = UTS_RELEASE; +#endif +#endif MODULE + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAJOR_NR GOLDSTAR_CDROM_MAJOR +#include "blk.h" + + +static int gscdPresent = 0; + +static unsigned char gscd_buf[2048]; /* buffer for block size conversion */ +static int gscd_bn = -1; +static short gscd_port = GSCD_BASE_ADDR; + +/* Kommt spaeter vielleicht noch mal dran ... + * static struct wait_queue *gscd_waitq = NULL; + */ + +static void gscd_transfer (void); +static void gscd_read_cmd (void); +static void gscd_hsg2msf (long hsg, struct msf *msf); +static void gscd_bin2bcd (unsigned char *p); + +/* Schnittstellen zum Kern/FS */ + +static void do_gscd_request (void); +static int gscd_ioctl (struct inode *, struct file *, unsigned int, unsigned long); +static int gscd_open (struct inode *, struct file *); +static void gscd_release (struct inode *, struct file *); +static int check_gscd_med_chg (dev_t); + +/* GoldStar Funktionen */ + +static void cc_Reset (void); +static int wait_drv_ready (void); +static int find_drives (void); +static void cmd_out (int, char *, char *, int); +static void cmd_status (void); +static void cc_Ident (char *); +static void cc_SetSpeed (void); +static void init_cd_drive (int); + +static int get_status (void); +static void clear_Audio (void); +static void cc_invalidate (void); + +/* some things for the next version */ +#ifdef FUTURE_WORK +static void update_state (void); +static long gscd_msf2hsg (struct msf *mp); +static int gscd_bcd2bin (unsigned char bcd); +#endif + +/* common GoldStar Initialization */ + +static long my_gscd_init (unsigned long , unsigned long); + + +/* lo-level cmd-Funktionen */ + +static void cmd_info_in ( char *, int ); +static void cmd_end ( void ); +static void cmd_read_b ( char *, int, int ); +static void cmd_read_w ( char *, int, int ); +static int cmd_unit_alive ( void ); +static void cmd_write_cmd ( char * ); + + +/* GoldStar Variablen */ + +static int curr_drv_state; +static int drv_states[] = {0,0,0,0,0,0,0,0}; +static int drv_mode; +static int disk_state; +static int speed; +static int ndrives; + +static unsigned char drv_num_read; +static unsigned char f_dsk_valid; +static unsigned char current_drive; +static unsigned char f_drv_ok; + + +static char f_AudioPlay; +static char f_AudioPause; +static int AudioStart_m; +static int AudioStart_f; +static int AudioEnd_m; +static int AudioEnd_f; + + +static struct file_operations gscd_fops = { + NULL, /* lseek - default */ + block_read, /* read - general block-dev read */ + block_write, /* write - general block-dev write */ + NULL, /* readdir - bad */ + NULL, /* select */ + gscd_ioctl, /* ioctl */ + NULL, /* mmap */ + gscd_open, /* open */ + gscd_release, /* release */ + NULL, /* fsync */ + NULL, /* fasync*/ + check_gscd_med_chg, /* media change */ + NULL /* revalidate */ +}; + +/* + * Checking if the media has been changed + * (not yet implemented) + */ +static int check_gscd_med_chg (dev_t full_dev) +{ + int target; + + + target = MINOR(full_dev); + + if (target > 0) + { + printk("GSCD: GoldStar CD-ROM request error: invalid device.\n"); + return 0; + } + + #ifdef GSCD_DEBUG + printk ("gscd: check_med_change\n"); + #endif + + return 0; +} + + +void gscd_setup (char *str, int *ints) +{ + if (ints[0] > 0) + { + gscd_port = ints[1]; + } +} + + +static int gscd_ioctl (struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg) +{ +unsigned char to_do[10]; +unsigned char dummy; + + + switch (cmd) + { + case CDROMSTART: /* Spin up the drive */ + /* Don't think we can do this. Even if we could, + * I think the drive times out and stops after a while + * anyway. For now, ignore it. + */ + return 0; + + case CDROMRESUME: /* keine Ahnung was das ist */ + return 0; + + + case CDROMEJECT: + cmd_status (); + to_do[0] = CMD_TRAY_CTL; + cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0); + + return 0; + + default: + return -EINVAL; + } + +} + + +/* + * Take care of the different block sizes between cdrom and Linux. + * When Linux gets variable block sizes this will probably go away. + */ + +static void gscd_transfer (void) +{ +long offs; + + while (CURRENT -> nr_sectors > 0 && gscd_bn == CURRENT -> sector / 4) + { + offs = (CURRENT -> sector & 3) * 512; + memcpy(CURRENT -> buffer, gscd_buf + offs, 512); + CURRENT -> nr_sectors--; + CURRENT -> sector++; + CURRENT -> buffer += 512; + } +} + + +/* + * I/O request routine called from Linux kernel. + */ + +static void do_gscd_request (void) +{ +unsigned int block,dev; +unsigned int nsect; + +repeat: + if (!(CURRENT) || CURRENT->dev < 0) return; + INIT_REQUEST; + dev = MINOR(CURRENT->dev); + block = CURRENT->sector; + nsect = CURRENT->nr_sectors; + + if (CURRENT == NULL || CURRENT -> sector == -1) + return; + + if (CURRENT -> cmd != READ) + { + printk("GSCD: bad cmd %d\n", CURRENT -> cmd); + end_request(0); + goto repeat; + } + + if (MINOR(CURRENT -> dev) != 0) + { + printk("GSCD: this version supports only one device\n"); + end_request(0); + goto repeat; + } + + gscd_transfer(); + + /* if we satisfied the request from the buffer, we're done. */ + + if (CURRENT -> nr_sectors == 0) + { + end_request(1); + goto repeat; + } + +#ifdef GSCD_DEBUG + printk ("GSCD: dev %d, block %d, nsect %d\n", dev, block, nsect ); +#endif + + gscd_read_cmd (); +} + + + +/* + * Check the result of the set-mode command. On success, send the + * read-data command. + */ + +static void +gscd_read_cmd (void) +{ +long block; +struct gscd_Play_msf gscdcmd; +char cmd[] = { CMD_READ, 0x80, 0,0,0, 0,1 }; /* cmd mode M-S-F secth sectl */ + + + + cmd_status (); + if ( disk_state & (ST_NO_DISK | ST_DOOR_OPEN) ) + { + printk ( "GSCD: no disk or door open\n" ); + end_request (0); + } + else + { + if ( disk_state & ST_INVALID ) + { + printk ( "GSCD: disk invalid\n" ); + end_request (0); + } + else + { + gscd_bn = -1; /* purge our buffer */ + block = CURRENT -> sector / 4; + gscd_hsg2msf(block, &gscdcmd.start); /* cvt to msf format */ + + cmd[2] = gscdcmd.start.min; + cmd[3] = gscdcmd.start.sec; + cmd[4] = gscdcmd.start.frame; + +#ifdef GSCD_DEBUG + printk ("GSCD: read msf %d:%d:%d\n", cmd[2], cmd[3], cmd[4] ); +#endif + cmd_out ( TYPE_DATA, (char *)&cmd, (char *)&gscd_buf[0], 1 ); + + gscd_bn = CURRENT -> sector / 4; + gscd_transfer(); + end_request(1); + } + } + SET_TIMER(do_gscd_request, 1); +} + + +/* + * Open the device special file. Check that a disk is in. + */ + +static int gscd_open (struct inode *ip, struct file *fp) +{ +int st; + +#ifdef GSCD_DEBUG +printk ( "GSCD: open\n" ); +#endif + + if (gscdPresent == 0) + return -ENXIO; /* no hardware */ + + get_status (); + st = disk_state & (ST_NO_DISK | ST_DOOR_OPEN); + if ( st ) + { + printk ( "GSCD: no disk or door open\n" ); + return -ENXIO; + } + +/* if (updateToc() < 0) + return -EIO; +*/ + + #ifdef MODULE + MOD_INC_USE_COUNT; + #endif + + return 0; +} + + +/* + * On close, we flush all gscd blocks from the buffer cache. + */ + +static void gscd_release (struct inode * inode, struct file * file) +{ + +#ifdef GSCD_DEBUG +printk ( "GSCD: release\n" ); +#endif + + gscd_bn = -1; + sync_dev(inode->i_rdev); + invalidate_buffers(inode -> i_rdev); + + #ifdef MODULE + MOD_DEC_USE_COUNT; + #endif +} + + +int get_status (void) +{ +int status; + + cmd_status (); + status = disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01); + + if ( status == (ST_x08 | ST_x04 | ST_INVALID | ST_x01) ) + { + cc_invalidate (); + return 1; + } + else + { + return 0; + } +} + + +void cc_invalidate (void) +{ + drv_num_read = 0xFF; + f_dsk_valid = 0xFF; + current_drive = 0xFF; + f_drv_ok = 0xFF; + + clear_Audio (); + +} + +void clear_Audio (void) +{ + + f_AudioPlay = 0; + f_AudioPause = 0; + AudioStart_m = 0; + AudioStart_f = 0; + AudioEnd_m = 0; + AudioEnd_f = 0; + +} + +/* + * waiting ? + */ + +int wait_drv_ready (void) +{ +int found, read; + + do + { + found = inb ( GSCDPORT(0) ); + found &= 0x0f; + read = inb ( GSCDPORT(0) ); + read &= 0x0f; + } while ( read != found ); + +#ifdef GSCD_DEBUG +printk ( "Wait for: %d\n", read ); +#endif + + return read; +} + +void cc_Ident (char * respons) +{ +char to_do [] = {CMD_IDENT, 0, 0}; + + cmd_out (TYPE_INFO, (char *)&to_do, (char *)respons, (int)0x1E ); + +} + +void cc_SetSpeed (void) +{ +char to_do [] = {CMD_SETSPEED, 0, 0}; +char dummy; + + if ( speed > 0 ) + { + to_do[1] = speed & 0x0F; + cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0); + } +} + + +void cc_Reset (void) +{ +char to_do [] = {CMD_RESET, 0}; +char dummy; + + cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0); +} + + + +void cmd_status (void) +{ +char to_do [] = {CMD_STATUS, 0}; +char dummy; + + cmd_out (TYPE_INFO, (char *)&to_do, (char *)&dummy, 0); + +#ifdef GSCD_DEBUG +printk ("GSCD: Status: %d\n", disk_state ); +#endif + +} + +void cmd_out ( int cmd_type, char * cmd, char * respo_buf, int respo_count ) +{ +int result; + + + result = wait_drv_ready (); + if ( result != drv_mode ) + { + unsigned long test_loops = 0xFFFF; + int i,dummy; + + outb ( curr_drv_state, GSCDPORT(0)); + + /* LOCLOOP_170 */ + do + { + result = wait_drv_ready (); + test_loops--; + } while ( (result != drv_mode) && (test_loops > 0) ); + + if ( result != drv_mode ) + { + disk_state = ST_x08 | ST_x04 | ST_INVALID; + return; + } + + /* ...and waiting */ + for ( i=1,dummy=1 ; i<0xFFFF ; i++ ) + { + dummy *= i; + } + } + + /* LOC_172 */ + /* check the unit */ + /* and wake it up */ + if ( cmd_unit_alive () != 0x08 ) + { + /* LOC_174 */ + /* game over for this unit */ + disk_state = ST_x08 | ST_x04 | ST_INVALID; + return; + } + + /* LOC_176 */ + #ifdef GSCD_DEBUG + printk ("LOC_176 "); + #endif + if ( drv_mode == 0x09 ) + { + /* magic... */ + printk ("GSCD: magic ...\n"); + outb ( result, GSCDPORT(2)); + } + + /* write the command to the drive */ + cmd_write_cmd (cmd); + + /* LOC_178 */ + for (;;) + { + result = wait_drv_ready (); + if ( result != drv_mode ) + { + /* LOC_179 */ + if ( result == 0x04 ) /* Mode 4 */ + { + /* LOC_205 */ + #ifdef GSCD_DEBUG + printk ("LOC_205 "); + #endif + disk_state = inb ( GSCDPORT (2)); + + do + { + result = wait_drv_ready (); + } while ( result != drv_mode ); + return; + + } + else + { + if ( result == 0x06 ) /* Mode 6 */ + { + /* LOC_181 */ + #ifdef GSCD_DEBUG + printk ("LOC_181 "); + #endif + + if (cmd_type == TYPE_DATA) + { + /* read data */ + /* LOC_184 */ + if ( drv_mode == 9 ) + { + /* read the data to the buffer (word) */ + + /* (*(cmd+1))?(CD_FRAMESIZE/2):(CD_FRAMESIZE_RAW/2) */ + cmd_read_w ( respo_buf, respo_count, CD_FRAMESIZE/2 ); + return; + } + else + { + /* read the data to the buffer (byte) */ + + /* (*(cmd+1))?(CD_FRAMESIZE):(CD_FRAMESIZE_RAW) */ + cmd_read_b ( respo_buf, respo_count, CD_FRAMESIZE ); + return; + } + } + else + { + /* read the info to the buffer */ + cmd_info_in ( respo_buf, respo_count ); + return; + } + + return; + } + } + + } + else + { + disk_state = ST_x08 | ST_x04 | ST_INVALID; + return; + } + } /* for (;;) */ + + +#ifdef GSCD_DEBUG +printk ("\n"); +#endif +} + + +static void cmd_write_cmd ( char *pstr ) +{ +int i,j; + + /* LOC_177 */ + #ifdef GSCD_DEBUG + printk ("LOC_177 "); + #endif + + /* calculate the number of parameter */ + j = *pstr & 0x0F; + + /* shift it out */ + for ( i=0 ; i 0) ); + + return result; +} + + +static void cmd_info_in ( char *pb, int count ) +{ +int result; +char read; + + + /* read info */ + /* LOC_182 */ + #ifdef GSCD_DEBUG + printk ("LOC_182 "); + #endif + + do + { + read = inb (GSCDPORT(2)); + if ( count > 0 ) + { + *pb = read; + pb++; + count--; + } + + /* LOC_183 */ + do + { + result = wait_drv_ready (); + } while ( result == 0x0E ); + } while ( result == 6 ); + + cmd_end (); + return; +} + + +static void cmd_read_b ( char *pb, int count, int size ) +{ +int result; +int i; + + + /* LOC_188 */ + /* LOC_189 */ + #ifdef GSCD_DEBUG + printk ("LOC_189 "); + #endif + + do + { + do + { + result = wait_drv_ready (); + } while ( result != 6 || result == 0x0E ); + + if ( result != 6 ) + { + cmd_end (); + return; + } + + #ifdef GSCD_DEBUG + printk ("LOC_191 "); + #endif + + for ( i=0 ; i< size ; i++ ) + { + *pb = inb (GSCDPORT(2)); + pb++; + } + count--; + } while ( count > 0 ); + + cmd_end (); + return; +} + + +static void cmd_end (void) +{ +int result; + + + /* LOC_204 */ + #ifdef GSCD_DEBUG + printk ("LOC_204 "); + #endif + + do + { + result = wait_drv_ready (); + if ( result == drv_mode ) + { + return; + } + } while ( result != 4 ); + + /* LOC_205 */ + #ifdef GSCD_DEBUG + printk ("LOC_205 "); + #endif + + disk_state = inb ( GSCDPORT (2)); + + do + { + result = wait_drv_ready (); + } while ( result != drv_mode ); + return; + +} + + +static void cmd_read_w ( char *pb, int count, int size ) +{ +int result; +int i; + + + #ifdef GSCD_DEBUG + printk ("LOC_185 "); + #endif + + do + { + /* LOC_185 */ + do + { + result = wait_drv_ready (); + } while ( result != 6 || result == 0x0E ); + + if ( result != 6 ) + { + cmd_end (); + return; + } + + for ( i=0 ; i 0 ); + + cmd_end (); + return; +} + +int find_drives (void) +{ +int *pdrv; +int drvnum; +int subdrv; +int i; + + speed = 0; + pdrv = (int *)&drv_states; + curr_drv_state = 0xFE; + subdrv = 0; + drvnum = 0; + + for ( i=0 ; i<8 ; i++ ) + { + subdrv++; + cmd_status (); + disk_state &= ST_x08 | ST_x04 | ST_INVALID | ST_x01; + if ( disk_state != (ST_x08 | ST_x04 | ST_INVALID) ) + { + /* LOC_240 */ + *pdrv = curr_drv_state; + init_cd_drive (drvnum); + pdrv++; + drvnum++; + } + else + { + if ( subdrv < 2 ) + { + continue; + } + else + { + subdrv = 0; + } + } + +/* curr_drv_state<<1; <-- das geht irgendwie nicht */ +/* muss heissen: curr_drv_state <<= 1; (ist ja Wert-Zuweisung) */ + curr_drv_state *= 2; + curr_drv_state |= 1; +#ifdef GSCD_DEBUG + printk ("DriveState: %d\n", curr_drv_state ); +#endif + } + + ndrives = drvnum; + return drvnum; +} + +void init_cd_drive ( int num ) +{ +char resp [50]; +int i; + + printk ("GSCD: init unit %d\n", num ); + cc_Ident ((char *)&resp); + + printk ("GSCD: identification: "); + for ( i=0 ; i<0x1E; i++ ) + { + printk ( "%c", resp[i] ); + } + printk ("\n"); + + cc_SetSpeed (); + +} + +#ifdef FUTURE_WORK +/* return_done */ +static void update_state ( void ) +{ +unsigned int AX; + + + if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 ) + { + if ( disk_state == (ST_x08 | ST_x04 | ST_INVALID)) + { + AX = ST_INVALID; + } + + if ( (disk_state & (ST_x08 | ST_x04 | ST_INVALID | ST_x01)) == 0 ) + { + invalidate (); + f_drv_ok = 0; + } + + AX |= 0x8000; + } + + if ( disk_state & ST_PLAYING ) + { + AX |= 0x200; + } + + AX |= 0x100; + /* pkt_esbx = AX; */ + + disk_state = 0; + +} +#endif + +/* Init for the Module-Version */ +int init_module (void) +{ +long err; + + + /* call the GoldStar-init with dummys */ + err = my_gscd_init ( 10, 20 ); + + if ( err < 0 ) + { + return -EIO; + } + else + { + printk ( "Happy GoldStar !\n" ); + return 0; + } +} + +#ifdef MODULE +void cleanup_module (void) +{ + + if (MOD_IN_USE) + { + printk("GoldStar-module in use - can't remove it.\n" ); + return; + } + + if ((unregister_blkdev(MAJOR_NR, "gscd" ) == -EINVAL)) + { + printk("What's that: can't unregister GoldStar-module\n" ); + return; + } + + release_region (gscd_port,4); + printk( "GoldStar-module released.\n" ); +} +#endif + + +/* Test for presence of drive and initialize it. Called only at boot time. */ +unsigned long gscd_init (unsigned long mem_start, unsigned long mem_end) +{ +unsigned long err; + + err = my_gscd_init ( mem_start, mem_end ); + return ( labs(err)); +} + + +/* This is the common initalisation for the GoldStar drive. */ +/* It is called at boot time AND for module init. */ +long my_gscd_init (unsigned long mem_start, unsigned long mem_end) +{ +int i; +int result; + + printk ("GSCD: version %s\n", GSCD_VERSION); + printk ("GSCD: Trying to detect a Goldstar R420 CD-ROM drive at 0x%X.\n", gscd_port); + + if (check_region(gscd_port, 4)) + { + printk("GSCD: Init failed, I/O port (%X) already in use.\n", gscd_port); + return -mem_start; + } + + + /* check for card */ + result = wait_drv_ready (); + if ( result == 0x09 ) + { + printk ("GSCD: DMA kann ich noch nicht!\n" ); + return -mem_start; + } + + if ( result == 0x0b ) + { + drv_mode = result; + i = find_drives (); + if ( i == 0 ) + { + printk ( "GSCD: GoldStar CD-ROM Drive is not found.\n" ); + return -mem_start; + } + } + + if ( (result != 0x0b) && (result != 0x09) ) + { + printk ("GSCD: GoldStar Interface Adapter does not exist or H/W error\n" ); + return -mem_start; + } + + /* reset all drives */ + i = 0; + while ( drv_states[i] != 0 ) + { + curr_drv_state = drv_states[i]; + printk ( "GSCD: Reset unit %d ... ",i ); + cc_Reset (); + printk ( "done\n" ); + i++; + } + + if (register_blkdev(MAJOR_NR, "gscd", &gscd_fops) != 0) + { + printk("GSCD: Unable to get major %d for GoldStar CD-ROM\n", + MAJOR_NR); + return -mem_start; + } + + blk_dev[MAJOR_NR].request_fn = DEVICE_REQUEST; + read_ahead[MAJOR_NR] = 4; + + disk_state = 0; + gscdPresent = 1; + + request_region(gscd_port, 4, "gscd"); + + printk ( "GSCD: GoldStar CD-ROM Drive found.\n" ); + return mem_start; +} + +static void gscd_hsg2msf (long hsg, struct msf *msf) +{ + hsg += CD_BLOCK_OFFSET; + msf -> min = hsg / (CD_FRAMES*CD_SECS); + hsg %= CD_FRAMES*CD_SECS; + msf -> sec = hsg / CD_FRAMES; + msf -> frame = hsg % CD_FRAMES; + + gscd_bin2bcd(&msf -> min); /* convert to BCD */ + gscd_bin2bcd(&msf -> sec); + gscd_bin2bcd(&msf -> frame); +} + + +static void gscd_bin2bcd (unsigned char *p) +{ +int u, t; + + u = *p % 10; + t = *p / 10; + *p = u | (t << 4); +} + + +#ifdef FUTURE_WOTK +static long gscd_msf2hsg (struct msf *mp) +{ + return gscd_bcd2bin(mp -> frame) + + gscd_bcd2bin(mp -> sec) * CD_FRAMES + + gscd_bcd2bin(mp -> min) * CD_FRAMES * CD_SECS + - CD_BLOCK_OFFSET; +} + +static int gscd_bcd2bin (unsigned char bcd) +{ + return (bcd >> 4) * 10 + (bcd & 0xF); +} +#endif + + --- linux/include/linux/gscd.h.ol Wed Apr 19 21:01:44 1995 +++ linux/include/linux/gscd.h Mon Apr 17 00:23:56 1995 @@ -0,0 +1,110 @@ +/* + * Definitions for a GoldStar R420 CD-ROM interface + * + * Copyright (C) 1995 Oliver Raupach + * Eberhard Moenkeberg + * + * Published under the GPL. + * + */ + + +/* The Interface Card default address is 0x340. This will work fo most + applications. Address selection is accomplished by jumpers PN801-1 to + PN801-4 on the GoldStar Interface Card. + Appropriate settings are: 0x300, 0x310, 0x320, 0x330, 0x340, 0x350, 0x360 + 0x370, 0x380, 0x390, 0x3A0, 0x3B0, 0x3C0, 0x3D0, 0x3E0, 0x3F0 */ + +/* insert here the I/O port address */ +#define GSCD_BASE_ADDR 0x340 + +/* change this to set the dma-channel */ +#define GSCD_DMA_CHANNEL 3 /* not used */ + +/************** nothing to set up below here *********************/ + +/* port access macro */ +#define GSCDPORT(x) (gscd_port + (x)) + +/* + * commands + * the lower nibble holds the command length + */ +#define CMD_STATUS 0x01 +#define CMD_READSUBQ 0x02 /* 1: ?, 2: UPC, 5: ? */ +#define CMD_SEEK 0x05 /* read_mode M-S-F */ +#define CMD_READ 0x07 /* read_mode M-S-F nsec_h nsec_l */ +#define CMD_RESET 0x11 +#define CMD_SETMODE 0x15 +#define CMD_PLAY 0x17 /* M-S-F M-S-F */ +#define CMD_LOCK_CTL 0x22 /* 0: unlock, 1: lock */ +#define CMD_IDENT 0x31 +#define CMD_SETSPEED 0x32 /* 0: auto */ /* ??? */ +#define CMD_GETMODE 0x41 +#define CMD_PAUSE 0x51 +#define CMD_READTOC 0x61 +#define CMD_DISKINFO 0x71 +#define CMD_TRAY_CTL 0x81 + +/* + * disk_state: + */ +#define ST_PLAYING 0x80 +#define ST_UNLOCKED 0x40 +#define ST_NO_DISK 0x20 +#define ST_DOOR_OPEN 0x10 +#define ST_x08 0x08 +#define ST_x04 0x04 +#define ST_INVALID 0x02 +#define ST_x01 0x01 + +/* + * cmd_type: + */ +#define TYPE_INFO 0x01 +#define TYPE_DATA 0x02 + +/* + * read_mode: + */ +#define MOD_POLLED 0x80 +#define MOD_x08 0x08 +#define MOD_RAW 0x04 + +#define READ_DATA(port, buf, nr) insb(port, buf, nr) + +#define SET_TIMER(func, jifs) \ + ((timer_table[GSCD_TIMER].expires = jiffies + jifs), \ + (timer_table[GSCD_TIMER].fn = func), \ + (timer_active |= 1<