src/cdrom/bsdi/SDL_syscdrom.c
author Sam Lantinga <slouken@libsdl.org>
Wed, 01 Feb 2006 06:32:25 +0000
changeset 1312 c9b51268668f
parent 252 e8157fcb3114
child 1336 3692456e7b0f
permissions -rw-r--r--
Updated copyright information and removed rcs id lines (problematic in branch merges)
I batch edited these files, so please let me know if I've accidentally removed anybody's
credit here.
slouken@178
     1
/*
slouken@178
     2
    SDL - Simple DirectMedia Layer
slouken@1312
     3
    Copyright (C) 1997-2006 Sam Lantinga
slouken@178
     4
slouken@178
     5
    This library is free software; you can redistribute it and/or
slouken@1312
     6
    modify it under the terms of the GNU Lesser General Public
slouken@178
     7
    License as published by the Free Software Foundation; either
slouken@1312
     8
    version 2.1 of the License, or (at your option) any later version.
slouken@178
     9
slouken@178
    10
    This library is distributed in the hope that it will be useful,
slouken@178
    11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
slouken@178
    12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
slouken@1312
    13
    Lesser General Public License for more details.
slouken@178
    14
slouken@1312
    15
    You should have received a copy of the GNU Lesser General Public
slouken@1312
    16
    License along with this library; if not, write to the Free Software
slouken@1312
    17
    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
slouken@178
    18
slouken@178
    19
    Sam Lantinga
slouken@252
    20
    slouken@libsdl.org
slouken@178
    21
*/
slouken@178
    22
slouken@178
    23
/*
slouken@178
    24
 * Functions for system-level CD-ROM audio control for BSD/OS 4.x
slouken@178
    25
 * This started life out as a copy of the freebsd/SDL_cdrom.c file but was
slouken@178
    26
 * heavily modified.   Works for standard (MMC) SCSI and ATAPI CDrom drives.
slouken@178
    27
 *
slouken@178
    28
 * Steven Schultz - sms@to.gd-es.com
slouken@178
    29
*/
slouken@178
    30
slouken@178
    31
#include <sys/types.h>
slouken@178
    32
#include <stdlib.h>
slouken@178
    33
#include <sys/stat.h>
slouken@178
    34
#include <fcntl.h>
slouken@178
    35
#include <stdio.h>
slouken@178
    36
#include <string.h>
slouken@178
    37
#include <errno.h>
slouken@178
    38
#include <err.h>
slouken@178
    39
#include <unistd.h>
slouken@178
    40
#include <sys/ioctl.h>
slouken@178
    41
#include </sys/dev/scsi/scsi.h>
slouken@178
    42
#include </sys/dev/scsi/scsi_ioctl.h>
slouken@178
    43
slouken@178
    44
#include "SDL_error.h"
slouken@178
    45
#include "SDL_cdrom.h"
slouken@178
    46
#include "SDL_syscdrom.h"
slouken@178
    47
slouken@178
    48
/*
slouken@178
    49
 * The msf_to_frame and frame_to_msf were yanked from libcdrom and inlined
slouken@178
    50
 * here so that -lcdrom doesn't have to be dragged in for something so simple.
slouken@178
    51
*/
slouken@178
    52
slouken@178
    53
#define	FRAMES_PER_SECOND	75
slouken@178
    54
#define	FRAMES_PER_MINUTE	(FRAMES_PER_SECOND * 60)
slouken@178
    55
slouken@178
    56
int
slouken@178
    57
msf_to_frame(int minute, int second, int frame)
slouken@178
    58
	{
slouken@178
    59
	return(minute * FRAMES_PER_MINUTE + second * FRAMES_PER_SECOND + frame);
slouken@178
    60
	}
slouken@178
    61
slouken@178
    62
void
slouken@178
    63
