/*
    OpenVMS CDROM audio module for SDL (Simple DirectMedia Layer)
    Copyright (C) 2006

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Sam Lantinga
    slouken@libsdl.org

    (c)  Alexey Chupahin  (aka CHAPG)
*/

#ifdef SAVE_RCSID
static char rcsid =
 "@(#) $Id: SDL_syscdrom.c,v 1.11 2005/05/20 07:34:34 slouken Exp $";
#endif

/* Functions for system-level CD-ROM audio control */

#define DEBUG_CDROM 1
#include <sys/types.h>
#include <stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <ssdef.h>
#include <stsdef.h>
#include <descrip.h>
#include <lib$routines.h>
#include <starlet.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>


#include "SDL_error.h"
#include "SDL_cdrom.h"
#include "SDL_syscdrom.h"

// --------------------------------------------------
// OpenVMS specific definitions
// --------------------------------------------------
#define PAUSE                   0
#define RESUME                  1
#define PREVENT_REMOVAL         2
#define ALLOW_REMOVAL           3
#define PLAY_AUDIO              4
#define PLAY_AUDIO_MSF          5
#define PLAY_AUDIO_TRACK        6
#define PLAY_TRACK_REL          7
#define READ_HEADER             8
#define GET_STATUS              9
#define GET_TOC                 10
#define SET_VOLUME              11
#define GET_VOLUME              12
#define SET_DEFAULT             13
#define GET_DEFAULT             14
#define ONLINE                  15

#define SCSI_STS_GOOD                   0
#define SCSI_STS_CHECK_CONDITION        1
#define SCSI_STS_CONDITION_MET          2
#define SCSI_STS_BUSY                   3
#define SCSI_STS_INTERMEDIATE           8
#define SCSI_STS_INT_COND_MET           10
#define SCSI_STS_RES_CONFLICT           12
#define SCSI_STS_COMMAND_TERM           17
#define SCSI_STS_QUEUE_FULL             20

#define MSF     1
#define LBA     0
#define GK_EFN  1

#define MAX_TOC_LENGTH  804

#define SENSE_DATA_LENGTH 18

typedef struct
    {
        unsigned short toc_data_length;
        char toc_first_track;
        char toc_last_track;
    } READ_TOC_HEADER;

typedef struct
    {
    unsigned char msf_rsvd;
    unsigned int m_field : 8;
    unsigned int s_field : 8;
    unsigned int f_field : 8;
    } MSF_TYPE;

typedef struct
    {
        unsigned char byte[4];
    } LONG_STRUCT;
                      

typedef struct
    {
    unsigned char toc_rsvd1;            /* 1st byte */
    unsigned int pre_emp : 1;
    unsigned int copy_prohib : 1;
    unsigned int data_track : 1;
    unsigned int num_channels : 1;
    unsigned int toc_adr : 4;           /* 2nd byte */
    unsigned char toc_track_num;        /* 3rd byte */
    unsigned char toc_rsvd2;            /* 4th byte */
    union
        {
        LONG_STRUCT toc_abs_cdrom_addr;
        MSF_TYPE msf_field;             /* 5th thru 8th bytes */
        } MSF_LBA_UNION;
} READ_TOC_DATA;

typedef struct  {
        unsigned short  dsc$w_length;
        unsigned char   dsc$b_dtype;
        unsigned char   dsc$b_class;
        char            *dsc$a_pointer;
 } DESCRIPTOR;

DESCRIPTOR dev;


typedef struct
    {
    short function_code;        // function code
    short aucb_version;         // Should be 1
    unsigned long arg1;
    unsigned long arg2;
    unsigned long arg3;
    unsigned long rsvd1;
/*    unsigned long */ char *dest_buf_addr;
    unsigned long dest_buf_cnt;
   unsigned long dest_buf_trans_cnt;
    unsigned long command_status;
    unsigned long scsi_status;
/*    unsigned long*/ char *sense_buf_addr;
    unsigned long sense_buf_cnt;
    unsigned long sense_buf_trans_cnt;
    unsigned long rsvd2;
    } AUCB;

char    SENSE[SENSE_DATA_LENGTH];
int     wait_time=5;
globalvalue
    IO$_READVBLK,
    IO$_READPROMPT,
    IO$_DIAGNOSE;


/* The maximum number of CD-ROM drives we'll detect */
#define MAX_DRIVES	16	

