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: */ |