frame_to_msf(int frame, int *minp, int *secp, int *framep)
slouken@178
    64
	{
slouken@178
    65
	*minp = frame / FRAMES_PER_MINUTE;
slouken@178
    66
	*secp = (frame % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND;
slouken@178
    67
	*framep = frame % FRAMES_PER_SECOND;
slouken@178
    68
	}
slouken@178
    69
slouken@178
    70
/* The maximum number of CD-ROM drives we'll detect */
slouken@178
    71
#define MAX_DRIVES	16	
slouken@178
    72
slouken@178
    73
/* A list of available CD-ROM drives */
slouken@178
    74
static char *SDL_cdlist[MAX_DRIVES];
slouken@178
    75
static dev_t SDL_cdmode[MAX_DRIVES];
slouken@178
    76
slouken@178
    77
/* The system-dependent CD control functions */
slouken@178
    78
static const char *SDL_SYS_CDName(int drive);
slouken@178
    79
static int SDL_SYS_CDOpen(int drive);
slouken@178
    80
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
slouken@178
    81
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
slouken@178
    82
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
slouken@178
    83
static int SDL_SYS_CDPause(SDL_CD *cdrom);
slouken@178
    84
static int SDL_SYS_CDResume(SDL_CD *cdrom);
slouken@178
    85
static int SDL_SYS_CDStop(SDL_CD *cdrom);
slouken@178
    86
static int SDL_SYS_CDEject(SDL_CD *cdrom);
slouken@178
    87
static void SDL_SYS_CDClose(SDL_CD *cdrom);
slouken@178
    88
slouken@178
    89
typedef	struct	scsi_cdb cdb_t;
slouken@178
    90
slouken@178
    91
static int scsi_cmd(int fd,
slouken@178
    92
		struct scsi_cdb *cdb,
slouken@178
    93
		int cdblen, 
slouken@178
    94
		int rw,
slouken@178
    95
		caddr_t data,
slouken@178
    96
		int datalen,
slouken@178
    97
		struct scsi_user_cdb *sus)
slouken@178
    98
	{
slouken@178
    99
	int	scsistatus;
slouken@178
   100
	unsigned char	*cp;
slouken@178
   101
	struct	scsi_user_cdb suc;
slouken@178
   102
slouken@178
   103
    /* safety checks */
slouken@178
   104
	if	(!cdb) return(-1);
slouken@178
   105
	if	(rw != SUC_READ && rw != SUC_WRITE) return(-1);
slouken@178
   106
slouken@178
   107
	suc.suc_flags = rw;
slouken@178
   108
	suc.suc_cdblen = cdblen;
slouken@178
   109
	bcopy(cdb, suc.suc_cdb, cdblen);
slouken@178
   110
	suc.suc_datalen = datalen;
slouken@178
   111
	suc.suc_data = data;
slouken@178
   112
	suc.suc_timeout = 10;		/* 10 secs max for TUR or SENSE */
slouken@178
   113
	if	(ioctl(fd, SCSIRAWCDB, &suc) == -1)
slouken@178
   114
		return(-11);
slouken@178
   115
	scsistatus = suc.suc_sus.sus_status;
slouken@178
   116
	cp = suc.suc_sus.sus_sense;
slouken@178
   117
slouken@178
   118
/*
slouken@178
   119
 * If a place to copy the sense data back to has been provided then the
slouken@178
   120
 * caller is responsible for checking the errors and printing any information
slouken@178
   121
 * out if the status was not successful.
slouken@178
   122
*/
slouken@178
   123
	if	(scsistatus != 0 && !sus)
slouken@178
   124
		{
slouken@178
   125
		fprintf(stderr,"scsistatus = %x cmd = %x\n",
slouken@178
   126
			scsistatus, cdb[0]);
slouken@178
   127
		fprintf(stderr, "sense %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", 
slouken@178
   128
			cp[0], cp[1], cp[2], cp[3], cp[4], cp[5],
slouken@178
   129
			cp[6], cp[7], cp[8], cp[9], cp[10], cp[11],
slouken@178
   130
			cp[12], cp[13], cp[14], cp[15]);
slouken@178
   131
		return(1);
slouken@178
   132
		}
slouken@178
   133
	if	(sus)
slouken@178
   134
		bcopy(&suc, sus, sizeof (struct scsi_user_cdb));
slouken@178
   135
	if	(scsistatus)
slouken@178
   136
		return(1);	/* Return non-zero for unsuccessful status */
slouken@178
   137
	return(0);
slouken@178
   138
	}
slouken@178
   139
slouken@178
   140
/* request vendor brand and model */
slouken@178
   141
unsigned char *Inquiry(int fd)
slouken@178
   142
	{
slouken@178
   143
	static struct scsi_cdb6 cdb = 
slouken@178
   144
		{
slouken@178
   145
		0x12, 
slouken@178
   146
		0, 0, 0,
slouken@178
   147
		56,
slouken@178
   148
		0
slouken@178
   149
		};
slouken@178
   150
	static unsigned char Inqbuffer[56];
slouken@178
   151
slouken@178
   152
	if	(scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, Inqbuffer, 
slouken@178
   153
			sizeof(Inqbuffer), 0))
slouken@178
   154
		return("\377");
slouken@178
   155
	return(Inqbuffer);
slouken@178
   156
	}