/* A list of available CD-ROM drives */
static char *SDL_cdlist[MAX_DRIVES];
static dev_t SDL_cdmode[MAX_DRIVES];

/* The system-dependent CD control functions */
static const char *SDL_SYS_CDName(int drive);
static int SDL_SYS_CDOpen(int drive);
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
static int SDL_SYS_CDPause(SDL_CD *cdrom);
static int SDL_SYS_CDResume(SDL_CD *cdrom);
static int SDL_SYS_CDStop(SDL_CD *cdrom);
static int SDL_SYS_CDEject(SDL_CD *cdrom);
static void SDL_SYS_CDClose(SDL_CD *cdrom);



/* Check a drive to see if it is a CD-ROM */
static int CheckDrive(char *drive, char *mnttype, struct stat *stbuf)
{
	int is_cd=1;
	int status;
	short channel;

	dev.dsc$w_length = (unsigned short) strlen(drive);
	dev.dsc$b_dtype  = (unsigned char) 14;
	dev.dsc$b_class  = (unsigned char) 1;
	dev.dsc$a_pointer= strdup(drive);

    	/* If it doesn't exist, return -1 */
    	status = sys$assign (&dev,  &channel, 0, 0, 0);
    	if (!(status & 1)) {is_cd=0; return (is_cd);}

    	sys$dassgn(channel);

    	return(is_cd);

}

/* Add a CD-ROM drive to our list of valid drives */
static void AddDrive(char *drive, struct stat *stbuf)
{
	int i;

/* CHAPG
Checking dublicate drive names is not implemented yet;
to be fixed if needed
*/


		/* Add this drive to our list */
		i = SDL_numcds;
		SDL_cdlist[i] = (char *)malloc(strlen(drive)+1);
		if ( SDL_cdlist[i] == NULL ) {
			SDL_OutOfMemory();
			return;
		}
  strcpy(SDL_cdlist[i], drive);
  ++SDL_numcds;
#ifdef DEBUG_CDROM
  fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
#endif
}


int  SDL_SYS_CDInit(void)
{
	/* checklist: /dev/cdrom, /dev/hd?, /dev/scd? /dev/sr? */

	char *SDLcdrom;
	int i, j, exists;
	char drive[32];
	struct stat stbuf;

	/* Fill in our driver capabilities */
	SDL_CDcaps.Name = SDL_SYS_CDName;
	SDL_CDcaps.Open = SDL_SYS_CDOpen;
	SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
	SDL_CDcaps.Status = SDL_SYS_CDStatus;
	SDL_CDcaps.Play = SDL_SYS_CDPlay;
	SDL_CDcaps.Pause = SDL_SYS_CDPause;
	SDL_CDcaps.Resume = SDL_SYS_CDResume;
	SDL_CDcaps.Stop = SDL_SYS_CDStop;
	SDL_CDcaps.Eject = SDL_SYS_CDEject;
	SDL_CDcaps.Close = SDL_SYS_CDClose;

	/* Look in the environment for our CD-ROM drive list */
	SDLcdrom = getenv("SDL_CDROM");	/* ':' separated list of devices */
	if ( SDLcdrom != NULL ) {
		char *cdpath, *delim;
		cdpath = malloc(strlen(SDLcdrom)+1);
		if ( cdpath != NULL ) {
			strcpy(cdpath, SDLcdrom);
			SDLcdrom = cdpath;
			do {
				delim = strchr(SDLcdrom, ':');
				if ( delim ) {
					*delim++ = '\0';
				}
#ifdef DEBUG_CDROM
  fprintf(stderr, "Checking CD-ROM drive from SDL_CDROM: %s\n", SDLcdrom);
#endif
					AddDrive(SDLcdrom, &stbuf);
				if ( delim ) {
					SDLcdrom = delim;
				} else {
					SDLcdrom = NULL;
				}
			} while ( SDLcdrom );
			free(cdpath);
		}

		/* If we found our drives, there's nothing left to do */
		if ( SDL_numcds > 0 ) 	return(0);
	}

  return(0);
}


static const char *SDL_SYS_CDName(int drive)
{
	return(SDL_cdlist[drive]);
}

