src/cdrom/bsdi/SDL_syscdrom.c
changeset 1895 c121d94672cb
parent 1635 92947e3a18db
child 2669 e27bdcc80744
equal deleted inserted replaced
1894:c69cee13dd76 1895:c121d94672cb
    51 #define	FRAMES_PER_SECOND	75
    51 #define	FRAMES_PER_SECOND	75
    52 #define	FRAMES_PER_MINUTE	(FRAMES_PER_SECOND * 60)
    52 #define	FRAMES_PER_MINUTE	(FRAMES_PER_SECOND * 60)
    53 
    53 
    54 int
    54 int
    55 msf_to_frame(int minute, int second, int frame)
    55 msf_to_frame(int minute, int second, int frame)
    56 	{
    56 {
    57 	return(minute * FRAMES_PER_MINUTE + second * FRAMES_PER_SECOND + frame);
    57     return (minute * FRAMES_PER_MINUTE + second * FRAMES_PER_SECOND + frame);
    58 	}
    58 }
    59 
    59 
    60 void
    60 void
    61 frame_to_msf(int frame, int *minp, int *secp, int *framep)
    61 frame_to_msf(int frame, int *minp, int *secp, int *framep)
    62 	{
    62 {
    63 	*minp = frame / FRAMES_PER_MINUTE;
    63     *minp = frame / FRAMES_PER_MINUTE;
    64 	*secp = (frame % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND;
    64     *secp = (frame % FRAMES_PER_MINUTE) / FRAMES_PER_SECOND;
    65 	*framep = frame % FRAMES_PER_SECOND;
    65     *framep = frame % FRAMES_PER_SECOND;
    66 	}
    66 }
    67 
    67 
    68 /* The maximum number of CD-ROM drives we'll detect */
    68 /* The maximum number of CD-ROM drives we'll detect */
    69 #define MAX_DRIVES	16	
    69 #define MAX_DRIVES	16
    70 
    70 
    71 /* A list of available CD-ROM drives */
    71 /* A list of available CD-ROM drives */
    72 static char *SDL_cdlist[MAX_DRIVES];
    72 static char *SDL_cdlist[MAX_DRIVES];
    73 static dev_t SDL_cdmode[MAX_DRIVES];
    73 static dev_t SDL_cdmode[MAX_DRIVES];
    74 
    74 
    75 /* The system-dependent CD control functions */
    75 /* The system-dependent CD control functions */
    76 static const char *SDL_SYS_CDName(int drive);
    76 static const char *SDL_SYS_CDName(int drive);
    77 static int SDL_SYS_CDOpen(int drive);
    77 static int SDL_SYS_CDOpen(int drive);
    78 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom);
    78 static int SDL_SYS_CDGetTOC(SDL_CD * cdrom);
    79 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position);
    79 static CDstatus SDL_SYS_CDStatus(SDL_CD * cdrom, int *position);
    80 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length);
    80 static int SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length);
    81 static int SDL_SYS_CDPause(SDL_CD *cdrom);
    81 static int SDL_SYS_CDPause(SDL_CD * cdrom);
    82 static int SDL_SYS_CDResume(SDL_CD *cdrom);
    82 static int SDL_SYS_CDResume(SDL_CD * cdrom);
    83 static int SDL_SYS_CDStop(SDL_CD *cdrom);
    83 static int SDL_SYS_CDStop(SDL_CD * cdrom);
    84 static int SDL_SYS_CDEject(SDL_CD *cdrom);
    84 static int SDL_SYS_CDEject(SDL_CD * cdrom);
    85 static void SDL_SYS_CDClose(SDL_CD *cdrom);
    85 static void SDL_SYS_CDClose(SDL_CD * cdrom);
    86 
    86 
    87 typedef	struct	scsi_cdb cdb_t;
    87 typedef struct scsi_cdb cdb_t;
    88 
    88 
    89 static int scsi_cmd(int fd,
    89 static int
    90 		struct scsi_cdb *cdb,
    90 scsi_cmd(int fd,
    91 		int cdblen, 
    91          struct scsi_cdb *cdb,
    92 		int rw,
    92          int cdblen,
    93 		caddr_t data,
    93          int rw, caddr_t data, int datalen, struct scsi_user_cdb *sus)
    94 		int datalen,
    94 {
    95 		struct scsi_user_cdb *sus)
    95     int scsistatus;
    96 	{
    96     unsigned char *cp;
    97 	int	scsistatus;
    97     struct scsi_user_cdb suc;
    98 	unsigned char	*cp;
       
    99 	struct	scsi_user_cdb suc;
       
   100 
    98 
   101     /* safety checks */
    99     /* safety checks */
   102 	if	(!cdb) return(-1);
   100     if (!cdb)
   103 	if	(rw != SUC_READ && rw != SUC_WRITE) return(-1);
   101         return (-1);
   104 
   102     if (rw != SUC_READ && rw != SUC_WRITE)
   105 	suc.suc_flags = rw;
   103         return (-1);
   106 	suc.suc_cdblen = cdblen;
   104 
   107 	bcopy(cdb, suc.suc_cdb, cdblen);
   105     suc.suc_flags = rw;
   108 	suc.suc_datalen = datalen;
   106     suc.suc_cdblen = cdblen;
   109 	suc.suc_data = data;
   107     bcopy(cdb, suc.suc_cdb, cdblen);
   110 	suc.suc_timeout = 10;		/* 10 secs max for TUR or SENSE */
   108     suc.suc_datalen = datalen;
   111 	if	(ioctl(fd, SCSIRAWCDB, &suc) == -1)
   109     suc.suc_data = data;
   112 		return(-11);
   110     suc.suc_timeout = 10;       /* 10 secs max for TUR or SENSE */
   113 	scsistatus = suc.suc_sus.sus_status;
   111     if (ioctl(fd, SCSIRAWCDB, &suc) == -1)
   114 	cp = suc.suc_sus.sus_sense;
   112         return (-11);
       
   113     scsistatus = suc.suc_sus.sus_status;
       
   114     cp = suc.suc_sus.sus_sense;
   115 
   115 
   116 /*
   116 /*
   117  * If a place to copy the sense data back to has been provided then the
   117  * If a place to copy the sense data back to has been provided then the
   118  * caller is responsible for checking the errors and printing any information
   118  * caller is responsible for checking the errors and printing any information
   119  * out if the status was not successful.
   119  * out if the status was not successful.
   120 */
   120 */
   121 	if	(scsistatus != 0 && !sus)
   121     if (scsistatus != 0 && !sus) {
   122 		{
   122         fprintf(stderr, "scsistatus = %x cmd = %x\n", scsistatus, cdb[0]);
   123 		fprintf(stderr,"scsistatus = %x cmd = %x\n",
   123         fprintf(stderr,
   124 			scsistatus, cdb[0]);
   124                 "sense %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n",
   125 		fprintf(stderr, "sense %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n", 
   125                 cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7],
   126 			cp[0], cp[1], cp[2], cp[3], cp[4], cp[5],
   126                 cp[8], cp[9], cp[10], cp[11], cp[12], cp[13], cp[14], cp[15]);
   127 			cp[6], cp[7], cp[8], cp[9], cp[10], cp[11],
   127         return (1);
   128 			cp[12], cp[13], cp[14], cp[15]);
   128     }
   129 		return(1);
   129     if (sus)
   130 		}
   130         bcopy(&suc, sus, sizeof(struct scsi_user_cdb));
   131 	if	(sus)
   131     if (scsistatus)
   132 		bcopy(&suc, sus, sizeof (struct scsi_user_cdb));
   132         return (1);             /* Return non-zero for unsuccessful status */
   133 	if	(scsistatus)
   133     return (0);
   134 		return(1);	/* Return non-zero for unsuccessful status */
   134 }
   135 	return(0);
       
   136 	}
       
   137 
   135 
   138 /* request vendor brand and model */
   136 /* request vendor brand and model */
   139 unsigned char *Inquiry(int fd)
   137 unsigned char *
   140 	{
   138 Inquiry(int fd)
   141 	static struct scsi_cdb6 cdb = 
   139 {
   142 		{
   140     static struct scsi_cdb6 cdb = {
   143 		0x12, 
   141         0x12,
   144 		0, 0, 0,
   142         0, 0, 0,
   145 		56,
   143         56,
   146 		0
   144         0
   147 		};
   145     };
   148 	static unsigned char Inqbuffer[56];
   146     static unsigned char Inqbuffer[56];
   149 
   147 
   150 	if	(scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, Inqbuffer, 
   148     if (scsi_cmd(fd, (cdb_t *) & cdb, 6, SUC_READ, Inqbuffer,
   151 			sizeof(Inqbuffer), 0))
   149                  sizeof(Inqbuffer), 0))
   152 		return("\377");
   150         return ("\377");
   153 	return(Inqbuffer);
   151     return (Inqbuffer);
   154 	}
   152 }
   155 
   153 
   156 #define ADD_SENSECODE 12
   154 #define ADD_SENSECODE 12
   157 #define ADD_SC_QUALIFIER 13
   155 #define ADD_SC_QUALIFIER 13
   158 
   156 
   159 int TestForMedium(int fd)
   157 int
   160 	{
   158 TestForMedium(int fd)
   161 	int	sts, asc, ascq;
   159 {
   162 	struct	scsi_user_cdb sus;
   160     int sts, asc, ascq;
   163 	static struct scsi_cdb6 cdb =
   161     struct scsi_user_cdb sus;
   164 		{
   162     static struct scsi_cdb6 cdb = {
   165 		CMD_TEST_UNIT_READY, /* command */
   163         CMD_TEST_UNIT_READY,    /* command */
   166 		0,	/* reserved */
   164         0,                      /* reserved */
   167 		0,	/* reserved */
   165         0,                      /* reserved */
   168 		0,	/* reserved */
   166         0,                      /* reserved */
   169 		0,	/* reserved */
   167         0,                      /* reserved */
   170 		0	/* reserved */
   168         0                       /* reserved */
   171 		};
   169     };
   172 
   170 
   173 again:	sts = scsi_cmd(fd, (cdb_t *)&cdb, 6, SUC_READ, 0, 0, &sus);
   171   again:sts = scsi_cmd(fd, (cdb_t *) & cdb, 6, SUC_READ, 0, 0, &sus);
   174 	asc = sus.suc_sus.sus_sense[ADD_SENSECODE];
   172     asc = sus.suc_sus.sus_sense[ADD_SENSECODE];
   175 	ascq = sus.suc_sus.sus_sense[ADD_SC_QUALIFIER];
   173     ascq = sus.suc_sus.sus_sense[ADD_SC_QUALIFIER];
   176 	if	(asc == 0x3a && ascq == 0x0)	/* no medium */
   174     if (asc == 0x3a && ascq == 0x0)     /* no medium */
   177 		return(0);
   175         return (0);
   178 	if	(asc == 0x28 && ascq == 0x0)	/* medium changed */
   176     if (asc == 0x28 && ascq == 0x0)     /* medium changed */
   179 		goto again;
   177         goto again;
   180 	if	(asc == 0x4 && ascq == 0x1 )	/* coming ready */
   178     if (asc == 0x4 && ascq == 0x1) {    /* coming ready */
   181 		{
   179         sleep(2);
   182 		sleep(2);
   180         goto again;
   183 		goto again;
   181     }
   184 		}
   182     return (1);
   185 	return(1);
   183 }
   186 	}
       
   187 
   184 
   188 /* Check a drive to see if it is a CD-ROM */
   185 /* Check a drive to see if it is a CD-ROM */
   189 static int CheckDrive(char *drive, struct stat *stbuf)
   186 static int
   190 {
   187 CheckDrive(char *drive, struct stat *stbuf)
   191 	int is_cd = 0, cdfd;
   188 {
   192 	char *p;
   189     int is_cd = 0, cdfd;
   193 
   190     char *p;
   194 	/* If it doesn't exist, return -1 */
   191 
   195 	if ( stat(drive, stbuf) < 0 ) {
   192     /* If it doesn't exist, return -1 */
   196 		return(-1);
   193     if (stat(drive, stbuf) < 0) {
   197 	}
   194         return (-1);
   198 
   195     }
   199 	/* If it does exist, verify that it's an available CD-ROM */
   196 
   200 	cdfd = open(drive, (O_RDONLY|O_EXCL|O_NONBLOCK), 0);
   197     /* If it does exist, verify that it's an available CD-ROM */
   201 	if ( cdfd >= 0 ) {
   198     cdfd = open(drive, (O_RDONLY | O_EXCL | O_NONBLOCK), 0);
   202 		p = Inquiry(cdfd);
   199     if (cdfd >= 0) {
   203 		if (*p == TYPE_ROM)
   200         p = Inquiry(cdfd);
   204 			is_cd = 1;
   201         if (*p == TYPE_ROM)
   205 		close(cdfd);
   202             is_cd = 1;
   206 	}
   203         close(cdfd);
   207 	return(is_cd);
   204     }
       
   205     return (is_cd);
   208 }
   206 }
   209 
   207 
   210 /* Add a CD-ROM drive to our list of valid drives */
   208 /* Add a CD-ROM drive to our list of valid drives */
   211 static void AddDrive(char *drive, struct stat *stbuf)
   209 static void
   212 {
   210 AddDrive(char *drive, struct stat *stbuf)
   213 	int i;
   211 {
   214 
   212     int i;
   215 	if ( SDL_numcds < MAX_DRIVES ) {
   213 
   216 		/* Check to make sure it's not already in our list.
   214     if (SDL_numcds < MAX_DRIVES) {
   217 	 	   This can happen when we see a drive via symbolic link.
   215         /* Check to make sure it's not already in our list.
   218 		 */
   216            This can happen when we see a drive via symbolic link.
   219 		for ( i=0; i<SDL_numcds; ++i ) {
   217          */
   220 			if ( stbuf->st_rdev == SDL_cdmode[i] ) {
   218         for (i = 0; i < SDL_numcds; ++i) {
       
   219             if (stbuf->st_rdev == SDL_cdmode[i]) {
   221 #ifdef DEBUG_CDROM
   220 #ifdef DEBUG_CDROM
   222   fprintf(stderr, "Duplicate drive detected: %s == %s\n", drive, SDL_cdlist[i]);
   221                 fprintf(stderr, "Duplicate drive detected: %s == %s\n",
       
   222                         drive, SDL_cdlist[i]);
   223 #endif
   223 #endif
   224 				return;
   224                 return;
   225 			}
   225             }
   226 		}
   226         }
   227 
   227 
   228 		/* Add this drive to our list */
   228         /* Add this drive to our list */
   229 		i = SDL_numcds;
   229         i = SDL_numcds;
   230 		SDL_cdlist[i] = SDL_strdup(drive);
   230         SDL_cdlist[i] = SDL_strdup(drive);
   231 		if ( SDL_cdlist[i] == NULL ) {
   231         if (SDL_cdlist[i] == NULL) {
   232 			SDL_OutOfMemory();
   232             SDL_OutOfMemory();
   233 			return;
   233             return;
   234 		}
   234         }
   235 		SDL_cdmode[i] = stbuf->st_rdev;
   235         SDL_cdmode[i] = stbuf->st_rdev;
   236 		++SDL_numcds;
   236         ++SDL_numcds;
   237 #ifdef DEBUG_CDROM
   237 #ifdef DEBUG_CDROM
   238   fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
   238         fprintf(stderr, "Added CD-ROM drive: %s\n", drive);
   239 #endif
   239 #endif
   240 	}
   240     }
   241 }
   241 }
   242 
   242 
   243 int  SDL_SYS_CDInit(void)
   243 int
   244 {
   244 SDL_SYS_CDInit(void)
   245 	/* checklist: /dev/rsr?c */
   245 {
   246 	static char *checklist[] = {
   246     /* checklist: /dev/rsr?c */
   247 	"?0 rsr?", NULL
   247     static char *checklist[] = {
   248 	};
   248         "?0 rsr?", NULL
   249 	char *SDLcdrom;
   249     };
   250 	int i, j, exists;
   250     char *SDLcdrom;
   251 	char drive[32];
   251     int i, j, exists;
   252 	struct stat stbuf;
   252     char drive[32];
   253 
   253     struct stat stbuf;
   254 	/* Fill in our driver capabilities */
   254 
   255 	SDL_CDcaps.Name = SDL_SYS_CDName;
   255     /* Fill in our driver capabilities */
   256 	SDL_CDcaps.Open = SDL_SYS_CDOpen;
   256     SDL_CDcaps.Name = SDL_SYS_CDName;
   257 	SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
   257     SDL_CDcaps.Open = SDL_SYS_CDOpen;
   258 	SDL_CDcaps.Status = SDL_SYS_CDStatus;
   258     SDL_CDcaps.GetTOC = SDL_SYS_CDGetTOC;
   259 	SDL_CDcaps.Play = SDL_SYS_CDPlay;
   259     SDL_CDcaps.Status = SDL_SYS_CDStatus;
   260 	SDL_CDcaps.Pause = SDL_SYS_CDPause;
   260     SDL_CDcaps.Play = SDL_SYS_CDPlay;
   261 	SDL_CDcaps.Resume = SDL_SYS_CDResume;
   261     SDL_CDcaps.Pause = SDL_SYS_CDPause;
   262 	SDL_CDcaps.Stop = SDL_SYS_CDStop;
   262     SDL_CDcaps.Resume = SDL_SYS_CDResume;
   263 	SDL_CDcaps.Eject = SDL_SYS_CDEject;
   263     SDL_CDcaps.Stop = SDL_SYS_CDStop;
   264 	SDL_CDcaps.Close = SDL_SYS_CDClose;
   264     SDL_CDcaps.Eject = SDL_SYS_CDEject;
   265 
   265     SDL_CDcaps.Close = SDL_SYS_CDClose;
   266 	/* Look in the environment for our CD-ROM drive list */
   266 
   267 	SDLcdrom = SDL_getenv("SDL_CDROM");	/* ':' separated list of devices */
   267     /* Look in the environment for our CD-ROM drive list */
   268 	if ( SDLcdrom != NULL ) {
   268     SDLcdrom = SDL_getenv("SDL_CDROM"); /* ':' separated list of devices */
   269 		char *cdpath, *delim;
   269     if (SDLcdrom != NULL) {
   270 		size_t len = SDL_strlen(SDLcdrom)+1;
   270         char *cdpath, *delim;
   271 		cdpath = SDL_stack_alloc(char, len);
   271         size_t len = SDL_strlen(SDLcdrom) + 1;
   272 		if ( cdpath != NULL ) {
   272         cdpath = SDL_stack_alloc(char, len);
   273 			SDL_strlcpy(cdpath, SDLcdrom, len);
   273         if (cdpath != NULL) {
   274 			SDLcdrom = cdpath;
   274             SDL_strlcpy(cdpath, SDLcdrom, len);
   275 			do {
   275             SDLcdrom = cdpath;
   276 				delim = SDL_strchr(SDLcdrom, ':');
   276             do {
   277 				if ( delim ) {
   277                 delim = SDL_strchr(SDLcdrom, ':');
   278 					*delim++ = '\0';
   278                 if (delim) {
   279 				}
   279                     *delim++ = '\0';
   280 				if ( CheckDrive(SDLcdrom, &stbuf) > 0 ) {
   280                 }
   281 					AddDrive(SDLcdrom, &stbuf);
   281                 if (CheckDrive(SDLcdrom, &stbuf) > 0) {
   282 				}
   282                     AddDrive(SDLcdrom, &stbuf);
   283 				if ( delim ) {
   283                 }
   284 					SDLcdrom = delim;
   284                 if (delim) {
   285 				} else {
   285                     SDLcdrom = delim;
   286 					SDLcdrom = NULL;
   286                 } else {
   287 				}
   287                     SDLcdrom = NULL;
   288 			} while ( SDLcdrom );
   288                 }
   289 			SDL_stack_free(cdpath);
   289             }
   290 		}
   290             while (SDLcdrom);
   291 
   291             SDL_stack_free(cdpath);
   292 		/* If we found our drives, there's nothing left to do */
   292         }
   293 		if ( SDL_numcds > 0 ) {
   293 
   294 			return(0);
   294         /* If we found our drives, there's nothing left to do */
   295 		}
   295         if (SDL_numcds > 0) {
   296 	}
   296             return (0);
   297 
   297         }
   298 	/* Scan the system for CD-ROM drives */
   298     }
   299 	for ( i=0; checklist[i]; ++i ) {
   299 
   300 		if ( checklist[i][0] == '?' ) {
   300     /* Scan the system for CD-ROM drives */
   301 			char *insert;
   301     for (i = 0; checklist[i]; ++i) {
   302 			exists = 1;
   302         if (checklist[i][0] == '?') {
   303 			for ( j=checklist[i][1]; exists; ++j ) {
   303             char *insert;
   304 				SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%sc", &checklist[i][3]);
   304             exists = 1;
   305 				insert = SDL_strchr(drive, '?');
   305             for (j = checklist[i][1]; exists; ++j) {
   306 				if ( insert != NULL ) {
   306                 SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%sc",
   307 					*insert = j;
   307                              &checklist[i][3]);
   308 				}
   308                 insert = SDL_strchr(drive, '?');
   309 				switch (CheckDrive(drive, &stbuf)) {
   309                 if (insert != NULL) {
   310 					/* Drive exists and is a CD-ROM */
   310                     *insert = j;
   311 					case 1:
   311                 }
   312 						AddDrive(drive, &stbuf);
   312                 switch (CheckDrive(drive, &stbuf)) {
   313 						break;
   313                     /* Drive exists and is a CD-ROM */
   314 					/* Drive exists, but isn't a CD-ROM */
   314                 case 1:
   315 					case 0:
   315                     AddDrive(drive, &stbuf);
   316 						break;
   316                     break;
   317 					/* Drive doesn't exist */
   317                     /* Drive exists, but isn't a CD-ROM */
   318 					case -1:
   318                 case 0:
   319 						exists = 0;
   319                     break;
   320 						break;
   320                     /* Drive doesn't exist */
   321 				}
   321                 case -1:
   322 			}
   322                     exists = 0;
   323 		} else {
   323                     break;
   324 			SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s", checklist[i]);
   324                 }
   325 			if ( CheckDrive(drive, &stbuf) > 0 ) {
   325             }
   326 				AddDrive(drive, &stbuf);
   326         } else {
   327 			}
   327             SDL_snprintf(drive, SDL_arraysize(drive), "/dev/%s",
   328 		}
   328                          checklist[i]);
   329 	}
   329             if (CheckDrive(drive, &stbuf) > 0) {
   330 	return(0);
   330                 AddDrive(drive, &stbuf);
   331 }
   331             }
   332 
   332         }
   333 static const char *SDL_SYS_CDName(int drive)
   333     }
   334 {
   334     return (0);
   335 	return(SDL_cdlist[drive]);
   335 }
   336 }
   336 
   337 
   337 static const char *
   338 static int SDL_SYS_CDOpen(int drive)
   338 SDL_SYS_CDName(int drive)
   339 {
   339 {
   340 	return(open(SDL_cdlist[drive], O_RDONLY | O_NONBLOCK | O_EXCL, 0));
   340     return (SDL_cdlist[drive]);
   341 }
   341 }
   342 
   342 
   343 static int SDL_SYS_CDGetTOC(SDL_CD *cdrom)
   343 static int
   344 	{
   344 SDL_SYS_CDOpen(int drive)
   345 	u_char cdb[10], buf[4], *p, *toc;
   345 {
   346 	struct scsi_user_cdb sus;
   346     return (open(SDL_cdlist[drive], O_RDONLY | O_NONBLOCK | O_EXCL, 0));
   347 	int i, sts, first_track, last_track, ntracks, toc_size;
   347 }
   348 
   348 
   349 	bzero(cdb, sizeof (cdb));
   349 static int
   350 	cdb[0] = 0x43;		/* Read TOC */
   350 SDL_SYS_CDGetTOC(SDL_CD * cdrom)
   351 	cdb[1] = 0x2;		/* MSF */
   351 {
   352 	cdb[8] = 4;		/* size TOC header */
   352     u_char cdb[10], buf[4], *p, *toc;
   353 	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, 4, &sus);
   353     struct scsi_user_cdb sus;
   354 	if	(sts < 0)
   354     int i, sts, first_track, last_track, ntracks, toc_size;
   355 		return(-1);
   355 
   356 	first_track = buf[2];
   356     bzero(cdb, sizeof(cdb));
   357 	last_track = buf[3];
   357     cdb[0] = 0x43;              /* Read TOC */
   358 	ntracks = last_track - first_track + 1;
   358     cdb[1] = 0x2;               /* MSF */
   359 	cdrom->numtracks = ntracks;
   359     cdb[8] = 4;                 /* size TOC header */
   360 	toc_size = 4 + (ntracks + 1) * 8;
   360     sts = scsi_cmd(cdrom->id, (cdb_t *) cdb, 10, SUC_READ, buf, 4, &sus);
   361 	toc = (u_char *)SDL_malloc(toc_size);
   361     if (sts < 0)
   362 	if	(toc == NULL)
   362         return (-1);
   363 		return(-1);
   363     first_track = buf[2];
   364 	bzero(cdb, sizeof (cdb));
   364     last_track = buf[3];
   365 	cdb[0] = 0x43;
   365     ntracks = last_track - first_track + 1;
   366 	cdb[1] = 0x2;
   366     cdrom->numtracks = ntracks;
   367 	cdb[6] = first_track;
   367     toc_size = 4 + (ntracks + 1) * 8;
   368 	cdb[7] = toc_size >> 8;
   368     toc = (u_char *) SDL_malloc(toc_size);
   369 	cdb[8] = toc_size & 0xff;
   369     if (toc == NULL)
   370 	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, toc, toc_size, 
   370         return (-1);
   371 			&sus);
   371     bzero(cdb, sizeof(cdb));
   372 	if	(sts < 0)
   372     cdb[0] = 0x43;
   373 		{
   373     cdb[1] = 0x2;
   374 		SDL_free(toc);
   374     cdb[6] = first_track;
   375 		return(-1);
   375     cdb[7] = toc_size >> 8;
   376 		}
   376     cdb[8] = toc_size & 0xff;
   377 
   377     sts = scsi_cmd(cdrom->id, (cdb_t *) cdb, 10, SUC_READ, toc, toc_size,
   378 	for	(i = 0, p = toc+4; i <= ntracks; i++, p+= 8)
   378                    &sus);
   379 		{
   379     if (sts < 0) {
   380 		if	(i == ntracks)
   380         SDL_free(toc);
   381 			cdrom->track[i].id = 0xAA;	/* Leadout */
   381         return (-1);
   382 		else
   382     }
   383 			cdrom->track[i].id = first_track + i;
   383 
   384 		if	(p[1] & 0x20)
   384     for (i = 0, p = toc + 4; i <= ntracks; i++, p += 8) {
   385 			cdrom->track[i].type = SDL_DATA_TRACK;
   385         if (i == ntracks)
   386 		else
   386             cdrom->track[i].id = 0xAA;  /* Leadout */
   387 			cdrom->track[i].type = SDL_AUDIO_TRACK;
   387         else
   388 		cdrom->track[i].offset = msf_to_frame(p[5], p[6], p[7]);
   388             cdrom->track[i].id = first_track + i;
   389 		cdrom->track[i].length = 0;
   389         if (p[1] & 0x20)
   390 		if	(i > 0)
   390             cdrom->track[i].type = SDL_DATA_TRACK;
   391 			cdrom->track[i-1].length = cdrom->track[i].offset -
   391         else
   392 						   cdrom->track[i-1].offset;
   392             cdrom->track[i].type = SDL_AUDIO_TRACK;
   393 		}
   393         cdrom->track[i].offset = msf_to_frame(p[5], p[6], p[7]);
   394 	SDL_free(toc);
   394         cdrom->track[i].length = 0;
   395 	return(0);
   395         if (i > 0)
   396 	}
   396             cdrom->track[i - 1].length = cdrom->track[i].offset -
       
   397                 cdrom->track[i - 1].offset;
       
   398     }
       
   399     SDL_free(toc);
       
   400     return (0);
       
   401 }
   397 
   402 
   398 /* Get CD-ROM status */
   403 /* Get CD-ROM status */
   399 static CDstatus SDL_SYS_CDStatus(SDL_CD *cdrom, int *position)
   404 static CDstatus
   400 	{
   405 SDL_SYS_CDStatus(SDL_CD * cdrom, int *position)
   401 	CDstatus status;
   406 {
   402 	u_char	cdb[10], buf[16];
   407     CDstatus status;
   403 	int	sts;
   408     u_char cdb[10], buf[16];
   404 	struct	scsi_user_cdb sus;
   409     int sts;
   405 
   410     struct scsi_user_cdb sus;
   406 	bzero(cdb, sizeof (cdb));
   411 
   407 	cdb[0] = 0x42;		/* read subq */
   412     bzero(cdb, sizeof(cdb));
   408 	cdb[1] = 0x2;		/* MSF */
   413     cdb[0] = 0x42;              /* read subq */
   409 	cdb[2] = 0x40;		/* q channel */
   414     cdb[1] = 0x2;               /* MSF */
   410 	cdb[3] = 1;		/* current pos */
   415     cdb[2] = 0x40;              /* q channel */
   411 	cdb[7] = sizeof (buf) >> 8;
   416     cdb[3] = 1;                 /* current pos */
   412 	cdb[8] = sizeof (buf) & 0xff;
   417     cdb[7] = sizeof(buf) >> 8;
   413 	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, buf, sizeof (buf),
   418     cdb[8] = sizeof(buf) & 0xff;
   414 			&sus);
   419     sts = scsi_cmd(cdrom->id, (cdb_t *) cdb, 10, SUC_READ, buf, sizeof(buf),
   415 	if	(sts < 0)
   420                    &sus);
   416 		return(-1);
   421     if (sts < 0)
   417 	if	(sts)
   422         return (-1);
   418 		{
   423     if (sts) {
   419 		if	(TestForMedium(cdrom->id) == 0)
   424         if (TestForMedium(cdrom->id) == 0)
   420 			status = CD_TRAYEMPTY;
   425             status = CD_TRAYEMPTY;
   421 		else
   426         else
   422 			status = CD_ERROR;
   427             status = CD_ERROR;
   423 		}
   428     } else {
   424 	else
   429         switch (buf[1]) {
   425 		{
   430         case 0x11:
   426 		switch	(buf[1])
   431             status = CD_PLAYING;
   427 			{
   432             break;
   428 			case	0x11:
   433         case 0x12:
   429 				status = CD_PLAYING;
   434             status = CD_PAUSED;
   430 				break;
   435             break;
   431 			case	0x12:
   436         case 0x13:
   432 				status = CD_PAUSED;
   437         case 0x14:
   433 				break;
   438         case 0x15:
   434 			case	0x13:
   439             status = CD_STOPPED;
   435 			case	0x14:
   440             break;
   436 			case	0x15:
   441         default:
   437 				status = CD_STOPPED;
   442             status = CD_ERROR;
   438 				break;
   443             break;
   439 			default:
   444         }
   440 				status = CD_ERROR;
   445     }
   441 				break;
   446     if (position) {
   442 			}
   447         if (status == CD_PLAYING || (status == CD_PAUSED))
   443 		}
   448             *position = msf_to_frame(buf[9], buf[10], buf[11]);
   444 	if	(position)
   449         else
   445 		{
   450             *position = 0;
   446 		if	( status == CD_PLAYING || (status == CD_PAUSED) )
   451     }
   447 			*position = msf_to_frame(buf[9], buf[10], buf[11]);
   452     return (status);
   448 		else
   453 }
   449 			*position = 0;
       
   450 		}
       
   451 	return(status);
       
   452 	}
       
   453 
   454 
   454 /* Start play */
   455 /* Start play */
   455 static int SDL_SYS_CDPlay(SDL_CD *cdrom, int start, int length)
   456 static int
   456 	{
   457 SDL_SYS_CDPlay(SDL_CD * cdrom, int start, int length)
   457 	u_char	cdb[10];
   458 {
   458 	int	sts, minute, second, frame, eminute, esecond, eframe;
   459     u_char cdb[10];
   459 	struct	scsi_user_cdb sus;
   460     int sts, minute, second, frame, eminute, esecond, eframe;
   460 
   461     struct scsi_user_cdb sus;
   461 	bzero(cdb, sizeof(cdb));
   462 
   462 	cdb[0] = 0x47;		/* Play */
   463     bzero(cdb, sizeof(cdb));
   463 	frame_to_msf(start, &minute, &second, &frame);
   464     cdb[0] = 0x47;              /* Play */
   464 	frame_to_msf(start + length, &eminute, &esecond, &eframe);
   465     frame_to_msf(start, &minute, &second, &frame);
   465 	cdb[3] = minute;
   466     frame_to_msf(start + length, &eminute, &esecond, &eframe);
   466 	cdb[4] = second;
   467     cdb[3] = minute;
   467 	cdb[5] = frame;
   468     cdb[4] = second;
   468 	cdb[6] = eminute;
   469     cdb[5] = frame;
   469 	cdb[7] = esecond;
   470     cdb[6] = eminute;
   470 	cdb[8] = eframe;
   471     cdb[7] = esecond;
   471 	sts = scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus);
   472     cdb[8] = eframe;
   472 	return(sts);
   473     sts = scsi_cmd(cdrom->id, (cdb_t *) cdb, 10, SUC_READ, 0, 0, &sus);
   473 	}
   474     return (sts);
   474 
   475 }
   475 static	int
   476 
   476 pauseresume(SDL_CD *cdrom, int flag)
   477 static int
   477 	{
   478 pauseresume(SDL_CD * cdrom, int flag)
   478 	u_char	cdb[10];
   479 {
   479 	struct	scsi_user_cdb sus;
   480     u_char cdb[10];
   480 
   481     struct scsi_user_cdb sus;
   481 	bzero(cdb, sizeof (cdb));
   482 
   482 	cdb[0] = 0x4b;
   483     bzero(cdb, sizeof(cdb));
   483 	cdb[8] = flag & 0x1;
   484     cdb[0] = 0x4b;
   484 	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 10, SUC_READ, 0, 0, &sus));
   485     cdb[8] = flag & 0x1;
   485 	}
   486     return (scsi_cmd(cdrom->id, (cdb_t *) cdb, 10, SUC_READ, 0, 0, &sus));
       
   487 }
   486 
   488 
   487 /* Pause play */
   489 /* Pause play */
   488 static int SDL_SYS_CDPause(SDL_CD *cdrom)
   490 static int
   489 {
   491 SDL_SYS_CDPause(SDL_CD * cdrom)
   490 	return(pauseresume(cdrom, 0));
   492 {
       
   493     return (pauseresume(cdrom, 0));
   491 }
   494 }
   492 
   495 
   493 /* Resume play */
   496 /* Resume play */
   494 static int SDL_SYS_CDResume(SDL_CD *cdrom)
   497 static int
   495 {
   498 SDL_SYS_CDResume(SDL_CD * cdrom)
   496 	return(pauseresume(cdrom, 1));
   499 {
       
   500     return (pauseresume(cdrom, 1));
   497 }
   501 }
   498 
   502 
   499 /* Stop play */
   503 /* Stop play */
   500 static int SDL_SYS_CDStop(SDL_CD *cdrom)
   504 static int
   501 {
   505 SDL_SYS_CDStop(SDL_CD * cdrom)
   502 	u_char cdb[6];
   506 {
   503 	struct	scsi_user_cdb sus;
   507     u_char cdb[6];
   504 
   508     struct scsi_user_cdb sus;
   505 	bzero(cdb, sizeof (cdb));
   509 
   506 	cdb[0] = 0x1b;		/* stop */
   510     bzero(cdb, sizeof(cdb));
   507 	cdb[1] = 1;		/* immediate */
   511     cdb[0] = 0x1b;              /* stop */
   508 	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
   512     cdb[1] = 1;                 /* immediate */
       
   513     return (scsi_cmd(cdrom->id, (cdb_t *) cdb, 6, SUC_READ, 0, 0, &sus));
   509 }
   514 }
   510 
   515 
   511 /* Eject the CD-ROM */
   516 /* Eject the CD-ROM */
   512 static int SDL_SYS_CDEject(SDL_CD *cdrom)
   517 static int
   513 {
   518 SDL_SYS_CDEject(SDL_CD * cdrom)
   514 	u_char cdb[6];
   519 {
   515 	struct	scsi_user_cdb sus;
   520     u_char cdb[6];
   516 
   521     struct scsi_user_cdb sus;
   517 	bzero(cdb, sizeof (cdb));
   522 
   518 	cdb[0] = 0x1b;		/* stop */
   523     bzero(cdb, sizeof(cdb));
   519 	cdb[1] = 1;		/* immediate */
   524     cdb[0] = 0x1b;              /* stop */
   520 	cdb[4] = 2;		/* eject */
   525     cdb[1] = 1;                 /* immediate */
   521 	return(scsi_cmd(cdrom->id, (cdb_t *)cdb, 6, SUC_READ, 0, 0, &sus));
   526     cdb[4] = 2;                 /* eject */
       
   527     return (scsi_cmd(cdrom->id, (cdb_t *) cdb, 6, SUC_READ, 0, 0, &sus));
   522 }
   528 }
   523 
   529 
   524 /* Close the CD-ROM handle */
   530 /* Close the CD-ROM handle */
   525 static void SDL_SYS_CDClose(SDL_CD *cdrom)
   531 static void
   526 	{
   532 SDL_SYS_CDClose(SDL_CD * cdrom)
   527 	close(cdrom->id);
   533 {
   528 	}
   534     close(cdrom->id);
   529 
   535 }
   530 void SDL_SYS_CDQuit(void)
   536 
   531 {
   537 void
   532 	int i;
   538 SDL_SYS_CDQuit(void)
   533 
   539 {
   534 	if ( SDL_numcds > 0 ) {
   540     int i;
   535 		for ( i=0; i<SDL_numcds; ++i ) {
   541 
   536 			SDL_free(SDL_cdlist[i]);
   542     if (SDL_numcds > 0) {
   537 			}
   543         for (i = 0; i < SDL_numcds; ++i) {
   538 		}
   544             SDL_free(SDL_cdlist[i]);
   539 	SDL_numcds = 0;
   545         }
       
   546     }
       
   547     SDL_numcds = 0;
   540 }
   548 }
   541 
   549 
   542 #endif /* SDL_CDROM_BSDI */
   550 #endif /* SDL_CDROM_BSDI */
       
   551 /* vi: set ts=4 sw=4 expandtab: */