slouken@178
   157
slouken@178
   158
#define ADD_SENSECODE 12
slouken@178
   159
#define ADD_SC_QUALIFIER 13
slouken@178
   160
slouken@178
   161
int TestForMedium(int fd)
slouken@178
   162
	{
slouken@178
   163
	int	sts, asc, ascq;
slouken@178
   164
	struct	scsi_user_cdb sus;
slouken@178
   165
	static struct scsi_cdb6 cdb =
slouken@178
   166
		{
slouken@178
   167
		CMD_TEST_UNIT_READY, /* command */
slouken@178
   168
		0,	/* reserved */
slouken@178
   169
		0,	/* reserved */
slouken@178
   170
		0,	/* reserved */
slouken@178
   171
		0,	/* reserved */
slouken@178
   172
		0	/* reserved */
slouken@178
   173
		};
slouken@178
   174
slouken@178
   175
again:	sts = scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, 0, 0, &sus);
slouken@178
   176
	asc = sus.suc_sus.sus_sense[ADD_SENSECODE];
slouken@178
   177
	ascq = sus.suc_sus.sus_sense[ADD_SC_QUALIFIER];
slouken@178
   178
	if	(asc == 0x3a && ascq == 0x0)	/* no medium */
slouken@178
   179
		return(0);
slouken@178
   180
	if	(asc == 0x28 && ascq == 0x0)	/* medium changed */
slouken@178
   181
		goto again;
slouken@178
   182
	if	(asc == 0x4 && ascq == 0x1 )	/* coming ready */
slouken@178
   183
		{
slouken@178
   184
		sleep(2);
slouken@178
   185
		goto again;
slouken@178
   186
		}
slouken@178
   187
	return(1);
slouken@178
   188
	}
slouken@178
   189
slouken@178
   190
/* Check a drive to see if it is a CD-ROM */
slouken@178
   191
static int CheckDrive(char *drive, struct stat *stbuf)
slouken@178
   192
{
slouken@178
   193
	int is_cd = 0, cdfd;
slouken@178
   194
	char *p;
slouken@178
   195
slouken@178
   196
	/* If it doesn't exist, return -1 */
slouken@178
   197
	if ( stat(drive, stbuf) < 0 ) {
slouken@178
   198
		return(-1);
slouken@178
   199
	}
slouken@178
   200
slouken@178
   201
	/* If it does exist, verify that it's an available CD-ROM */
slouken@178
   202
	cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
slouken@178
   203
	if ( cdfd >= 0 ) {
slouken@178
   204
		p = Inquiry(cdfd);
slouken@178
   205
		if (*p == TYPE_ROM)
slouken@178
   206
			is_cd = 1;
slouken@178
   207
		close(cdfd);
slouken@178
   208
	}
slouken@178
   209
	return(is_cd);
slouken@178
   210
}
slouken@178
   211
slouken@178
   212
/* Add a CD-ROM drive to our list of valid drives */
slouken@178
   213