static int SDL_SYS_CDOpen(int drive)
{
    unsigned short channel;
    unsigned long status;

    dev.dsc$w_length = (unsigned short) strlen(SDL_cdlist[drive]);
    dev.dsc$b_dtype  = (unsigned char) 14;
    dev.dsc$b_class  = (unsigned char) 1;
    dev.dsc$a_pointer= strdup(SDL_cdlist[drive]);

    status = sys$assign (&dev,  &channel, 0, 0, 0);

#ifdef DEBUG_CDROM
        printf("SDL_SYS_CDOpen: SDL_cdlist[drive] %s\n",SDL_cdlist[drive]);
        printf("Status channel %d %d\n",status,channel);
#endif

    if (!(status & 1)) {return (0);}

    return((int)channel);
}

static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
{
int i;
int okay = 0;
char                blk[MAX_TOC_LENGTH];
AUCB                aucb;
READ_TOC_HEADER     *toc_header;
READ_TOC_DATA       *toc_data;
int                 cd_iosb[2];
int                 get_toc_status;
int                 status;

// Filling aucb structure to get TOC
    aucb.function_code = GET_TOC;               //AUDIO_GET_TOC
    aucb.aucb_version =  1;                     // should be 1 - regards to http://h71000.www7.hp.com/DOC/73final/6136/6136pro_007.
    aucb.arg1 = MSF;                            // MSF mode
    aucb.arg2 = 0;                              // starting track 0
    aucb.arg3 = 0;                              //
    aucb.rsvd1 = 0;                             // reserved always zero
    aucb.dest_buf_addr = blk;
    aucb.dest_buf_cnt = MAX_TOC_LENGTH;
    aucb.dest_buf_trans_cnt = 0;
    aucb.scsi_status = -1;
    aucb.command_status = 0;
    aucb.sense_buf_addr= SENSE;
    aucb.sense_buf_cnt = SENSE_DATA_LENGTH;
    aucb.sense_buf_trans_cnt =0;
    aucb.rsvd1 = aucb.rsvd2 = 0;

#ifdef DEBUG_CDROM
    printf("Execute READ TOC function\n");
#endif
    get_toc_status = 1;

    status = sys$qiow ( GK_EFN, cdrom->id, IO$_READPROMPT, cd_iosb, 0, 0, &aucb, sizeof(AUCB), 0, 0, 0, 0);

    if (status != SS$_NORMAL) { fprintf(stderr, "qiow error get CDROM_TOC_HEADER"); okay= 0; }

    if (aucb.command_status !=  SS$_NORMAL)
            {
#ifdef DEBUG_CDROM
                printf("\nOperating system command status is NOT NORMAL");
#endif
                okay= 0;
            }
            else
             {
#ifdef DEBUG_CDROM
                printf("\nOperating system command status is NORMAL");
                /* Do not continue looping when the status was OK */
#endif
		okay=0;
            }

  if (get_toc_status == SS$_NORMAL)
      {
          /*
          * Determine the number of TOC track descriptors
          */

          toc_header = (READ_TOC_HEADER *) blk;

          /*
          * We must switch the order of the bytes so that the most signifigant
          * byte is in the correct place.
          */
/* I dont know what this code do
          toc_header->toc_data_length = (toc_header->toc_data_length >> 8)
                                        | ((unsigned short)blk[0]) << 8;
*/
#ifdef DEBUG_CDROM
          printf("\nThe first track is: %d, The last track is: %d\n",
                (int)toc_header->toc_first_track , (int)toc_header->toc_last_track);
	  printf(" by blk: %d  %d\n",(int)blk[2], (int)blk[3]);
          printf("\n\n");
#endif

          cdrom->numtracks = toc_header->toc_last_track   -  toc_header->toc_first_track +1;

          if ( cdrom->numtracks > SDL_MAX_TRACKS ) { cdrom->numtracks = SDL_MAX_TRACKS; }

          toc_data = (READ_TOC_DATA *) &(blk[4]);

	        if ( cdrom->numtracks > SDL_MAX_TRACKS ) {
			cdrom->numtracks = SDL_MAX_TRACKS;
		}
		/* Read all the track TOC entries */
		for ( i=0; i<=cdrom->numtracks; ++i ) {
			if ( i == cdrom->numtracks ) {
				cdrom->track[i].id = 0xAA;
			} else {
				cdrom->track[i].id = toc_header->toc_first_track + i;
			}
			
                	if (toc_data->data_track) cdrom->track[i].type = SDL_DATA_TRACK;
                                            else cdrom->track[i].type = SDL_AUDIO_TRACK;

			cdrom->track[i].offset = MSF_TO_FRAMES(
						toc_data->MSF_LBA_UNION.msf_field.m_field,
						toc_data->MSF_LBA_UNION.msf_field.s_field,
						toc_data->MSF_LBA_UNION.msf_field.f_field);
			cdrom->track[i].length = 0;
			if ( i > 0 ) {
					cdrom->track[i-1].length =
						cdrom->track[i].offset-
						cdrom->track[i-1].offset;
			}

			if ( i == (cdrom->numtracks) ) {
			okay = 1;
			}
		toc_data++;
	}
   }

#ifdef DEBUG_CDROM
printf("GetTOC Okay %d \n",okay);
#endif

return(okay ? 0 : -1);
}


