1 /*
2  * Copyright (C) 1990 Regents of the University of California.
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and
5  * its documentation for any purpose is hereby granted without fee,
6  * provided that the above copyright notice appear in all copies and that
7  * both that copyright notice and this permission notice appear in
8  * supporting documentation, and that the name of the University of
9  * California not be used in advertising or publicity pertaining to
10  * distribution of the software without specific, written prior
11  * permission.  the University of California makes no representations
12  * about the suitability of this software for any purpose.  It is provided
13  * "as is" without express or implied warranty.
14  */
15 
16 static int c;
17 
18 # if defined(sun)
19 # include <stdio.h>
20 
21 # include <sys/file.h>
22 # include <sys/types.h>
23 # include <sys/param.h>
24 # include <sys/stat.h>
25 
26 # include <sun/dkio.h>
27 
28 # include <mntent.h>
29 # include <string.h>
30 
31 # include <sys/buf.h>
32 # ifdef sun4c
33 # include <scsi/targets/srdef.h>
34 # else
35 # include <sundev/srreg.h>
36 # endif
37 
38 # include <sys/time.h>
39 
40 # include "debug.h"
41 # include "cdrom_sun.h"
42 
43 extern char	*device;
44 # if defined(notdef)
45 extern void	cdrom_print_toc();
46 # endif /* defined(notdef) */
47 
48 static char	cdrom[] =	"/dev/rsr0";
49 
50 cdrom_info	cdi;
51 char		info_filename[256];
52 FILE		*disc_info = NULL;
53 
54 static int	cdrom_fd = -1;
55 
get_stored_info()56 get_stored_info()
57 {
58 	int i,n;
59 	char	line[100];
60 	char	*title;
61 
62         if ( cdi.maxtrack == 0) {
63                 return(0);
64         }
65 	for (i = 0, n = 0; i < cdi.maxtrack; i++)
66 	    n = n + ((i+1) * cdi.times[i]);
67 	n = n / cdi.maxtrack;
68 
69         disc_title = NULL;
70 	if (cdInfoDir != NULL)
71 	    sprintf(info_filename, "%s/cd.%d", cdInfoDir, n);
72 	else
73 	    sprintf(info_filename, "cd.%d", n);
74 
75 	if ((disc_info = fopen(info_filename, "r")) != NULL)
76 	{
77 	    fgets(line, 100, disc_info);
78 	    title = strchr(line, ':');
79 	    if (title != NULL)
80 	    {
81 	    	*(strchr(title, '\n')) = '\0';
82 	        disc_title = strdup(title + 1);
83 	    }
84 	    fgets(line, 100, disc_info);
85 	    sscanf(line, "Program: %s", program_str);
86 	}
87         if (disc_title == NULL) {
88                 disc_title = NOTITLESTR;
89         }
90 }
91 
92 int
cdrom_open()93 cdrom_open() {
94 	int	n;
95 	extern void update_title();
96 
97 	if (cdrom_fd != -1)
98 		return(cdi.curtrack);
99 
100 	if (device != NULL) {
101 		if ((cdrom_fd = open(device, O_RDONLY)) == -1) {
102 			debug-printf(stderr, "open: ");
103 			return(-1);
104 		}
105 	} else {
106 		if ((cdrom_fd = open(cdrom, O_RDONLY)) == -1) {
107 			debug-printf(stderr, "open: ");
108 			return(-1);
109 		}
110 	}
111 
112 	if (cdrom_get_times() == -1) {
113 		cdrom_close();
114 		return(-1);
115 	}
116 
117 	if ((n = cdrom_get_curtrack()) == -1)
118 		return(-1);
119 
120 	get_stored_info();
121 
122 	update_title();
123 
124 	if (cdi.state & CDROM_STATE_PLAY)
125 		cdi.curtrack = n;
126 
127 	if (cdi.state & CDROM_STATE_SHUFFLE)
128 		shuffle_setup();
129 
130 	return(cdi.curtrack);
131 }
132 
133 void
cdrom_close()134 cdrom_close() {
135 	if (cdrom_fd == -1)
136 		return;
137 
138 	if (cdi.times != NULL) {
139 		free((char *) cdi.times);
140 		free((char *) cdi.addrs);
141 		cdi.times = NULL;
142 		cdi.addrs = NULL;
143 	}
144 
145 	(void) close(cdrom_fd);
146 	cdrom_fd = -1;
147 }
148 
149 
150 int
cdrom_start()151 cdrom_start() {
152 	if (cdrom_fd == -1)
153 		return(-1);
154 
155 	if (ioctl(cdrom_fd, CDROMSTART) == -1) {
156 		perror("ioctl(cdromstart)");
157 		return(-1);
158 	}
159 
160 	return(0);
161 }
162 
163 int
cdrom_stop()164 cdrom_stop() {
165 	if (cdrom_fd == -1)
166 		return(-1);
167 
168 	if (ioctl(cdrom_fd, CDROMSTOP) == -1) {
169 		perror("ioctl(cdromstop)");
170 		return(-1);
171 	}
172 
173 	return(0);
174 }
175 
176 int
cdrom_eject()177 cdrom_eject() {
178 	if (cdrom_fd == -1)
179 		return(-1);
180 
181 	if (ioctl(cdrom_fd, CDROMEJECT) == -1) {
182 		perror("ioctl(cdromeject)");
183 		return(-1);
184 	}
185 
186 	return(0);
187 }
188 
189 int
cdrom_pause()190 cdrom_pause() {
191 	if (cdrom_fd == -1)
192 		return(-1);
193 
194 	if (ioctl(cdrom_fd, CDROMPAUSE) == -1) {
195 		perror("ioctl(cdrompause)");
196 		return(-1);
197 	}
198 
199 	return(0);
200 }
201 
202 int
cdrom_resume()203 cdrom_resume() {
204 	if (cdrom_fd == -1)
205 		return(-1);
206 
207 	if (ioctl(cdrom_fd, CDROMRESUME) == -1) {
208 		perror("ioctl(cdromresume)");
209 		return(-1);
210 	}
211 
212 	return(0);
213 }
214 
215 int
cdrom_volume(left_vol,right_vol)216 cdrom_volume(left_vol, right_vol)
217 	int			left_vol;
218 	int			right_vol;
219 {
220 	struct cdrom_volctrl	vol;
221 
222 	if (cdrom_fd == -1)
223 		return(-1);
224 
225 	vol.channel0 = left_vol;
226 	vol.channel1 = right_vol;
227 
228 	if (ioctl(cdrom_fd, CDROMVOLCTRL, &vol) == -1) {
229 		perror("ioctl(cdromvolctrl)");
230 		return(-1);
231 	}
232 
233 	return(0);
234 }
235 
236 int
cdrom_get_times()237 cdrom_get_times() {
238 	struct cdrom_tochdr	tochdr;
239 	extern unsigned short	*ushort_malloc();
240 	extern struct msf	*msf_malloc();
241 	unsigned long		trk, trk_total, otime;
242 	struct msf		msf;
243 
244 	if (cdrom_read_tochdr(&tochdr) == -1)
245 		return(-1);
246 
247 	cdi.mintrack = tochdr.cdth_trk0;
248 	cdi.maxtrack = tochdr.cdth_trk1;
249 
250 	if (cdi.times != NULL)
251 	{
252 		free((char *) cdi.times);
253 		free((char *) cdi.addrs);
254 		cdi.times = NULL;
255 		cdi.addrs = NULL;
256 	}
257 
258 	cdi.times = ushort_malloc(cdi.maxtrack - cdi.mintrack + 1);
259 	cdi.addrs = msf_malloc(cdi.maxtrack - cdi.mintrack + 2);
260 
261 	otime = 0;
262 
263 	for (trk = cdi.mintrack; trk <= cdi.maxtrack; trk++) {
264 		if (cdrom_get_msf(trk, &msf, &trk_total) == -1)
265 			return(-1);
266 
267 		/* record start address for each track (track 1 starts at 0)*/
268 		cdi.addrs[trk - cdi.mintrack] = msf;
269 
270 		trk_total -= otime;
271 
272 		/* use start time of next track as length of previous */
273 		if (otime != 0)
274 		{
275 			cdi.times[trk - cdi.mintrack - 1] = trk_total;
276 		}
277 
278 		otime += trk_total;
279 
280 	}
281 
282 	/* find start of  leadout to get length of last track */
283 	if (cdrom_get_msf(CDROM_LEADOUT, &msf, &trk_total) == -1)
284 		return(-1);
285 
286 	/* recode leadout start address */
287 	cdi.addrs[trk - cdi.mintrack] = msf;
288 	trk_total -= otime;
289 	otime += trk_total;
290 
291 	cdi.times[trk - cdi.mintrack - 1] = trk_total;
292 
293 	return(0);
294 }
295 
296 # if defined(notdef)
297 static void
cdrom_print_toc()298 cdrom_print_toc() {
299 	unsigned long		trk, trk_total;
300 
301 	for (trk = cdi.mintrack; trk <= cdi.maxtrack; trk++) {
302 		trk_total = cdi.times[trk - cdi.mintrack];
303 		debug_printf(1, "%02u:%02u\n", trk_total/60, trk_total%60);
304 	}
305 }
306 # endif /* defined(notdef) */
307 
308 int
cdrom_get_curtrack()309 cdrom_get_curtrack() {
310 	struct cdrom_subchnl	subchnl;
311 
312 	if (cdrom_fd == -1)
313 		return(-1);
314 
315 	if (ioctl(cdrom_fd, CDROMSUBCHNL, (char *) &subchnl) == -1) {
316 		fprintf(stderr, "ioctl(cdromsubchnl): ");
317 		perror(cdrom);
318 		return(-1);
319 	}
320 
321 	switch (subchnl.cdsc_audiostatus) {
322 		case CDROM_AUDIO_INVALID:
323 		return(-1);
324 
325 		/* playing track subchnl.cdsc_trk */
326 		case CDROM_AUDIO_PLAY:
327 		return((int) subchnl.cdsc_trk);
328 
329 		/* paused on track subchnl.cdsc_trk */
330 		case CDROM_AUDIO_PAUSED:
331 		return((int) subchnl.cdsc_trk);
332 
333 		/* punt */
334 		case CDROM_AUDIO_COMPLETED:
335 		return(0);
336 
337 		case CDROM_AUDIO_ERROR:
338 		return(-1);
339 
340 		/* punt */
341 		case CDROM_AUDIO_NO_STATUS:
342 		debug_printf(1, "cdrom_get_curtrack: no status\n");
343 		return(0);
344 	}
345 
346 	/* bad value in cdsc_audiostatus */
347 	return(-1);
348 }
349 
350 int
cdrom_get_msf(track,msf,length)351 cdrom_get_msf(track, msf, length)
352 	unsigned long		track;
353 	struct msf		*msf;
354 	unsigned long		*length;
355 {
356 	struct cdrom_tocentry	tocentry;
357 
358 	if (cdrom_read_tocentry(track, &tocentry) == -1)
359 		return(-1);
360 
361 	msf->minute = tocentry.cdte_addr.msf.minute;
362 	msf->second = tocentry.cdte_addr.msf.second;
363 	msf->frame = tocentry.cdte_addr.msf.frame;
364 
365 	*length = ((int) tocentry.cdte_addr.msf.minute * 60) +
366 		(int) tocentry.cdte_addr.msf.second;
367 
368 	return(0);
369 }
370 
371 int
cdrom_get_curmsf(msf)372 cdrom_get_curmsf(msf)
373 	struct msf *msf;
374 {
375 	struct cdrom_subchnl	subchnl;
376 
377 	if (cdrom_fd == -1)
378 		return(-1);
379 
380 	subchnl.cdsc_format = CDROM_MSF;
381 
382 	if (ioctl(cdrom_fd, CDROMSUBCHNL, (char *) &subchnl) == -1) {
383 		perror("ioctl(cdromsubchnl)");
384 		return(-1);
385 	}
386 
387 	msf->minute = subchnl.cdsc_absaddr.msf.minute;
388 	msf->second = subchnl.cdsc_absaddr.msf.second;
389 	msf->frame = subchnl.cdsc_absaddr.msf.frame;
390 
391 	return (0);
392 
393 }
394 
395 int
cdrom_play_track(start_track,end_track)396 cdrom_play_track(start_track, end_track)
397 	unsigned char		start_track;
398 	unsigned char		end_track;
399 {
400 	struct	cdrom_ti	ti;
401 
402 	if (cdrom_fd == -1)
403 		return(-1);
404 
405 	ti.cdti_trk0 = start_track;
406 	ti.cdti_ind0 = 1;
407 	ti.cdti_trk1 = end_track;
408 	ti.cdti_ind1 = 1;
409 
410 	if (ioctl(cdrom_fd, CDROMPLAYTRKIND, &ti) == -1) {
411 		perror("ioctl(cdromplaytrkind)");
412 		return(-1);
413 	}
414 
415 	return(0);
416 }
417 
418 int
cdrom_play_msf(start_msf,end_msf)419 cdrom_play_msf(start_msf, end_msf)
420 	struct msf	*start_msf;
421 	struct msf	*end_msf;
422 {
423 	struct	cdrom_msf	play_addr;
424 
425 	if (cdrom_fd == -1)
426 		return(-1);
427 
428 	play_addr.cdmsf_min0 = start_msf->minute;
429 	play_addr.cdmsf_sec0 = start_msf->second;
430 	play_addr.cdmsf_frame0 = start_msf->frame;
431 	play_addr.cdmsf_min1 = end_msf->minute;
432 	play_addr.cdmsf_sec1 = end_msf->second;
433 	play_addr.cdmsf_frame1 = end_msf->frame;
434 
435 	if (ioctl(cdrom_fd, CDROMPLAYMSF, &play_addr) == -1) {
436 		perror("ioctl(cdromplaymsf)");
437 		return(-1);
438 	}
439 
440 	return(0);
441 }
442 int
cdrom_read_tocentry(track,tocentry)443 cdrom_read_tocentry(track, tocentry)
444 	unsigned int		track;
445 	struct cdrom_tocentry	*tocentry;
446 {
447 	if (cdrom_fd == -1)
448 		return(-1);
449 
450 	tocentry->cdte_track = track;
451 	tocentry->cdte_format = CDROM_MSF;
452 
453 	if (ioctl(cdrom_fd, CDROMREADTOCENTRY, (char *) tocentry) == -1) {
454 		perror("ioctl(cdromreadtocentry)");
455 		return(-1);
456 	}
457 
458 	return(0);
459 }
460 
461 int
cdrom_read_tochdr(tochdr)462 cdrom_read_tochdr(tochdr)
463 	struct cdrom_tochdr	*tochdr;
464 {
465 	if (cdrom_fd == -1)
466 		return(-1);
467 
468 	if (ioctl(cdrom_fd, CDROMREADTOCHDR, (char *) tochdr) == -1) {
469 		debug-printf(stderr,"ioctl(cdromreadtochdr): ");
470 		/* perror("ioctl(cdromreadtochdr)"); */
471 		return(-1);
472 	}
473 
474 	return(0);
475 }
476 
477 int
cdrom_status()478 cdrom_status() {
479 	struct cdrom_subchnl	subchnl;
480 
481 	if (cdrom_fd == -1)
482 		return(-1);
483 
484 	if (ioctl(cdrom_fd, CDROMSUBCHNL, (char *) &subchnl) == -1) {
485 		fprintf(stderr, "ioctl(cdromsubchnl): ");
486 		perror(cdrom);
487 		exit(1);
488 	}
489 
490 	switch (subchnl.cdsc_audiostatus) {
491 		case CDROM_AUDIO_INVALID:
492 		return(CDROM_INVALID);
493 
494 		case CDROM_AUDIO_PLAY:
495 		return(CDROM_PLAYING);
496 
497 		case CDROM_AUDIO_PAUSED:
498 		return(CDROM_PAUSED);
499 
500 		case CDROM_AUDIO_COMPLETED:
501 		return(CDROM_COMPLETED);
502 
503 		case CDROM_AUDIO_ERROR:
504 		return(CDROM_ERROR);
505 
506 		case CDROM_AUDIO_NO_STATUS:
507 		return(CDROM_NO_STATUS);
508 	}
509 
510 	return(-1);
511 }
512 
513 # if defined(notused)
514 int
cdrom_playing(track)515 cdrom_playing(track)
516 	int			*track;
517 {
518 	struct cdrom_subchnl	sc;
519 
520 	if (cdrom_fd == -1)
521 		return(-1);
522 
523 	sc.cdsc_format = CDROM_MSF;
524 	if (ioctl(cdrom_fd, CDROMSUBCHNL, &sc) == -1) {
525 		perror("ioctl(cdromsubchnl)");
526 		return(-1);
527 	}
528 
529 	*track = sc.cdsc_trk;
530 
531 	if (sc.cdsc_audiostatus == CDROM_AUDIO_PLAY)
532 		return(1);
533 
534 	return(0);
535 }
536 # endif /* defined(notused) */
537 
538 # if defined(notused)
539 int
cdrom_paused(track)540 cdrom_paused(track)
541 	int			*track;
542 {
543 	struct cdrom_subchnl	sc;
544 
545 	if (cdrom_fd == -1)
546 		return(-1);
547 
548 	sc.cdsc_format = CDROM_MSF;
549 	if (ioctl(cdrom_fd, CDROMSUBCHNL, &sc) == -1) {
550 		perror("ioctl(cdromsubchnl)");
551 		return(-1);
552 	}
553 
554 	*track = sc.cdsc_trk;
555 
556 	if (sc.cdsc_audiostatus == CDROM_AUDIO_PAUSED)
557 		return(1);
558 
559 	return(0);
560 }
561 # endif /* defined(notused) */
562 
563 # if defined(notused)
564 int
mounted(name)565 mounted(name)
566 	char		*name;
567 {
568 	char		buf[MAXPATHLEN], *cp;
569 	struct stat	st;
570 	dev_t		bdevno;
571 	FILE		*fp;
572 	struct mntent	*mnt;
573 
574 	/*
575 	 * Get the block device corresponding to the raw device opened,
576 	 * and find its device number.
577 	 */
578 	if (stat(name, &st) != 0) {
579 		(void) fprintf(stderr, "stat: ");
580 		perror(name);
581 		return(UNMOUNTED);
582 	}
583 
584 	/*
585 	 * If this is a raw device, we have to build the block device name.
586 	 */
587 	if ((st.st_mode & S_IFMT) == S_IFCHR) {
588 		if ((cp = strchr(name, 'r')) != NULL)
589 			cp++;
590 
591 		(void) sprintf(buf, "/dev/%s", cp);
592 		if (stat(buf, &st) != 0) {
593 			(void) fprintf(stderr, "stat: ");
594 			perror(buf);
595 			return(UNMOUNTED);
596 		}
597 	}
598 
599 	if ((st.st_mode & S_IFMT) != S_IFBLK)
600 		return(UNMOUNTED);
601 
602 	bdevno = st.st_rdev & (dev_t)(~0x07);	/* Mask out partition. */
603 
604 	/*
605 	 * Now go through the mtab, looking at all hsfs filesystems.
606 	 * Compare the device mounted with our bdevno.
607 	 */
608 	if ((fp = setmntent(MOUNTED, "r")) == NULL) {
609 		(void) fprintf(stderr, "couldn't open %s\n", MOUNTED);
610 		return(UNMOUNTED);
611 	}
612 
613 	while ((mnt = getmntent(fp)) != NULL) {
614 		/* avoid obvious excess stat(2)'s */
615 		if (strcmp(mnt->mnt_type, "hsfs") != 0)
616 			continue;
617 
618 		if (stat(mnt->mnt_fsname, &st) != 0)
619 			continue;
620 
621 		if (((st.st_mode & S_IFMT) == S_IFBLK) &&
622 		    ((st.st_rdev & (dev_t)(~0x07)) == bdevno)) {
623 			(void) endmntent(fp);
624 			return(STILL_MOUNTED);
625 		}
626 	}
627 
628 	(void) endmntent(fp);
629 
630 	return(UNMOUNTED);
631 }
632 # endif /* defined(notused) */
633 
634 unsigned short *
ushort_malloc(n)635 ushort_malloc(n)
636 	int		n;
637 {
638 	extern char	*calloc();
639 	unsigned short	*ptr;
640 
641 	ptr = (unsigned short *) calloc(n, sizeof(unsigned short));
642 	if (ptr == NULL) {
643 		perror("calloc");
644 		exit(1);
645 	}
646 
647 	return(ptr);
648 }
649 
650 struct msf *
msf_malloc(n)651 msf_malloc(n)
652 	int		n;
653 {
654 	extern char	*calloc();
655 	struct msf	*ptr;
656 
657 	ptr = (struct msf *) calloc(n, sizeof(struct msf));
658 	if (ptr == NULL) {
659 		perror("calloc");
660 		exit(1);
661 	}
662 
663 	return(ptr);
664 }
665 
666 int
cdrom_disp_cdi()667 cdrom_disp_cdi() {
668 	int trk;
669 
670 	fprintf(stderr,"CDI structure:\n");
671 	fprintf(stderr,"\tcurtrack: %d\n",cdi.curtrack);
672 	fprintf(stderr,"\tmin: %d  max: %d  total: %d\n",
673 		cdi.mintrack, cdi.maxtrack, cdi.ntracks);
674 	fprintf(stderr,"\tdur: %d  state: %2x\n",cdi.duration, cdi.state);
675 	fprintf(stderr,"\tcurrand: %d  lastprog: %d\n",
676 		cdi.currand, cdi.lastprog);
677 	fprintf(stderr,"\n\tTracklist:\n");
678 	if (cdi.maxtrack != cdi.mintrack) {
679 		for (trk=cdi.mintrack; trk<=cdi.maxtrack; trk++) {
680 			fprintf(stderr,"\t%3d: %d %02d:%02d %d\n",trk,cdi.times[trk],
681 				cdi.addrs[trk].minute,cdi.addrs[trk].second,
682 				cdi.addrs[trk].frame);
683 		}
684 	}
685 }
686 
687 # endif /* defined(sun) */
688