static void AddDrive(char *drive, struct stat *stbuf)
slouken@178
   214
{
slouken@178
   215
	int i;
slouken@178
   216
slouken@178
   217
	if ( SDL_numcds < MAX_DRIVES ) {
slouken@178
   218
		/* Check to make sure it's not already in our list.
slouken@178
   219
	 	   This can happen when we see a drive via symbolic link.
slouken@178
   220
		 */
slouken@178
   221
		for ( i=0; i<SDL_numcds; ++i ) {
slouken@178
   222
			if ( stbuf->st_rdev == SDL_cdmode[i] ) {
slouken@178
   223
#ifdef DEBUG_CDROM
slouken@178
   224
  fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
slouken@178
   225
#endif
slouken@178
   226
				return;
slouken@178
   227
			}
slouken@178
   228
		}
slouken@178
   229
slouken@178
   230
		/* Add this drive to our list */
slouken@178
   231
		i = SDL_numcds;
slouken@178
   232
		SDL_cdlist[i] = (char *)malloc(strlen(drive)+1);
slouken@178
   233
		if ( SDL_cdlist[i] == NULL ) {
slouken@178
   234
			SDL_OutOfMemory();
slouken@178
   235
			return;
slouken@178
   236
		}
slouken@178
   237
		strcpy(SDL_cdlist[i], drive);
slouken@178
   238
		SDL_cdmode[i] = stbuf->st_rdev;
slouken@178
   239
		++SDL_numcds;
slouken@178
   240
#ifdef DEBUG_CDROM
slouken@178
   241
  fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
slouken@178
   242
#endif
slouken@178
   243
	}
slouken@178
   244
}
slouken@178
   245
slouken@178
   246
int  SDL_SYS_CDInit(void)
slouken@178
   247
{
slouken@178
   248
	/* checklist: /dev/rsr?c */
slouken@178
   249
	static char *checklist[] = {
slouken@178
   250
	"?0 rsr?", NULL
slouken@178
   251
	};
slouken@178
   252
	char *SDLcdrom;
slouken@178
   253
	int i, j, exists;
slouken@178
   254
	char drive[32];
slouken@178
   255
	struct stat stbuf;
slouken@178
   256
slouken@178
   257
	/* Fill in our driver capabilities */
slouken@178
   258
	SDL_CDcaps.Name = SDL_SYS_CDName;
slouken@178
   259
	SDL_CDcaps.Open = SDL_SYS_CDOpen;
slouken@178
   260
	SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
slouken@178
   261
	SDL_CDcaps.Status = SDL_SYS_CDStatus;
slouken@178
   262
	SDL_CDcaps.Play = SDL_SYS_CDPlay;
slouken@178
   263
	SDL_CDcaps.Pause = SDL_SYS_CDPause;
slouken@178
   264
	SDL_CDcaps.Resume = SDL_SYS_CDResume;
slouken@178
   265
	SDL_CDcaps.Stop = SDL_SYS_CDStop;
slouken@178
   266
	SDL_CDcaps.Eject = SDL_SYS_CDEject;
slouken@178
   267
	SDL_CDcaps.Close = SDL_SYS_CDClose;
slouken@178
   268
slouken@178
   269
	/* Look in the environment for our CD-ROM drive list */
slouken@178
   270
	SDLcdrom = getenv("SDL_CDROM");	/* ':' separated list of devices */
slouken@178
   271
	if ( SDLcdrom != NULL ) {
slouken@178
   272
		char *cdpath, *delim;
slouken@178
   273
		cdpath = malloc(strlen(SDLcdrom)+1);
slouken@178
   274
		if ( cdpath != NULL ) {
slouken@178
   275
			strcpy(cdpath, SDLcdrom);
slouken@178
   276
			SDLcdrom = cdpath;
slouken@178
   277
			do {
slouken@178
   278
				delim = strchr(SDLcdrom, ':');
slouken@178
   279
				if ( delim ) {
slouken@178
   280
					*delim++ = '\0';
slouken@178
   281
				}
slouken@178
   282
				if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
slouken@178
   283
					AddDrive(SDLcdrom, &stbuf);
slouken@178
   284
				}
slouken@178
   285
				if ( delim ) {
slouken@178
   286
					SDLcdrom = delim;
slouken@178
   287
				} else {
slouken@178
   288
					SDLcdrom = NULL;
slouken@178
   289
				}
slouken@178
   290
			} while ( SDLcdrom );
slouken@178
   291
			free(cdpath);
slouken@178
   292
		}
slouken@178
   293
slouken@178
   294
		/* If we found our drives, there's nothing left to do */
slouken@178
   295
		if ( SDL_numcds > 0 ) {
slouken@178
   296
			return(0);
slouken@178
   297
		}
slouken@178
   298
	}