/* Get CD-ROM status */
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
{

int i;
int okay = 0;
READ_TOC_DATA       *toc_data;
char                blk[MAX_TOC_LENGTH];
AUCB                aucb;
int                 cd_iosb[2];
int                 status_qio;
CDstatus            status;
int                 get_status;


// Filling aucb structure to get status
    aucb.function_code = GET_STATUS;            // Get Status
    aucb.aucb_version =  1;                     // should be 1 - regards to http://h71000.www7.hp.com/DOC/73final/6136/6136pro_007.
    aucb.arg1 = MSF;                            // MSF mode
    aucb.arg2 = 0;                           	// starting track 0
    aucb.arg3 = 0;                              //
    aucb.rsvd1 = 0;                             // reserved always zero
    aucb.dest_buf_addr = blk;
    aucb.dest_buf_cnt = MAX_TOC_LENGTH;
    aucb.dest_buf_trans_cnt = 0;
    aucb.scsi_status = -1;
    aucb.command_status = 0;
    aucb.sense_buf_addr= SENSE;
    aucb.sense_buf_cnt = SENSE_DATA_LENGTH;
    aucb.sense_buf_trans_cnt =0;
    aucb.rsvd1 = aucb.rsvd2 = 0;


#ifdef DEBUG_CDROM
        printf("Execute GET STATUS function\n");
#endif

        status_qio = sys$qiow (GK_EFN, cdrom->id, IO$_READPROMPT, cd_iosb, 0, 0,
                                &aucb, sizeof(AUCB), 0, 0, 0, 0);

        get_status = 1;

        if (status_qio == SS$_NORMAL)
        {
            /* First check Operating System Command status */
            if (aucb.command_status !=  SS$_NORMAL)
            {
#ifdef DEBUG_CDROM
                printf("\nOperating system command status is NOT NORMAL!\n");
#endif
//                /* Make some further checks, and print out the info */
//                get_status = complete_aucb(aucb);
            }
            else
            {

#ifdef DEBUG_CDROM
printf("\nOperating system command status is NORMAL\n");
#endif
            }
         }
         else
         {

#ifdef DEBUG_CDROM
            printf("\nSYS$QIOW ERROR, COMMAND ABORTED!\n");
#endif
            status = CD_ERROR;
         }

        /*
         * Print out Audio status string based on Audio status code.
        */

#ifdef DEBUG_CDROM
printf("blk[1] = %d\n",blk[1]);
#endif

      switch (blk[1])
        {
        case 17:
                status = CD_PLAYING;
            break;
        case 18:
                status = CD_PAUSED;
            break;
        case 19:
                status = CD_STOPPED;
            break;
        case 20:
                status = CD_ERROR;
            break;
	case 21:
		status = CD_STOPPED;
	    break;
        default:
                status = CD_STOPPED;
#ifdef DEBUG_CDROM
            printf("Audio status is (No valid status)\n");
#endif
            break;
        }


       toc_data = (READ_TOC_DATA *) &(blk[4]);


	if ( position ) {
		if ( status == CD_PLAYING || (status == CD_PAUSED) ) {
			*position = MSF_TO_FRAMES(
						toc_data->MSF_LBA_UNION.msf_field.m_field,
						toc_data->MSF_LBA_UNION.msf_field.s_field,
						toc_data->MSF_LBA_UNION.msf_field.f_field);
		} else {
			*position = 0;
		}
	}


  return (status);
}


