146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    SDL - Simple DirectMedia Layer
346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Copyright (C) 1997-2006 Sam Lantinga
446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is free software; you can redistribute it and/or
646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    modify it under the terms of the GNU Lesser General Public
746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License as published by the Free Software Foundation; either
846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    version 2.1 of the License, or (at your option) any later version.
946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    This library is distributed in the hope that it will be useful,
1146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    but WITHOUT ANY WARRANTY; without even the implied warranty of
1246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
1346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Lesser General Public License for more details.
1446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    You should have received a copy of the GNU Lesser General Public
1646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    License along with this library; if not, write to the Free Software
1746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
1946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    Sam Lantinga
2046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    slouken@libsdl.org
2146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
2246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_config.h"
2346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef SDL_CDROM_BSDI
2546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
2646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
2746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Functions for system-level CD-ROM audio control for BSD/OS 4.x
2846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * This started life out as a copy of the freebsd/SDL_cdrom.c file but was
2946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * heavily modified.   Works for standard (MMC) SCSI and ATAPI CDrom drives.
3046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner *
3146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * Steven Schultz - sms@to.gd-es.com
3246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
3346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
3446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/types.h>
3546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/stat.h>
3646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <fcntl.h>
3746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <err.h>
3846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <unistd.h>
3946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include <sys/ioctl.h>
4046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include </sys/dev/scsi/scsi.h>
4146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include </sys/dev/scsi/scsi_ioctl.h>
4246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "SDL_cdrom.h"
4446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#include "../SDL_syscdrom.h"
4546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
4646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
4746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * The msf_to_frame and frame_to_msf were yanked from libcdrom and inlined
4846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * here so that -lcdrom doesn't have to be dragged in for something so simple.
4946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
5046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define	FRAMES_PER_SECOND	75
5246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define	FRAMES_PER_MINUTE	(FRAMES_PER_SECOND * 60)
5346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
5446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint
5546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnermsf_to_frame(int minute, int second, int frame)
5646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
5746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(minute * FRAMES_PER_MINUTE + second * FRAMES_PER_SECOND + frame);
5846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
5946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid
6146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerframe_to_msf(int frame, int *minp, int *secp, int *framep)
6246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
6346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	*minp = frame / FRAMES_PER_MINUTE;
6446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	*secp = (frame % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND;
6546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	*framep = frame % FRAMES_PER_SECOND;
6646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
6746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
6846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The maximum number of CD-ROM drives we'll detect */
6946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define MAX_DRIVES	16
7046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* A list of available CD-ROM drives */
7246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic char *SDL_cdlist[MAX_DRIVES];
7346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic dev_t SDL_cdmode[MAX_DRIVES];
7446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
7546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* The system-dependent CD control functions */
7646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic const char *SDL_SYS_CDName(int drive);
7746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDOpen(int drive);
7846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
7946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
8046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
8146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDPause(SDL_CD *cdrom);
8246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDResume(SDL_CD *cdrom);
8346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDStop(SDL_CD *cdrom);
8446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDEject(SDL_CD *cdrom);
8546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void SDL_SYS_CDClose(SDL_CD *cdrom);
8646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8746be48730333120a7b939116cef075e61c12c703David 'Digit' Turnertypedef	struct	scsi_cdb cdb_t;
8846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
8946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int scsi_cmd(int fd,
9046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		struct scsi_cdb *cdb,
9146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int cdblen,
9246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int rw,
9346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		caddr_t data,
9446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		int datalen,
9546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		struct scsi_user_cdb *sus)
9646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
9746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int	scsistatus;
9846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	unsigned char	*cp;
9946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct	scsi_user_cdb suc;
10046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner    /* safety checks */
10246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(!cdb) return(-1);
10346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(rw != SUC_READ && rw != SUC_WRITE) return(-1);
10446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
10546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	suc.suc_flags = rw;
10646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	suc.suc_cdblen = cdblen;
10746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	bcopy(cdb, suc.suc_cdb, cdblen);
10846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	suc.suc_datalen = datalen;
10946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	suc.suc_data = data;
11046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	suc.suc_timeout = 10;		/* 10 secs max for TUR or SENSE */
11146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(ioctl(fd, SCSIRAWCDB, &suc) == -1)
11246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-11);
11346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	scsistatus = suc.suc_sus.sus_status;
11446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cp = suc.suc_sus.sus_sense;
11546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
11646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/*
11746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * If a place to copy the sense data back to has been provided then the
11846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * caller is responsible for checking the errors and printing any information
11946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner * out if the status was not successful.
12046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner*/
12146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(scsistatus != 0 && !sus)
12246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
12346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		fprintf(stderr,"scsistatus = %x cmd = %x\n",
12446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			scsistatus, cdb[0]);
12546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		fprintf(stderr, "sense %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
12646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cp[0], cp[1], cp[2], cp[3], cp[4], cp[5],
12746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cp[6], cp[7], cp[8], cp[9], cp[10], cp[11],
12846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cp[12], cp[13], cp[14], cp[15]);
12946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(1);
13046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
13146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(sus)
13246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		bcopy(&suc, sus, sizeof (struct scsi_user_cdb));
13346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(scsistatus)
13446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(1);	/* Return non-zero for unsuccessful status */
13546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(0);
13646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
13746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
13846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* request vendor brand and model */
13946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerunsigned char *Inquiry(int fd)
14046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
14146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	static struct scsi_cdb6 cdb =
14246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
14346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		0x12,
14446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		0, 0, 0,
14546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		56,
14646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		0
14746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		};
14846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	static unsigned char Inqbuffer[56];
14946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, Inqbuffer,
15146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			sizeof(Inqbuffer), 0))
15246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return("\377");
15346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(Inqbuffer);
15446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
15546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ADD_SENSECODE 12
15746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#define ADD_SC_QUALIFIER 13
15846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
15946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint TestForMedium(int fd)
16046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
16146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int	sts, asc, ascq;
16246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct	scsi_user_cdb sus;
16346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	static struct scsi_cdb6 cdb =
16446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
16546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		CMD_TEST_UNIT_READY, /* command */
16646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		0,	/* reserved */
16746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		0,	/* reserved */
16846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		0,	/* reserved */
16946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		0,	/* reserved */
17046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		0	/* reserved */
17146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		};
17246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
17346be48730333120a7b939116cef075e61c12c703David 'Digit' Turneragain:	sts = scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, 0, 0, &sus);
17446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	asc = sus.suc_sus.sus_sense[ADD_SENSECODE];
17546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ascq = sus.suc_sus.sus_sense[ADD_SC_QUALIFIER];
17646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(asc == 0x3a && ascq == 0x0)	/* no medium */
17746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(0);
17846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(asc == 0x28 && ascq == 0x0)	/* medium changed */
17946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		goto again;
18046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(asc == 0x4 && ascq == 0x1 )	/* coming ready */
18146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
18246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		sleep(2);
18346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		goto again;
18446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
18546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(1);
18646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
18746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
18846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Check a drive to see if it is a CD-ROM */
18946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int CheckDrive(char *drive, struct stat *stbuf)
19046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
19146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int is_cd = 0, cdfd;
19246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	char *p;
19346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
19446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* If it doesn't exist, return -1 */
19546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( stat(drive, stbuf) < 0 ) {
19646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
19746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
19846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
19946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* If it does exist, verify that it's an available CD-ROM */
20046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
20146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( cdfd >= 0 ) {
20246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		p = Inquiry(cdfd);
20346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if (*p == TYPE_ROM)
20446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			is_cd = 1;
20546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		close(cdfd);
20646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
20746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(is_cd);
20846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
20946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
21046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Add a CD-ROM drive to our list of valid drives */
21146be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void AddDrive(char *drive, struct stat *stbuf)
21246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
21346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
21446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
21546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_numcds < MAX_DRIVES ) {
21646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Check to make sure it's not already in our list.
21746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	 	   This can happen when we see a drive via symbolic link.
21846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		 */
21946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for ( i=0; i<SDL_numcds; ++i ) {
22046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( stbuf->st_rdev == SDL_cdmode[i] ) {
22146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_CDROM
22246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
22346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
22446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				return;
22546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
22646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
22746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
22846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* Add this drive to our list */
22946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		i = SDL_numcds;
23046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_cdlist[i] = SDL_strdup(drive);
23146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( SDL_cdlist[i] == NULL ) {
23246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_OutOfMemory();
23346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return;
23446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
23546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_cdmode[i] = stbuf->st_rdev;
23646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		++SDL_numcds;
23746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#ifdef DEBUG_CDROM
23846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner  fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
23946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif
24046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
24146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
24246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
24346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerint  SDL_SYS_CDInit(void)
24446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
24546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* checklist: /dev/rsr?c */
24646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	static char *checklist[] = {
24746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	"?0 rsr?", NULL
24846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	};
24946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	char *SDLcdrom;
25046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i, j, exists;
25146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	char drive[32];
25246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct stat stbuf;
25346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
25446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Fill in our driver capabilities */
25546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Name = SDL_SYS_CDName;
25646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Open = SDL_SYS_CDOpen;
25746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
25846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Status = SDL_SYS_CDStatus;
25946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Play = SDL_SYS_CDPlay;
26046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Pause = SDL_SYS_CDPause;
26146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Resume = SDL_SYS_CDResume;
26246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Stop = SDL_SYS_CDStop;
26346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Eject = SDL_SYS_CDEject;
26446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_CDcaps.Close = SDL_SYS_CDClose;
26546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
26646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Look in the environment for our CD-ROM drive list */
26746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDLcdrom = SDL_getenv("SDL_CDROM");	/* ':' separated list of devices */
26846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDLcdrom != NULL ) {
26946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		char *cdpath, *delim;
27046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		size_t len = SDL_strlen(SDLcdrom)+1;
27146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		cdpath = SDL_stack_alloc(char, len);
27246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( cdpath != NULL ) {
27346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_strlcpy(cdpath, SDLcdrom, len);
27446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDLcdrom = cdpath;
27546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			do {
27646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				delim = SDL_strchr(SDLcdrom, ':');
27746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( delim ) {
27846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					*delim++ = '\0';
27946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
28046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
28146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					AddDrive(SDLcdrom, &stbuf);
28246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
28346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( delim ) {
28446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					SDLcdrom = delim;
28546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				} else {
28646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					SDLcdrom = NULL;
28746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
28846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			} while ( SDLcdrom );
28946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_stack_free(cdpath);
29046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
29146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		/* If we found our drives, there's nothing left to do */
29346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( SDL_numcds > 0 ) {
29446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			return(0);
29546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
29646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
29746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
29846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	/* Scan the system for CD-ROM drives */
29946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for ( i=0; checklist[i]; ++i ) {
30046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if ( checklist[i][0] == '?' ) {
30146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			char *insert;
30246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			exists = 1;
30346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			for ( j=checklist[i][1]; exists; ++j ) {
30446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%sc", &checklist[i][3]);
30546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				insert = SDL_strchr(drive, '?');
30646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				if ( insert != NULL ) {
30746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					*insert = j;
30846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
30946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				switch (CheckDrive(drive, &stbuf)) {
31046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					/* Drive exists and is a CD-ROM */
31146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case 1:
31246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						AddDrive(drive, &stbuf);
31346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
31446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					/* Drive exists, but isn't a CD-ROM */
31546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case 0:
31646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
31746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					/* Drive doesn't exist */
31846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner					case -1:
31946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						exists = 0;
32046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						break;
32146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				}
32246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
32346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		} else {
32446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]);
32546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			if ( CheckDrive(drive, &stbuf) > 0 ) {
32646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				AddDrive(drive, &stbuf);
32746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
32846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
32946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
33046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(0);
33146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
33246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
33346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic const char *SDL_SYS_CDName(int drive)
33446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
33546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(SDL_cdlist[drive]);
33646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
33746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
33846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDOpen(int drive)
33946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
34046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(open(SDL_cdlist[drive], O_RDONLY | O_NONBLOCK | O_EXCL, 0));
34146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
34246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
34346be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
34446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
34546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	u_char cdb[10], buf[4], *p, *toc;
34646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct scsi_user_cdb sus;
34746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i, sts, first_track, last_track, ntracks, toc_size;
34846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
34946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	bzero(cdb, sizeof (cdb));
35046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[0] = 0x43;		/* Read TOC */
35146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[1] = 0x2;		/* MSF */
35246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[8] = 4;		/* size TOC header */
35346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, 4, &sus);
35446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(sts < 0)
35546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
35646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	first_track = buf[2];
35746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	last_track = buf[3];
35846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	ntracks = last_track - first_track + 1;
35946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdrom->numtracks = ntracks;
36046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	toc_size = 4 + (ntracks + 1) * 8;
36146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	toc = (u_char *)SDL_malloc(toc_size);
36246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(toc == NULL)
36346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
36446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	bzero(cdb, sizeof (cdb));
36546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[0] = 0x43;
36646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[1] = 0x2;
36746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[6] = first_track;
36846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[7] = toc_size >> 8;
36946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[8] = toc_size & 0xff;
37046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, toc, toc_size,
37146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			&sus);
37246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(sts < 0)
37346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
37446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		SDL_free(toc);
37546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
37646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
37746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
37846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	for	(i = 0, p = toc+4; i <= ntracks; i++, p+= 8)
37946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
38046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if	(i == ntracks)
38146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i].id = 0xAA;	/* Leadout */
38246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		else
38346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i].id = first_track + i;
38446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if	(p[1] & 0x20)
38546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i].type = SDL_DATA_TRACK;
38646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		else
38746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i].type = SDL_AUDIO_TRACK;
38846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		cdrom->track[i].offset = msf_to_frame(p[5], p[6], p[7]);
38946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		cdrom->track[i].length = 0;
39046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if	(i > 0)
39146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			cdrom->track[i-1].length = cdrom->track[i].offset -
39246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner						   cdrom->track[i-1].offset;
39346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
39446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_free(toc);
39546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(0);
39646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
39746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
39846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Get CD-ROM status */
39946be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
40046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
40146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	CDstatus status;
40246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	u_char	cdb[10], buf[16];
40346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int	sts;
40446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct	scsi_user_cdb sus;
40546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
40646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	bzero(cdb, sizeof (cdb));
40746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[0] = 0x42;		/* read subq */
40846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[1] = 0x2;		/* MSF */
40946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[2] = 0x40;		/* q channel */
41046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[3] = 1;		/* current pos */
41146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[7] = sizeof (buf) >> 8;
41246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[8] = sizeof (buf) & 0xff;
41346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, sizeof (buf),
41446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			&sus);
41546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(sts < 0)
41646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		return(-1);
41746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(sts)
41846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
41946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if	(TestForMedium(cdrom->id) == 0)
42046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			status = CD_TRAYEMPTY;
42146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		else
42246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			status = CD_ERROR;
42346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
42446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	else
42546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
42646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		switch	(buf[1])
42746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			{
42846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case	0x11:
42946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_PLAYING;
43046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
43146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case	0x12:
43246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_PAUSED;
43346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
43446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case	0x13:
43546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case	0x14:
43646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			case	0x15:
43746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_STOPPED;
43846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
43946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			default:
44046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				status = CD_ERROR;
44146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner				break;
44246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
44346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
44446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if	(position)
44546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		{
44646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		if	( status == CD_PLAYING || (status == CD_PAUSED) )
44746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			*position = msf_to_frame(buf[9], buf[10], buf[11]);
44846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		else
44946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			*position = 0;
45046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
45146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(status);
45246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
45346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
45446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Start play */
45546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
45646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
45746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	u_char	cdb[10];
45846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int	sts, minute, second, frame, eminute, esecond, eframe;
45946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct	scsi_user_cdb sus;
46046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
46146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	bzero(cdb, sizeof(cdb));
46246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[0] = 0x47;		/* Play */
46346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	frame_to_msf(start, &minute, &second, &frame);
46446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	frame_to_msf(start + length, &eminute, &esecond, &eframe);
46546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[3] = minute;
46646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[4] = second;
46746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[5] = frame;
46846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[6] = eminute;
46946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[7] = esecond;
47046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[8] = eframe;
47146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus);
47246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(sts);
47346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
47446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
47546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic	int
47646be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerpauseresume(SDL_CD *cdrom, int flag)
47746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
47846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	u_char	cdb[10];
47946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct	scsi_user_cdb sus;
48046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
48146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	bzero(cdb, sizeof (cdb));
48246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[0] = 0x4b;
48346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[8] = flag & 0x1;
48446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus));
48546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
48646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
48746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Pause play */
48846be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDPause(SDL_CD *cdrom)
48946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
49046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(pauseresume(cdrom, 0));
49146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
49246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
49346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Resume play */
49446be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDResume(SDL_CD *cdrom)
49546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
49646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(pauseresume(cdrom, 1));
49746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
49846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
49946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Stop play */
50046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDStop(SDL_CD *cdrom)
50146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
50246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	u_char cdb[6];
50346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct	scsi_user_cdb sus;
50446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
50546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	bzero(cdb, sizeof (cdb));
50646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[0] = 0x1b;		/* stop */
50746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[1] = 1;		/* immediate */
50846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
50946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
51046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
51146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Eject the CD-ROM */
51246be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic int SDL_SYS_CDEject(SDL_CD *cdrom)
51346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
51446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	u_char cdb[6];
51546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	struct	scsi_user_cdb sus;
51646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
51746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	bzero(cdb, sizeof (cdb));
51846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[0] = 0x1b;		/* stop */
51946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[1] = 1;		/* immediate */
52046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	cdb[4] = 2;		/* eject */
52146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
52246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
52346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
52446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner/* Close the CD-ROM handle */
52546be48730333120a7b939116cef075e61c12c703David 'Digit' Turnerstatic void SDL_SYS_CDClose(SDL_CD *cdrom)
52646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	{
52746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	close(cdrom->id);
52846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	}
52946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
53046be48730333120a7b939116cef075e61c12c703David 'Digit' Turnervoid SDL_SYS_CDQuit(void)
53146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner{
53246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	int i;
53346be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
53446be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	if ( SDL_numcds > 0 ) {
53546be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		for ( i=0; i<SDL_numcds; ++i ) {
53646be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			SDL_free(SDL_cdlist[i]);
53746be48730333120a7b939116cef075e61c12c703David 'Digit' Turner			}
53846be48730333120a7b939116cef075e61c12c703David 'Digit' Turner		}
53946be48730333120a7b939116cef075e61c12c703David 'Digit' Turner	SDL_numcds = 0;
54046be48730333120a7b939116cef075e61c12c703David 'Digit' Turner}
54146be48730333120a7b939116cef075e61c12c703David 'Digit' Turner
54246be48730333120a7b939116cef075e61c12c703David 'Digit' Turner#endif /* SDL_CDROM_BSDI */
543