slouken@178
   299
slouken@178
   300
	/* Scan the system for CD-ROM drives */
slouken@178
   301
	for ( i=0; checklist[i]; ++i ) {
slouken@178
   302
		if ( checklist[i][0] == '?' ) {
slouken@178
   303
			char *insert;
slouken@178
   304
			exists = 1;
slouken@178
   305
			for ( j=checklist[i][1]; exists; ++j ) {
slouken@178
   306
				sprintf(drive, "/dev/%sc", &checklist[i][3]);
slouken@178
   307
				insert = strchr(drive, '?');
slouken@178
   308
				if ( insert != NULL ) {
slouken@178
   309
					*insert = j;
slouken@178
   310
				}
slouken@178
   311
				switch (CheckDrive(drive, &stbuf)) {
slouken@178
   312
					/* Drive exists and is a CD-ROM */
slouken@178
   313
					case 1:
slouken@178
   314
						AddDrive(drive, &stbuf);
slouken@178
   315
						break;
slouken@178
   316
					/* Drive exists, but isn't a CD-ROM */
slouken@178
   317
					case 0:
slouken@178
   318
						break;
slouken@178
   319
					/* Drive doesn't exist */
slouken@178
   320
					case -1:
slouken@178
   321
						exists = 0;
slouken@178
   322
						break;
slouken@178
   323
				}
slouken@178
   324
			}
slouken@178
   325
		} else {
slouken@178
   326
			sprintf(drive, "/dev/%s", checklist[i]);
slouken@178
   327
			if ( CheckDrive(drive, &stbuf) > 0 ) {
slouken@178
   328
				AddDrive(drive, &stbuf);
slouken@178
   329
			}
slouken@178
   330
		}
slouken@178
   331
	}
slouken@178
   332
	return(0);
slouken@178
   333
}
slouken@178
   334
slouken@178
   335
static const char *SDL_SYS_CDName(int drive)
slouken@178
   336
{
slouken@178
   337
	return(SDL_cdlist[drive]);
slouken@178
   338
}
slouken@178
   339
slouken@178
   340
static int SDL_SYS_CDOpen(int drive)
slouken@178
   341
{
slouken@178
   342
	return(open(SDL_cdlist[drive], O_RDONLY | O_NONBLOCK | O_EXCL, 0));
slouken@178
   343
}
slouken@178
   344
slouken@178
   345
static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
slouken@178
   346
	{
slouken@178
   347
	u_char cdb[10], buf[4], *p, *toc;
slouken@178
   348
	struct scsi_user_cdb sus;
slouken@178
   349
	int i, sts, first_track, last_track, ntracks, toc_size;
slouken@178
   350
slouken@178
   351
	bzero(cdb, sizeof (cdb));
slouken@178
   352
	cdb[0] = 0x43;		/* Read TOC */
slouken@178
   353
	cdb[1] = 0x2;		/* MSF */
slouken@178
   354
	cdb[8] = 4;		/* size TOC header */
slouken@178
   355
	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, 4, &sus);
slouken@178
   356
	if	(sts < 0)
slouken@178
   357
		return(-1);
slouken@178
   358
	first_track = buf[2];
slouken@178
   359
	last_track = buf[3];
slouken@178
   360
	ntracks = last_track - first_track + 1;
slouken@178
   361
	cdrom->numtracks = ntracks;
slouken@178
   362
	toc_size = 4 + (ntracks + 1) * 8;
slouken@178
   363
	toc = (u_char *)malloc(toc_size);
slouken@178
   364
	if	(toc == NULL)
slouken@178
   365
		return(-1);
slouken@178
   366
	bzero(cdb, sizeof (cdb));
slouken@178
   367
	cdb[0] = 0x43;
slouken@178
   368
	cdb[1] = 0x2;
slouken@178
   369
	cdb[6] = first_track;
slouken@178
   370
	cdb[7] = toc_size >> 8;
slouken@178
   371
	cdb[8] = toc_size & 0xff;
slouken@178
   372
	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, toc, toc_size, 
slouken@178
   373
			&sus);