/* Start play */
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
{
int 		    m0,s0,f0, m1,s1,f1;
AUCB                aucb;
char                blk[MAX_TOC_LENGTH];
int		    status;
int                 cd_iosb[2];

FRAMES_TO_MSF(start, &m0, &s0, &f0);
FRAMES_TO_MSF(start+length,   &m1, &s1, &f1);

#ifdef DEBUG_CDROM
 fprintf(stderr, "Trying to play from %d:%d:%d to %d:%d:%d\n",
	m0, s0, f0,
	m1, s1, f1);
#endif

// Filling aucb structure to get status
    aucb.function_code = PLAY_AUDIO_MSF;       // Play audio MSF
    aucb.aucb_version =  1;                    // should be 1 - regards to http://h71000.www7.hp.com/DOC/73final/6136/6136pro_007.
    aucb.arg1 = m0<<16 | s0<<8 | f0;           //
    aucb.arg2 = m1<<16 | s1<<8 | f1;           //
    aucb.arg3 =  0;                            //
    aucb.rsvd1 = 0;                            // reserved always zero
    aucb.dest_buf_addr = blk;
    aucb.dest_buf_cnt = MAX_TOC_LENGTH;
    aucb.dest_buf_trans_cnt = 0;
    aucb.scsi_status = -1;
    aucb.command_status = 0;
    aucb.sense_buf_addr= SENSE;
    aucb.sense_buf_cnt = SENSE_DATA_LENGTH;
    aucb.sense_buf_trans_cnt =0;
    aucb.rsvd1 = aucb.rsvd2 = 0;
                  

    status = sys$qiow (GK_EFN, cdrom->id, IO$_READPROMPT, cd_iosb, 0, 0,
                                &aucb, sizeof(AUCB), 0, 0, 0, 0);

        /* Only proceed if there was not a SYS$QIOW error */
        if (status == SS$_NORMAL)
        {
            /* First check Operating System Command status */
            if (aucb.command_status !=  SS$_NORMAL)
            {
#ifdef CDROM_DEBUG
                printf("\nOperating system command status is NOT NORMAL");
#endif
                /* Make some further checks, and print out the info */
//                play_status = complete_aucb(aucb);

                /*
                * If status was anything other than Unit Attention,
                * stop retrying , otherwise wait 5 seconds and retry
                */
                return(0);
            }      
         }
         else {
		printf("ERROR QIO!!!\n");
		return (0);
	   }
return (1);
}

/* Pause play */
static int SDL_SYS_CDPause(SDL_CD *cdrom)
{
char                blk[MAX_TOC_LENGTH];
AUCB                aucb;
READ_TOC_HEADER     *toc_header;
READ_TOC_DATA       *toc_data;
int                 cd_iosb[2];
int                 status;

// Filling aucb structure to get TOC
    aucb.function_code = PAUSE;                //
    aucb.aucb_version =  1;                    // should be 1 - regards to http://h71000.www7.hp.com/DOC/73final/6136/6136pro_007.
    aucb.arg1 = 0;                             //
    aucb.arg2 = 0;                             //
    aucb.arg3 = 0;                             //
    aucb.rsvd1 = 0;                            // reserved always zero
    aucb.dest_buf_addr = NULL;
    aucb.dest_buf_cnt = 0;
    aucb.dest_buf_trans_cnt = 0;
    aucb.scsi_status = 0;
    aucb.command_status = 0;
    aucb.sense_buf_addr= SENSE;
    aucb.sense_buf_cnt = SENSE_DATA_LENGTH;
    aucb.sense_buf_trans_cnt =0;
    aucb.rsvd1 = aucb.rsvd2 = 0;

        status = sys$qiow (GK_EFN, cdrom->id, IO$_READPROMPT, cd_iosb, 0, 0,
                                &aucb, sizeof(AUCB), 0, 0, 0, 0);
                                                                
        /* Only proceed if there was not a SYS$QIOW error */
        if (status == SS$_NORMAL) return (1);
            else return (0);

}

