Esempio n. 1
0
File: mcd.c Progetto: MarginC/kame
static int
mcd_pause(struct mcd_softc *sc)
{
	struct mcd_qchninfo q;
	int rc;

	/* Verify current status */
	if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS &&
	    sc->data.audio_status != CD_AS_PLAY_PAUSED) {
		if (sc->data.debug)
			device_printf(sc->dev,
				"pause attempted when not playing, audio status %d\n",
				sc->data.audio_status);
		return (EINVAL);
	}

	/* Get the current position */
	if (mcd_getqchan(sc, &q) < 0)
		return (EIO);

	/* Copy it into lastpb */
	sc->data.lastpb.start_msf[0] = q.hd_pos_msf[0];
	sc->data.lastpb.start_msf[1] = q.hd_pos_msf[1];
	sc->data.lastpb.start_msf[2] = q.hd_pos_msf[2];

	/* Stop playing */
	if ((rc=mcd_stop(sc)) != 0)
		return (rc);

	/* Set the proper status and exit */
	sc->data.audio_status = CD_AS_PLAY_PAUSED;
	return (0);
}
Esempio n. 2
0
int
mcd_pause(struct mcd_softc *sc)
{
	union mcd_qchninfo q;
	int error;

	/* Verify current status. */
	if (sc->audio_status != CD_AS_PLAY_IN_PROGRESS)	{
		printf("%s: pause: attempted when not playing\n",
		    device_xname(sc->sc_dev));
		return EINVAL;
	}

	/* Get the current position. */
	if ((error = mcd_getqchan(sc, &q, CD_CURRENT_POSITION)) != 0)
		return error;

	/* Copy it into lastpb. */
	sc->lastpb.data.seek.start_msf[0] = q.current.absolute_pos[0];
	sc->lastpb.data.seek.start_msf[1] = q.current.absolute_pos[1];
	sc->lastpb.data.seek.start_msf[2] = q.current.absolute_pos[2];

	/* Stop playing. */
	if ((error = mcd_stop(sc)) != 0)
		return error;

	/* Set the proper status and exit. */
	sc->audio_status = CD_AS_PLAY_PAUSED;
	return 0;
}
Esempio n. 3
0
int
mcd_read_toc(struct mcd_softc *sc)
{
	struct ioc_toc_header th;
	union mcd_qchninfo q;
	int error, trk, idx, retry;

	if ((error = mcd_toc_header(sc, &th)) != 0)
		return error;

	if ((error = mcd_stop(sc)) != 0)
		return error;

	if (sc->debug)
		printf("%s: read_toc: reading qchannel info\n",
		    device_xname(sc->sc_dev));

	for (trk = th.starting_track; trk <= th.ending_track; trk++)
		sc->toc[trk].toc.idx_no = 0x00;
	trk = th.ending_track - th.starting_track + 1;
	for (retry = 300; retry && trk > 0; retry--) {
		if (mcd_getqchan(sc, &q, CD_TRACK_INFO) != 0)
			break;
		if (q.toc.trk_no != 0x00 || q.toc.idx_no == 0x00)
			continue;
		idx = bcd2bin(q.toc.idx_no);
		if (idx < MCD_MAXTOCS &&
		    sc->toc[idx].toc.idx_no == 0x00) {
			sc->toc[idx] = q;
			trk--;
		}
	}

	/* Inform the drive that we're finished so it turns off the light. */
	if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
		return error;

	if (trk != 0)
		return EINVAL;

	/* Add a fake last+1 for mcd_playtracks(). */
	idx = th.ending_track + 1;
	sc->toc[idx].toc.control = sc->toc[idx-1].toc.control;
	sc->toc[idx].toc.addr_type = sc->toc[idx-1].toc.addr_type;
	sc->toc[idx].toc.trk_no = 0x00;
	sc->toc[idx].toc.idx_no = 0xaa;
	sc->toc[idx].toc.absolute_pos[0] = sc->volinfo.vol_msf[0];
	sc->toc[idx].toc.absolute_pos[1] = sc->volinfo.vol_msf[1];
	sc->toc[idx].toc.absolute_pos[2] = sc->volinfo.vol_msf[2];

	return 0;
}
Esempio n. 4
0
File: mcd.c Progetto: MarginC/kame
static int
mcd_subchan(struct mcd_softc *sc, struct ioc_read_subchannel *sch)
{
	struct mcd_qchninfo q;
	struct cd_sub_channel_info data;
	int lba;

	if (sc->data.debug)
		device_printf(sc->dev, "subchan af=%d, df=%d\n",
			sch->address_format,
			sch->data_format);

	if (sch->address_format != CD_MSF_FORMAT &&
	    sch->address_format != CD_LBA_FORMAT)
		return (EINVAL);

	if (sch->data_format != CD_CURRENT_POSITION &&
	    sch->data_format != CD_MEDIA_CATALOG)
		return (EINVAL);

	if (mcd_setmode(sc, MCD_MD_COOKED) != 0)
		return (EIO);

	if (mcd_getqchan(sc, &q) < 0)
		return (EIO);

	data.header.audio_status = sc->data.audio_status;
	data.what.position.data_format = sch->data_format;

	switch (sch->data_format) {
	case CD_MEDIA_CATALOG:
		data.what.media_catalog.mc_valid = 1;
		data.what.media_catalog.mc_number[0] = '\0';
		break;

	case CD_CURRENT_POSITION:
		data.what.position.control = q.control;
		data.what.position.addr_type = q.addr_type;
		data.what.position.track_number = bcd2bin(q.trk_no);
		data.what.position.index_number = bcd2bin(q.idx_no);
		switch (sch->address_format) {
		case CD_MSF_FORMAT:
			data.what.position.reladdr.msf.unused = 0;
			data.what.position.reladdr.msf.minute = bcd2bin(q.trk_size_msf[0]);
			data.what.position.reladdr.msf.second = bcd2bin(q.trk_size_msf[1]);
			data.what.position.reladdr.msf.frame = bcd2bin(q.trk_size_msf[2]);
			data.what.position.absaddr.msf.unused = 0;
			data.what.position.absaddr.msf.minute = bcd2bin(q.hd_pos_msf[0]);
			data.what.position.absaddr.msf.second = bcd2bin(q.hd_pos_msf[1]);
			data.what.position.absaddr.msf.frame = bcd2bin(q.hd_pos_msf[2]);
			break;
		case CD_LBA_FORMAT:
			lba = msf2hsg(q.trk_size_msf, 1);
			/*
			 * Pre-gap has index number of 0, and decreasing MSF
			 * address.  Must be converted to negative LBA, per
			 * SCSI spec.
			 */
			if (data.what.position.index_number == 0)
				lba = -lba;
			data.what.position.reladdr.lba = htonl(lba);
			data.what.position.absaddr.lba = htonl(msf2hsg(q.hd_pos_msf, 0));
			break;
		}
		break;
	}

	return copyout(&data, sch->data, min(sizeof(struct cd_sub_channel_info), sch->data_len));
}
Esempio n. 5
0
File: mcd.c Progetto: MarginC/kame
static int
mcd_read_toc(struct mcd_softc *sc)
{
	struct ioc_toc_header th;
	struct mcd_qchninfo q;
	int rc, trk, idx, retry;

	/* Only read TOC if needed */
	if (sc->data.flags & MCDTOC)
		return (0);

	if (sc->data.debug)
		device_printf(sc->dev, "reading toc header\n");

	if ((rc = mcd_toc_header(sc, &th)) != 0)
		return (rc);

	if (mcd_send(sc, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0)
		return (EIO);

	if (mcd_setmode(sc, MCD_MD_TOC) != 0)
		return (EIO);

	if (sc->data.debug)
		device_printf(sc->dev, "get_toc reading qchannel info\n");

	for(trk=th.starting_track; trk<=th.ending_track; trk++)
		sc->data.toc[trk].idx_no = 0;
	trk = th.ending_track - th.starting_track + 1;
	for(retry=0; retry<600 && trk>0; retry++)
	{
		if (mcd_getqchan(sc, &q) < 0) break;
		idx = bcd2bin(q.idx_no);
		if (idx>=th.starting_track && idx<=th.ending_track && q.trk_no==0) {
			if (sc->data.toc[idx].idx_no == 0) {
				sc->data.toc[idx] = q;
				trk--;
			}
		}
	}

	if (mcd_setmode(sc, MCD_MD_COOKED) != 0)
		return (EIO);

	if (trk != 0)
		return (ENXIO);

	/* add a fake last+1 */
	idx = th.ending_track + 1;
	sc->data.toc[idx].control = sc->data.toc[idx-1].control;
	sc->data.toc[idx].addr_type = sc->data.toc[idx-1].addr_type;
	sc->data.toc[idx].trk_no = 0;
	sc->data.toc[idx].idx_no = MCD_LASTPLUS1;
	sc->data.toc[idx].hd_pos_msf[0] = sc->data.volinfo.vol_msf[0];
	sc->data.toc[idx].hd_pos_msf[1] = sc->data.volinfo.vol_msf[1];
	sc->data.toc[idx].hd_pos_msf[2] = sc->data.volinfo.vol_msf[2];

	if (sc->data.debug)
	{ int i;
	for (i = th.starting_track; i <= idx; i++)
		device_printf(sc->dev, "trk %d idx %d pos %d %d %d\n",
			i,
			sc->data.toc[i].idx_no > 0x99 ? sc->data.toc[i].idx_no :
			bcd2bin(sc->data.toc[i].idx_no),
			bcd2bin(sc->data.toc[i].hd_pos_msf[0]),
			bcd2bin(sc->data.toc[i].hd_pos_msf[1]),
			bcd2bin(sc->data.toc[i].hd_pos_msf[2]));
	}

	sc->data.flags |= MCDTOC;

	return (0);
}
Esempio n. 6
0
int
mcd_read_subchannel(struct mcd_softc *sc, struct ioc_read_subchannel *ch, struct cd_sub_channel_info *info)
{
	int len = ch->data_len;
	union mcd_qchninfo q;
	daddr_t lba;
	int error;

	if (sc->debug)
		printf("%s: subchan: af=%d df=%d\n", device_xname(sc->sc_dev),
		    ch->address_format, ch->data_format);

	if (len > sizeof(*info) || len < sizeof(info->header))
		return EINVAL;
	if (ch->address_format != CD_MSF_FORMAT &&
	    ch->address_format != CD_LBA_FORMAT)
		return EINVAL;
	if (ch->data_format != CD_CURRENT_POSITION &&
	    ch->data_format != CD_MEDIA_CATALOG)
		return EINVAL;

	if ((error = mcd_getqchan(sc, &q, ch->data_format)) != 0)
		return error;

	info->header.audio_status = sc->audio_status;
	info->what.media_catalog.data_format = ch->data_format;

	switch (ch->data_format) {
	case CD_MEDIA_CATALOG:
		info->what.media_catalog.mc_valid = 1;
#if 0
		info->what.media_catalog.mc_number =
#endif
		break;

	case CD_CURRENT_POSITION:
		info->what.position.track_number = bcd2bin(q.current.trk_no);
		info->what.position.index_number = bcd2bin(q.current.idx_no);
		switch (ch->address_format) {
		case CD_MSF_FORMAT:
			info->what.position.reladdr.addr[0] = 0;
			info->what.position.reladdr.addr[1] = bcd2bin(q.current.relative_pos[0]);
			info->what.position.reladdr.addr[2] = bcd2bin(q.current.relative_pos[1]);
			info->what.position.reladdr.addr[3] = bcd2bin(q.current.relative_pos[2]);
			info->what.position.absaddr.addr[0] = 0;
			info->what.position.absaddr.addr[1] = bcd2bin(q.current.absolute_pos[0]);
			info->what.position.absaddr.addr[2] = bcd2bin(q.current.absolute_pos[1]);
			info->what.position.absaddr.addr[3] = bcd2bin(q.current.absolute_pos[2]);
			break;
		case CD_LBA_FORMAT:
			lba = msf2hsg(q.current.relative_pos, 1);
			/*
			 * Pre-gap has index number of 0, and decreasing MSF
			 * address.  Must be converted to negative LBA, per
			 * SCSI spec.
			 */
			if (info->what.position.index_number == 0x00)
				lba = -lba;
			info->what.position.reladdr.addr[0] = lba >> 24;
			info->what.position.reladdr.addr[1] = lba >> 16;
			info->what.position.reladdr.addr[2] = lba >> 8;
			info->what.position.reladdr.addr[3] = lba;
			lba = msf2hsg(q.current.absolute_pos, 0);
			info->what.position.absaddr.addr[0] = lba >> 24;
			info->what.position.absaddr.addr[1] = lba >> 16;
			info->what.position.absaddr.addr[2] = lba >> 8;
			info->what.position.absaddr.addr[3] = lba;
			break;
		}
		break;
	}

	return 0;
}