slouken@178
   374
	if	(sts < 0)
slouken@178
   375
		{
slouken@178
   376
		free(toc);
slouken@178
   377
		return(-1);
slouken@178
   378
		}
slouken@178
   379
slouken@178
   380
	for	(i = 0, p = toc+4; i <= ntracks; i++, p+= 8)
slouken@178
   381
		{
slouken@178
   382
		if	(i == ntracks)
slouken@178
   383
			cdrom->track[i].id = 0xAA;	/* Leadout */
slouken@178
   384
		else
slouken@178
   385
			cdrom->track[i].id = first_track + i;
slouken@178
   386
		if	(p[1] & 0x20)
slouken@178
   387
			cdrom->track[i].type = SDL_DATA_TRACK;
slouken@178
   388
		else
slouken@178
   389
			cdrom->track[i].type = SDL_AUDIO_TRACK;
slouken@178
   390
		cdrom->track[i].offset = msf_to_frame(p[5], p[6], p[7]);
slouken@178
   391
		cdrom->track[i].length = 0;
slouken@178
   392
		if	(i > 0)
slouken@178
   393
			cdrom->track[i-1].length = cdrom->track[i].offset -
slouken@178
   394
						   cdrom->track[i-1].offset;
slouken@178
   395
		}
slouken@178
   396
	free(toc);
slouken@178
   397
	return(0);
slouken@178
   398
	}
slouken@178
   399
slouken@178
   400
/* Get CD-ROM status */
slouken@178
   401
static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
slouken@178
   402
	{
slouken@178
   403
	CDstatus status;
slouken@178
   404
	u_char	cdb[10], buf[16];
slouken@178
   405
	int	sts;
slouken@178
   406
	struct	scsi_user_cdb sus;
slouken@178
   407
slouken@178
   408
	bzero(cdb, sizeof (cdb));
slouken@178
   409
	cdb[0] = 0x42;		/* read subq */
slouken@178
   410
	cdb[1] = 0x2;		/* MSF */
slouken@178
   411
	cdb[2] = 0x40;		/* q channel */
slouken@178
   412
	cdb[3] = 1;		/* current pos */
slouken@178
   413
	cdb[7] = sizeof (buf) >> 8;
slouken@178
   414
	cdb[8] = sizeof (buf) & 0xff;
slouken@178
   415
	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, sizeof (buf),
slouken@178
   416
			&sus);
slouken@178
   417
	if	(sts < 0)
slouken@178
   418
		return(-1);
slouken@178
   419
	if	(sts)
slouken@178
   420
		{
slouken@178
   421
		if	(TestForMedium(cdrom->id) == 0)
slouken@178
   422
			status = CD_TRAYEMPTY;
slouken@178
   423
		else
slouken@178
   424
			status = CD_ERROR;
slouken@178
   425
		}
slouken@178
   426
	else
slouken@178
   427
		{
slouken@178
   428
		switch	(buf[1])
slouken@178
   429
			{
slouken@178
   430
			case	0x11:
slouken@178
   431
				status = CD_PLAYING;
slouken@178
   432
				break;
slouken@178
   433
			case	0x12:
slouken@178
   434
				status = CD_PAUSED;
slouken@178
   435
				break;
slouken@178
   436
			case	0x13:
slouken@178
   437
			case	0x14:
slouken@178
   438
			case	0x15:
slouken@178
   439
				status = CD_STOPPED;
slouken@178
   440
				break;
slouken@178
   441
			default:
slouken@178
   442
				status = CD_ERROR;
slouken@178
   443
				break;
slouken@178
   444
			}
slouken@178
   445
		}
slouken@178
   446
	if	(position)
slouken@178
   447
		{
slouken@178
   448
		if	( status == CD_PLAYING || (status == CD_PAUSED) )
slouken@178
   449
			*position = msf_to_frame(buf[9], buf[10], buf[11]);
slouken@178
   450
		else
slouken@178
   451
			*position = 0;
slouken@178
   452
		}
slouken@178
   453
	return(status);
slouken@178
   454
	}
slouken@178
   455
slouken@178
   456
/* Start play */
slouken@178
   457