/* Resume play */
static int SDL_SYS_CDResume(SDL_CD *cdrom)
{
char                blk[MAX_TOC_LENGTH];
AUCB                aucb;
int                 cd_iosb[2];
int                 status;

// Filling aucb structure to get TOC
    aucb.function_code = RESUME;                //
    aucb.aucb_version =  1;                    // should be 1 - regards to http://h71000.www7.hp.com/DOC/73final/6136/6136pro_007.
    aucb.arg1 = 0;                             //
    aucb.arg2 = 0;                             //
    aucb.arg3 = 0;                             //
    aucb.rsvd1 = 0;                            // reserved always zero
    aucb.dest_buf_addr = NULL;
    aucb.dest_buf_cnt = 0;
    aucb.dest_buf_trans_cnt = 0;
    aucb.scsi_status = 0;
    aucb.command_status = 0;
    aucb.sense_buf_addr= SENSE;
    aucb.sense_buf_cnt = SENSE_DATA_LENGTH;
    aucb.sense_buf_trans_cnt =0;
    aucb.rsvd1 = aucb.rsvd2 = 0;

        status = sys$qiow (GK_EFN, cdrom->id, IO$_READPROMPT, cd_iosb, 0, 0,
                                &aucb, sizeof(AUCB), 0, 0, 0, 0);

        /* Only proceed if there was not a SYS$QIOW error */
        if (status == SS$_NORMAL) return (1);
                else return (0);


}

/* Stop play */
/* Very strange - I dont find command descriptions in OpenVMS documentation 
- so I just quick hacked it from xmcd - best audio player.
*/
static int SDL_SYS_CDStop(SDL_CD *cdrom)
{
char                blk[MAX_TOC_LENGTH];
AUCB                aucb;
int                 cd_iosb[2];
int                 status;
int		    i;
char stop_command [6] = {1,0,0,0,0,0};
int	gk_desc[15];

gk_desc[0] = 1;
gk_desc[1] = 3;
gk_desc[2] = (unsigned int)stop_command;
gk_desc[3] = 6;
gk_desc[4] = 0;
gk_desc[5] = 0;
gk_desc[6] = 0;
gk_desc[7] = 0;
gk_desc[8] = 20;
for (i=9; i<15; i++) gk_desc[i] = 0;

	status = sys$qiow (GK_EFN, cdrom->id, IO$_DIAGNOSE, cd_iosb, 0, 0, 
			   &gk_desc[0], 15*4, 0, 0, 0, 0);
        /* Only proceed if there was not a SYS$QIOW error */
        if (status == SS$_NORMAL) return (1);
                else return (0);
}

/* Eject the CD-ROM */
static int SDL_SYS_CDEject(SDL_CD *cdrom)
{
char                blk[MAX_TOC_LENGTH];
AUCB                aucb;
int                 cd_iosb[2];
int                 status;

char eject_command [6] = {0x1B,1,0,0,2,0};
char allow_eject [6] = {0x1B,0,0,0,0,0};
int     gk_desc[15];
int	i;
 

gk_desc[0] = 1;
gk_desc[1] = 3;
gk_desc[2] = (unsigned long)allow_eject;
gk_desc[3] = 6;
gk_desc[4] = 0;
gk_desc[5] = 0;
gk_desc[6] = 0;
gk_desc[7] = 0;
gk_desc[8] = 20;
for (i=9; i<15; i++) gk_desc[i] = 0;
 
        status = sys$qiow (GK_EFN, cdrom->id, IO$_DIAGNOSE, cd_iosb, 0, 0,
                           gk_desc, 15*4, 0, 0, 0, 0);                                                                               

gk_desc[0] = 1;
gk_desc[1] = 3;
gk_desc[2] = (unsigned int)eject_command;
gk_desc[3] = 6;
gk_desc[4] = 0;
gk_desc[5] = 0;
gk_desc[6] = 0;
gk_desc[7] = 0;
gk_desc[8] = 20;
for (i=9; i<15; i++) gk_desc[i] = 0;
                                                                                
        status = sys$qiow (GK_EFN, cdrom->id, IO$_DIAGNOSE, cd_iosb, 0, 0,
                           gk_desc, 15*4, 0, 0, 0, 0);
        /* Only proceed if there was not a SYS$QIOW error */
        if (status == SS$_NORMAL) return (1);
                else return (0);

}

/* Close the CD-ROM handle */
/* SCSI CD Drives around me cant load anything byself */

static void SDL_SYS_CDClose(SDL_CD *cdrom)
{
//	close(cdrom->id);
}

void SDL_SYS_CDQuit(void)
{
	int i;

	if ( SDL_numcds > 0 ) {
		for ( i=0; i<SDL_numcds; ++i ) {
			free(SDL_cdlist[i]);
		}
		SDL_numcds = 0;
	}
}

