Added CD-ROM support for BSD/OS (thanks Steven!)
authorSam Lantinga
Thu, 13 Sep 2001 15:57:48 +0000
changeset 1781fc1a101bf23
parent 177 5f46f27efb6a
child 179 ec9ec33673a2
Added CD-ROM support for BSD/OS (thanks Steven!)
configure.in
docs.html
src/cdrom/bsdi/.cvsignore
src/cdrom/bsdi/Makefile.am
src/cdrom/bsdi/SDL_syscdrom.c
     1.1 --- a/configure.in	Wed Sep 12 05:11:15 2001 +0000
     1.2 +++ b/configure.in	Thu Sep 13 15:57:48 2001 +0000
     1.3 @@ -1347,18 +1347,18 @@
     1.4              JOYSTICK_DRIVERS="$JOYSTICK_DRIVERS dummy/libjoystick_dummy.la"
     1.5          fi
     1.6          # Set up files for the cdrom library
     1.7 -        # (No cdrom support yet)
     1.8          if test x$enable_cdrom = xyes; then
     1.9 -            CDROM_SUBDIRS="$CDROM_SUBDIRS dummy"
    1.10 -            CDROM_DRIVERS="$CDROM_DRIVERS dummy/libcdrom_dummy.la"
    1.11 +            CDROM_SUBDIRS="$CDROM_SUBDIRS bsdi"
    1.12 +            CDROM_DRIVERS="$CDROM_DRIVERS bsdi/libcdrom_bsdi.la"
    1.13          fi
    1.14          # Set up files for the thread library
    1.15 +        SDL_LIBS="$SDL_LIBS -lsem"
    1.16          if test x$enable_threads = xyes; then
    1.17              COPY_ARCH_SRC(src/thread, linux, SDL_systhread.c)
    1.18              COPY_ARCH_SRC(src/thread, linux, SDL_systhread_c.h)
    1.19              COPY_ARCH_SRC(src/thread, linux, SDL_sysmutex.c)
    1.20              COPY_ARCH_SRC(src/thread, linux, SDL_sysmutex_c.h)
    1.21 -            COPY_ARCH_SRC(src/thread, generic, SDL_syssem.c)
    1.22 +            COPY_ARCH_SRC(src/thread, linux, SDL_syssem.c)
    1.23              COPY_ARCH_SRC(src/thread, generic, SDL_syssem_c.h)
    1.24              COPY_ARCH_SRC(src/thread, linux, SDL_syscond.c)
    1.25              COPY_ARCH_SRC(src/thread, generic, SDL_syscond_c.h)
    1.26 @@ -2247,6 +2247,7 @@
    1.27  src/cdrom/aix/Makefile
    1.28  src/cdrom/beos/Makefile
    1.29  src/cdrom/dummy/Makefile
    1.30 +src/cdrom/bsdi/Makefile
    1.31  src/cdrom/freebsd/Makefile
    1.32  src/cdrom/linux/Makefile
    1.33  src/cdrom/macos/Makefile
     2.1 --- a/docs.html	Wed Sep 12 05:11:15 2001 +0000
     2.2 +++ b/docs.html	Thu Sep 13 15:57:48 2001 +0000
     2.3 @@ -16,8 +16,10 @@
     2.4  Major changes since SDL 1.0.0:
     2.5  </H2>
     2.6  <UL>
     2.7 +	<LI> 1.2.3: Added CD-ROM support for BSD/OS (thanks Steven!)
     2.8  	<LI> 1.2.3: Added library version information to the Windows DLL
     2.9  	<LI> 1.2.3: Added initial support for EPOC/Symbian OS (thanks Hannu!)
    2.10 +	<LI> 1.2.3: Added a joystick driver for  MacOS X (thanks Max!)
    2.11  	<LI> 1.2.3: Improved MacOS X international keyboard handling
    2.12  	<LI> 1.2.3: Added support for DirectFB video on Linux (thanks Denis!)
    2.13  	<LI> 1.2.3: Fixed IDE and SCSI CD-ROM detection on BeOS (thanks Caz!)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/src/cdrom/bsdi/.cvsignore	Thu Sep 13 15:57:48 2001 +0000
     3.3 @@ -0,0 +1,6 @@
     3.4 +Makefile.in
     3.5 +Makefile
     3.6 +.libs
     3.7 +*.o
     3.8 +*.lo
     3.9 +*.la
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/cdrom/bsdi/Makefile.am	Thu Sep 13 15:57:48 2001 +0000
     4.3 @@ -0,0 +1,8 @@
     4.4 +
     4.5 +## Makefile.am for the BSDi cdrom driver for SDL
     4.6 +
     4.7 +noinst_LTLIBRARIES = libcdrom_bsdi.la
     4.8 +libcdrom_bsdi_la_SOURCES = $(SRCS)
     4.9 +
    4.10 +# The SDL cdrom driver sources
    4.11 +SRCS =  SDL_syscdrom.c
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/cdrom/bsdi/SDL_syscdrom.c	Thu Sep 13 15:57:48 2001 +0000
     5.3 @@ -0,0 +1,547 @@
     5.4 +/*
     5.5 +    SDL - Simple DirectMedia Layer
     5.6 +    Copyright (C) 1997, 1998, 1999, 2000  Sam Lantinga
     5.7 +
     5.8 +    This library is free software; you can redistribute it and/or
     5.9 +    modify it under the terms of the GNU Library General Public
    5.10 +    License as published by the Free Software Foundation; either
    5.11 +    version 2 of the License, or (at your option) any later version.
    5.12 +
    5.13 +    This library is distributed in the hope that it will be useful,
    5.14 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.15 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    5.16 +    Library General Public License for more details.
    5.17 +
    5.18 +    You should have received a copy of the GNU Library General Public
    5.19 +    License along with this library; if not, write to the Free
    5.20 +    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
    5.21 +
    5.22 +    Sam Lantinga
    5.23 +    slouken@devolution.com
    5.24 +*/
    5.25 +
    5.26 +#ifdef SAVE_RCSID
    5.27 +static char rcsid =
    5.28 + "@(#) $Id$";
    5.29 +#endif
    5.30 +
    5.31 +/*
    5.32 + * Functions for system-level CD-ROM audio control for BSD/OS 4.x
    5.33 + * This started life out as a copy of the freebsd/SDL_cdrom.c file but was
    5.34 + * heavily modified.   Works for standard (MMC) SCSI and ATAPI CDrom drives.
    5.35 + *
    5.36 + * Steven Schultz - sms@to.gd-es.com
    5.37 +*/
    5.38 +
    5.39 +#include <sys/types.h>
    5.40 +#include <stdlib.h>
    5.41 +#include <sys/stat.h>
    5.42 +#include <fcntl.h>
    5.43 +#include <stdio.h>
    5.44 +#include <string.h>
    5.45 +#include <errno.h>
    5.46 +#include <err.h>
    5.47 +#include <unistd.h>
    5.48 +#include <sys/ioctl.h>
    5.49 +#include </sys/dev/scsi/scsi.h>
    5.50 +#include </sys/dev/scsi/scsi_ioctl.h>
    5.51 +
    5.52 +#include "SDL_error.h"
    5.53 +#include "SDL_cdrom.h"
    5.54 +#include "SDL_syscdrom.h"
    5.55 +
    5.56 +/*
    5.57 + * The msf_to_frame and frame_to_msf were yanked from libcdrom and inlined
    5.58 + * here so that -lcdrom doesn't have to be dragged in for something so simple.
    5.59 +*/
    5.60 +
    5.61 +#define	FRAMES_PER_SECOND	75
    5.62 +#define	FRAMES_PER_MINUTE	(FRAMES_PER_SECOND * 60)
    5.63 +
    5.64 +int
    5.65 +msf_to_frame(int minute, int second, int frame)
    5.66 +	{
    5.67 +	return(minute * FRAMES_PER_MINUTE + second * FRAMES_PER_SECOND + frame);
    5.68 +	}
    5.69 +
    5.70 +void
    5.71 +frame_to_msf(int frame, int *minp, int *secp, int *framep)
    5.72 +	{
    5.73 +	*minp = frame / FRAMES_PER_MINUTE;
    5.74 +	*secp = (frame % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND;
    5.75 +	*framep = frame % FRAMES_PER_SECOND;
    5.76 +	}
    5.77 +
    5.78 +/* The maximum number of CD-ROM drives we'll detect */
    5.79 +#define MAX_DRIVES	16	
    5.80 +
    5.81 +/* A list of available CD-ROM drives */
    5.82 +static char *SDL_cdlist[MAX_DRIVES];
    5.83 +static dev_t SDL_cdmode[MAX_DRIVES];
    5.84 +
    5.85 +/* The system-dependent CD control functions */
    5.86 +static const char *SDL_SYS_CDName(int drive);
    5.87 +static int SDL_SYS_CDOpen(int drive);
    5.88 +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
    5.89 +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
    5.90 +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
    5.91 +static int SDL_SYS_CDPause(SDL_CD *cdrom);
    5.92 +static int SDL_SYS_CDResume(SDL_CD *cdrom);
    5.93 +static int SDL_SYS_CDStop(SDL_CD *cdrom);
    5.94 +static int SDL_SYS_CDEject(SDL_CD *cdrom);
    5.95 +static void SDL_SYS_CDClose(SDL_CD *cdrom);
    5.96 +
    5.97 +typedef	struct	scsi_cdb cdb_t;
    5.98 +
    5.99 +static int scsi_cmd(int fd,
   5.100 +		struct scsi_cdb *cdb,
   5.101 +		int cdblen, 
   5.102 +		int rw,
   5.103 +		caddr_t data,
   5.104 +		int datalen,
   5.105 +		struct scsi_user_cdb *sus)
   5.106 +	{
   5.107 +	int	scsistatus;
   5.108 +	unsigned char	*cp;
   5.109 +	struct	scsi_user_cdb suc;
   5.110 +
   5.111 +    /* safety checks */
   5.112 +	if	(!cdb) return(-1);
   5.113 +	if	(rw != SUC_READ && rw != SUC_WRITE) return(-1);
   5.114 +
   5.115 +	suc.suc_flags = rw;
   5.116 +	suc.suc_cdblen = cdblen;
   5.117 +	bcopy(cdb, suc.suc_cdb, cdblen);
   5.118 +	suc.suc_datalen = datalen;
   5.119 +	suc.suc_data = data;
   5.120 +	suc.suc_timeout = 10;		/* 10 secs max for TUR or SENSE */
   5.121 +	if	(ioctl(fd, SCSIRAWCDB, &suc) == -1)
   5.122 +		return(-11);
   5.123 +	scsistatus = suc.suc_sus.sus_status;
   5.124 +	cp = suc.suc_sus.sus_sense;
   5.125 +
   5.126 +/*
   5.127 + * If a place to copy the sense data back to has been provided then the
   5.128 + * caller is responsible for checking the errors and printing any information
   5.129 + * out if the status was not successful.
   5.130 +*/
   5.131 +	if	(scsistatus != 0 && !sus)
   5.132 +		{
   5.133 +		fprintf(stderr,"scsistatus = %x cmd = %x\n",
   5.134 +			scsistatus, cdb[0]);
   5.135 +		fprintf(stderr, "sense %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", 
   5.136 +			cp[0], cp[1], cp[2], cp[3], cp[4], cp[5],
   5.137 +			cp[6], cp[7], cp[8], cp[9], cp[10], cp[11],
   5.138 +			cp[12], cp[13], cp[14], cp[15]);
   5.139 +		return(1);
   5.140 +		}
   5.141 +	if	(sus)
   5.142 +		bcopy(&suc, sus, sizeof (struct scsi_user_cdb));
   5.143 +	if	(scsistatus)
   5.144 +		return(1);	/* Return non-zero for unsuccessful status */
   5.145 +	return(0);
   5.146 +	}
   5.147 +
   5.148 +/* request vendor brand and model */
   5.149 +unsigned char *Inquiry(int fd)
   5.150 +	{
   5.151 +	static struct scsi_cdb6 cdb = 
   5.152 +		{
   5.153 +		0x12, 
   5.154 +		0, 0, 0,
   5.155 +		56,
   5.156 +		0
   5.157 +		};
   5.158 +	static unsigned char Inqbuffer[56];
   5.159 +
   5.160 +	if	(scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, Inqbuffer, 
   5.161 +			sizeof(Inqbuffer), 0))
   5.162 +		return("\377");
   5.163 +	return(Inqbuffer);
   5.164 +	}
   5.165 +
   5.166 +#define ADD_SENSECODE 12
   5.167 +#define ADD_SC_QUALIFIER 13
   5.168 +
   5.169 +int TestForMedium(int fd)
   5.170 +	{
   5.171 +	int	sts, asc, ascq;
   5.172 +	struct	scsi_user_cdb sus;
   5.173 +	static struct scsi_cdb6 cdb =
   5.174 +		{
   5.175 +		CMD_TEST_UNIT_READY, /* command */
   5.176 +		0,	/* reserved */
   5.177 +		0,	/* reserved */
   5.178 +		0,	/* reserved */
   5.179 +		0,	/* reserved */
   5.180 +		0	/* reserved */
   5.181 +		};
   5.182 +
   5.183 +again:	sts = scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, 0, 0, &sus);
   5.184 +	asc = sus.suc_sus.sus_sense[ADD_SENSECODE];
   5.185 +	ascq = sus.suc_sus.sus_sense[ADD_SC_QUALIFIER];
   5.186 +	if	(asc == 0x3a && ascq == 0x0)	/* no medium */
   5.187 +		return(0);
   5.188 +	if	(asc == 0x28 && ascq == 0x0)	/* medium changed */
   5.189 +		goto again;
   5.190 +	if	(asc == 0x4 && ascq == 0x1 )	/* coming ready */
   5.191 +		{
   5.192 +		sleep(2);
   5.193 +		goto again;
   5.194 +		}
   5.195 +	return(1);
   5.196 +	}
   5.197 +
   5.198 +/* Check a drive to see if it is a CD-ROM */
   5.199 +static int CheckDrive(char *drive, struct stat *stbuf)
   5.200 +{
   5.201 +	int is_cd = 0, cdfd;
   5.202 +	char *p;
   5.203 +
   5.204 +	/* If it doesn't exist, return -1 */
   5.205 +	if ( stat(drive, stbuf) < 0 ) {
   5.206 +		return(-1);
   5.207 +	}
   5.208 +
   5.209 +	/* If it does exist, verify that it's an available CD-ROM */
   5.210 +	cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
   5.211 +	if ( cdfd >= 0 ) {
   5.212 +		p = Inquiry(cdfd);
   5.213 +		if (*p == TYPE_ROM)
   5.214 +			is_cd = 1;
   5.215 +		close(cdfd);
   5.216 +	}
   5.217 +	return(is_cd);
   5.218 +}
   5.219 +
   5.220 +/* Add a CD-ROM drive to our list of valid drives */
   5.221 +static void AddDrive(char *drive, struct stat *stbuf)
   5.222 +{
   5.223 +	int i;
   5.224 +
   5.225 +	if ( SDL_numcds < MAX_DRIVES ) {
   5.226 +		/* Check to make sure it's not already in our list.
   5.227 +	 	   This can happen when we see a drive via symbolic link.
   5.228 +		 */
   5.229 +		for ( i=0; i<SDL_numcds; ++i ) {
   5.230 +			if ( stbuf->st_rdev == SDL_cdmode[i] ) {
   5.231 +#ifdef DEBUG_CDROM
   5.232 +  fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
   5.233 +#endif
   5.234 +				return;
   5.235 +			}
   5.236 +		}
   5.237 +
   5.238 +		/* Add this drive to our list */
   5.239 +		i = SDL_numcds;
   5.240 +		SDL_cdlist[i] = (char *)malloc(strlen(drive)+1);
   5.241 +		if ( SDL_cdlist[i] == NULL ) {
   5.242 +			SDL_OutOfMemory();
   5.243 +			return;
   5.244 +		}
   5.245 +		strcpy(SDL_cdlist[i], drive);
   5.246 +		SDL_cdmode[i] = stbuf->st_rdev;
   5.247 +		++SDL_numcds;
   5.248 +#ifdef DEBUG_CDROM
   5.249 +  fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
   5.250 +#endif
   5.251 +	}
   5.252 +}
   5.253 +
   5.254 +int  SDL_SYS_CDInit(void)
   5.255 +{
   5.256 +	/* checklist: /dev/rsr?c */
   5.257 +	static char *checklist[] = {
   5.258 +	"?0 rsr?", NULL
   5.259 +	};
   5.260 +	char *SDLcdrom;
   5.261 +	int i, j, exists;
   5.262 +	char drive[32];
   5.263 +	struct stat stbuf;
   5.264 +
   5.265 +	/* Fill in our driver capabilities */
   5.266 +	SDL_CDcaps.Name = SDL_SYS_CDName;
   5.267 +	SDL_CDcaps.Open = SDL_SYS_CDOpen;
   5.268 +	SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
   5.269 +	SDL_CDcaps.Status = SDL_SYS_CDStatus;
   5.270 +	SDL_CDcaps.Play = SDL_SYS_CDPlay;
   5.271 +	SDL_CDcaps.Pause = SDL_SYS_CDPause;
   5.272 +	SDL_CDcaps.Resume = SDL_SYS_CDResume;
   5.273 +	SDL_CDcaps.Stop = SDL_SYS_CDStop;
   5.274 +	SDL_CDcaps.Eject = SDL_SYS_CDEject;
   5.275 +	SDL_CDcaps.Close = SDL_SYS_CDClose;
   5.276 +
   5.277 +	/* Look in the environment for our CD-ROM drive list */
   5.278 +	SDLcdrom = getenv("SDL_CDROM");	/* ':' separated list of devices */
   5.279 +	if ( SDLcdrom != NULL ) {
   5.280 +		char *cdpath, *delim;
   5.281 +		cdpath = malloc(strlen(SDLcdrom)+1);
   5.282 +		if ( cdpath != NULL ) {
   5.283 +			strcpy(cdpath, SDLcdrom);
   5.284 +			SDLcdrom = cdpath;
   5.285 +			do {
   5.286 +				delim = strchr(SDLcdrom, ':');
   5.287 +				if ( delim ) {
   5.288 +					*delim++ = '\0';
   5.289 +				}
   5.290 +				if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
   5.291 +					AddDrive(SDLcdrom, &stbuf);
   5.292 +				}
   5.293 +				if ( delim ) {
   5.294 +					SDLcdrom = delim;
   5.295 +				} else {
   5.296 +					SDLcdrom = NULL;
   5.297 +				}
   5.298 +			} while ( SDLcdrom );
   5.299 +			free(cdpath);
   5.300 +		}
   5.301 +
   5.302 +		/* If we found our drives, there's nothing left to do */
   5.303 +		if ( SDL_numcds > 0 ) {
   5.304 +			return(0);
   5.305 +		}
   5.306 +	}
   5.307 +
   5.308 +	/* Scan the system for CD-ROM drives */
   5.309 +	for ( i=0; checklist[i]; ++i ) {
   5.310 +		if ( checklist[i][0] == '?' ) {
   5.311 +			char *insert;
   5.312 +			exists = 1;
   5.313 +			for ( j=checklist[i][1]; exists; ++j ) {
   5.314 +				sprintf(drive, "/dev/%sc", &checklist[i][3]);
   5.315 +				insert = strchr(drive, '?');
   5.316 +				if ( insert != NULL ) {
   5.317 +					*insert = j;
   5.318 +				}
   5.319 +				switch (CheckDrive(drive, &stbuf)) {
   5.320 +					/* Drive exists and is a CD-ROM */
   5.321 +					case 1:
   5.322 +						AddDrive(drive, &stbuf);
   5.323 +						break;
   5.324 +					/* Drive exists, but isn't a CD-ROM */
   5.325 +					case 0:
   5.326 +						break;
   5.327 +					/* Drive doesn't exist */
   5.328 +					case -1:
   5.329 +						exists = 0;
   5.330 +						break;
   5.331 +				}
   5.332 +			}
   5.333 +		} else {
   5.334 +			sprintf(drive, "/dev/%s", checklist[i]);
   5.335 +			if ( CheckDrive(drive, &stbuf) > 0 ) {
   5.336 +				AddDrive(drive, &stbuf);
   5.337 +			}
   5.338 +		}
   5.339 +	}
   5.340 +	return(0);
   5.341 +}
   5.342 +
   5.343 +static const char *SDL_SYS_CDName(int drive)
   5.344 +{
   5.345 +	return(SDL_cdlist[drive]);
   5.346 +}
   5.347 +
   5.348 +static int SDL_SYS_CDOpen(int drive)
   5.349 +{
   5.350 +	return(open(SDL_cdlist[drive], O_RDONLY | O_NONBLOCK | O_EXCL, 0));
   5.351 +}
   5.352 +
   5.353 +static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
   5.354 +	{
   5.355 +	u_char cdb[10], buf[4], *p, *toc;
   5.356 +	struct scsi_user_cdb sus;
   5.357 +	int i, sts, first_track, last_track, ntracks, toc_size;
   5.358 +
   5.359 +	bzero(cdb, sizeof (cdb));
   5.360 +	cdb[0] = 0x43;		/* Read TOC */
   5.361 +	cdb[1] = 0x2;		/* MSF */
   5.362 +	cdb[8] = 4;		/* size TOC header */
   5.363 +	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, 4, &sus);
   5.364 +	if	(sts < 0)
   5.365 +		return(-1);
   5.366 +	first_track = buf[2];
   5.367 +	last_track = buf[3];
   5.368 +	ntracks = last_track - first_track + 1;
   5.369 +	cdrom->numtracks = ntracks;
   5.370 +	toc_size = 4 + (ntracks + 1) * 8;
   5.371 +	toc = (u_char *)malloc(toc_size);
   5.372 +	if	(toc == NULL)
   5.373 +		return(-1);
   5.374 +	bzero(cdb, sizeof (cdb));
   5.375 +	cdb[0] = 0x43;
   5.376 +	cdb[1] = 0x2;
   5.377 +	cdb[6] = first_track;
   5.378 +	cdb[7] = toc_size >> 8;
   5.379 +	cdb[8] = toc_size & 0xff;
   5.380 +	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, toc, toc_size, 
   5.381 +			&sus);
   5.382 +	if	(sts < 0)
   5.383 +		{
   5.384 +		free(toc);
   5.385 +		return(-1);
   5.386 +		}
   5.387 +
   5.388 +	for	(i = 0, p = toc+4; i <= ntracks; i++, p+= 8)
   5.389 +		{
   5.390 +		if	(i == ntracks)
   5.391 +			cdrom->track[i].id = 0xAA;	/* Leadout */
   5.392 +		else
   5.393 +			cdrom->track[i].id = first_track + i;
   5.394 +		if	(p[1] & 0x20)
   5.395 +			cdrom->track[i].type = SDL_DATA_TRACK;
   5.396 +		else
   5.397 +			cdrom->track[i].type = SDL_AUDIO_TRACK;
   5.398 +		cdrom->track[i].offset = msf_to_frame(p[5], p[6], p[7]);
   5.399 +		cdrom->track[i].length = 0;
   5.400 +		if	(i > 0)
   5.401 +			cdrom->track[i-1].length = cdrom->track[i].offset -
   5.402 +						   cdrom->track[i-1].offset;
   5.403 +		}
   5.404 +	free(toc);
   5.405 +	return(0);
   5.406 +	}
   5.407 +
   5.408 +/* Get CD-ROM status */
   5.409 +static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
   5.410 +	{
   5.411 +	CDstatus status;
   5.412 +	u_char	cdb[10], buf[16];
   5.413 +	int	sts;
   5.414 +	struct	scsi_user_cdb sus;
   5.415 +
   5.416 +	bzero(cdb, sizeof (cdb));
   5.417 +	cdb[0] = 0x42;		/* read subq */
   5.418 +	cdb[1] = 0x2;		/* MSF */
   5.419 +	cdb[2] = 0x40;		/* q channel */
   5.420 +	cdb[3] = 1;		/* current pos */
   5.421 +	cdb[7] = sizeof (buf) >> 8;
   5.422 +	cdb[8] = sizeof (buf) & 0xff;
   5.423 +	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, sizeof (buf),
   5.424 +			&sus);
   5.425 +	if	(sts < 0)
   5.426 +		return(-1);
   5.427 +	if	(sts)
   5.428 +		{
   5.429 +		if	(TestForMedium(cdrom->id) == 0)
   5.430 +			status = CD_TRAYEMPTY;
   5.431 +		else
   5.432 +			status = CD_ERROR;
   5.433 +		}
   5.434 +	else
   5.435 +		{
   5.436 +		switch	(buf[1])
   5.437 +			{
   5.438 +			case	0x11:
   5.439 +				status = CD_PLAYING;
   5.440 +				break;
   5.441 +			case	0x12:
   5.442 +				status = CD_PAUSED;
   5.443 +				break;
   5.444 +			case	0x13:
   5.445 +			case	0x14:
   5.446 +			case	0x15:
   5.447 +				status = CD_STOPPED;
   5.448 +				break;
   5.449 +			default:
   5.450 +				status = CD_ERROR;
   5.451 +				break;
   5.452 +			}
   5.453 +		}
   5.454 +	if	(position)
   5.455 +		{
   5.456 +		if	( status == CD_PLAYING || (status == CD_PAUSED) )
   5.457 +			*position = msf_to_frame(buf[9], buf[10], buf[11]);
   5.458 +		else
   5.459 +			*position = 0;
   5.460 +		}
   5.461 +	return(status);
   5.462 +	}
   5.463 +
   5.464 +/* Start play */
   5.465 +static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
   5.466 +	{
   5.467 +	u_char	cdb[10];
   5.468 +	int	sts, minute, second, frame, eminute, esecond, eframe;
   5.469 +	struct	scsi_user_cdb sus;
   5.470 +
   5.471 +	bzero(cdb, sizeof(cdb));
   5.472 +	cdb[0] = 0x47;		/* Play */
   5.473 +	frame_to_msf(start, &minute, &second, &frame);
   5.474 +	frame_to_msf(start + length, &eminute, &esecond, &eframe);
   5.475 +	cdb[3] = minute;
   5.476 +	cdb[4] = second;
   5.477 +	cdb[5] = frame;
   5.478 +	cdb[6] = eminute;
   5.479 +	cdb[7] = esecond;
   5.480 +	cdb[8] = eframe;
   5.481 +	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus);
   5.482 +	return(sts);
   5.483 +	}
   5.484 +
   5.485 +static	int
   5.486 +pauseresume(SDL_CD *cdrom, int flag)
   5.487 +	{
   5.488 +	u_char	cdb[10];
   5.489 +	struct	scsi_user_cdb sus;
   5.490 +
   5.491 +	bzero(cdb, sizeof (cdb));
   5.492 +	cdb[0] = 0x4b;
   5.493 +	cdb[8] = flag & 0x1;
   5.494 +	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus));
   5.495 +	}
   5.496 +
   5.497 +/* Pause play */
   5.498 +static int SDL_SYS_CDPause(SDL_CD *cdrom)
   5.499 +{
   5.500 +	return(pauseresume(cdrom, 0));
   5.501 +}
   5.502 +
   5.503 +/* Resume play */
   5.504 +static int SDL_SYS_CDResume(SDL_CD *cdrom)
   5.505 +{
   5.506 +	return(pauseresume(cdrom, 1));
   5.507 +}
   5.508 +
   5.509 +/* Stop play */
   5.510 +static int SDL_SYS_CDStop(SDL_CD *cdrom)
   5.511 +{
   5.512 +	u_char cdb[6];
   5.513 +	struct	scsi_user_cdb sus;
   5.514 +
   5.515 +	bzero(cdb, sizeof (cdb));
   5.516 +	cdb[0] = 0x1b;		/* stop */
   5.517 +	cdb[1] = 1;		/* immediate */
   5.518 +	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
   5.519 +}
   5.520 +
   5.521 +/* Eject the CD-ROM */
   5.522 +static int SDL_SYS_CDEject(SDL_CD *cdrom)
   5.523 +{
   5.524 +	u_char cdb[6];
   5.525 +	struct	scsi_user_cdb sus;
   5.526 +
   5.527 +	bzero(cdb, sizeof (cdb));
   5.528 +	cdb[0] = 0x1b;		/* stop */
   5.529 +	cdb[1] = 1;		/* immediate */
   5.530 +	cdb[4] = 2;		/* eject */
   5.531 +	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
   5.532 +}
   5.533 +
   5.534 +/* Close the CD-ROM handle */
   5.535 +static void SDL_SYS_CDClose(SDL_CD *cdrom)
   5.536 +	{
   5.537 +	close(cdrom->id);
   5.538 +	}
   5.539 +
   5.540 +void SDL_SYS_CDQuit(void)
   5.541 +{
   5.542 +	int i;
   5.543 +
   5.544 +	if ( SDL_numcds > 0 ) {
   5.545 +		for ( i=0; i<SDL_numcds; ++i ) {
   5.546 +			free(SDL_cdlist[i]);
   5.547 +			}
   5.548 +		}
   5.549 +	SDL_numcds = 0;
   5.550 +}