static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
slouken@178
   458
	{
slouken@178
   459
	u_char	cdb[10];
slouken@178
   460
	int	sts, minute, second, frame, eminute, esecond, eframe;
slouken@178
   461
	struct	scsi_user_cdb sus;
slouken@178
   462
slouken@178
   463
	bzero(cdb, sizeof(cdb));
slouken@178
   464
	cdb[0] = 0x47;		/* Play */
slouken@178
   465
	frame_to_msf(start, &minute, &second, &frame);
slouken@178
   466
	frame_to_msf(start + length, &eminute, &esecond, &eframe);
slouken@178
   467
	cdb[3] = minute;
slouken@178
   468
	cdb[4] = second;
slouken@178
   469
	cdb[5] = frame;
slouken@178
   470
	cdb[6] = eminute;
slouken@178
   471
	cdb[7] = esecond;
slouken@178
   472
	cdb[8] = eframe;
slouken@178
   473
	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus);
slouken@178
   474
	return(sts);
slouken@178
   475
	}
slouken@178
   476
slouken@178
   477
static	int
slouken@178
   478
pauseresume(SDL_CD *cdrom, int flag)
slouken@178
   479
	{
slouken@178
   480
	u_char	cdb[10];
slouken@178
   481
	struct	scsi_user_cdb sus;
slouken@178
   482
slouken@178
   483
	bzero(cdb, sizeof (cdb));
slouken@178
   484
	cdb[0] = 0x4b;
slouken@178
   485
	cdb[8] = flag & 0x1;
slouken@178
   486
	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus));
slouken@178
   487
	}
slouken@178
   488
slouken@178
   489
/* Pause play */
slouken@178
   490
static int SDL_SYS_CDPause(SDL_CD *cdrom)
slouken@178
   491
{
slouken@178
   492
	return(pauseresume(cdrom, 0));
slouken@178
   493
}
slouken@178
   494
slouken@178
   495
/* Resume play */
slouken@178
   496
static int SDL_SYS_CDResume(SDL_CD *cdrom)
slouken@178
   497
{
slouken@178
   498
	return(pauseresume(cdrom, 1));
slouken@178
   499
}
slouken@178
   500
slouken@178
   501
/* Stop play */
slouken@178
   502
static int SDL_SYS_CDStop(SDL_CD *cdrom)
slouken@178
   503
{
slouken@178
   504
	u_char cdb[6];
slouken@178
   505
	struct	scsi_user_cdb sus;
slouken@178
   506
slouken@178
   507
	bzero(cdb, sizeof (cdb));
slouken@178
   508
	cdb[0] = 0x1b;		/* stop */
slouken@178
   509
	cdb[1] = 1;		/* immediate */
slouken@178
   510
	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
slouken@178
   511
}
slouken@178
   512
slouken@178
   513
/* Eject the CD-ROM */
slouken@178
   514
static int SDL_SYS_CDEject(SDL_CD *cdrom)
slouken@178
   515
{
slouken@178
   516
	u_char cdb[6];
slouken@178
   517
	struct	scsi_user_cdb sus;
slouken@178
   518
slouken@178
   519
	bzero(cdb, sizeof (cdb));
slouken@178
   520
	cdb[0] = 0x1b;		/* stop */
slouken@178
   521
	cdb[1] = 1;		/* immediate */
slouken@178
   522
	cdb[4] = 2;		/* eject */
slouken@178
   523
	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
slouken@178
   524
}
slouken@178
   525
slouken@178
   526
/* Close the CD-ROM handle */
slouken@178
   527
static void SDL_SYS_CDClose(SDL_CD *cdrom)
slouken@178
   528
	{
slouken@178
   529
	close(cdrom->id);
slouken@178
   530
	}
slouken@178
   531
slouken@178
   532
void SDL_SYS_CDQuit(void)
slouken@178
   533
{
slouken@178
   534
	int i;
slouken@178
   535
slouken@178
   536
	if ( SDL_numcds > 0 ) {
slouken@178
   537
		for ( i=0; i<SDL_numcds; ++i ) {
slouken@178
   538
			free(SDL_cdlist[i]);
slouken@178
   539
			}
slouken@178
   540
		}
slouken@178
   541
	SDL_numcds = 0;
slouken@178
   542
}