Пример #1
0
Файл: mcd.c Проект: MarginC/kame
static int
mcd_playtracks(struct mcd_softc *sc, struct ioc_play_track *pt)
{
	struct mcd_read2 pb;
	int a = pt->start_track;
	int z = pt->end_track;
	int rc, i;

	if ((rc = mcd_read_toc(sc)) != 0)
		return (rc);

	if (sc->data.debug)
		device_printf(sc->dev, "playtracks from %d:%d to %d:%d\n",
			a, pt->start_index, z, pt->end_index);

	if (   a < bcd2bin(sc->data.volinfo.trk_low)
	    || a > bcd2bin(sc->data.volinfo.trk_high)
	    || a > z
	    || z < bcd2bin(sc->data.volinfo.trk_low)
	    || z > bcd2bin(sc->data.volinfo.trk_high))
		return (EINVAL);

	for (i = 0; i < 3; i++) {
		pb.start_msf[i] = sc->data.toc[a].hd_pos_msf[i];
		pb.end_msf[i] = sc->data.toc[z+1].hd_pos_msf[i];
	}

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

	return mcd_play(sc, &pb);
}
Пример #2
0
Файл: mcd.c Проект: MarginC/kame
static int
mcdopen(dev_t dev, int flags, int fmt, struct thread *td)
{
	struct mcd_softc *sc;
	int r,retry;

	sc = (struct mcd_softc *)dev->si_drv1;

	/* not initialized*/
	if (!(sc->data.flags & MCDINIT))
		return (ENXIO);

	/* invalidated in the meantime? mark all open part's invalid */
	if (!(sc->data.flags & MCDVALID) && sc->data.openflags)
		return (ENXIO);

	if (mcd_getstat(sc, 1) == -1)
		return (EIO);

	if (    (sc->data.status & (MCDDSKCHNG|MCDDOOROPEN))
	    || !(sc->data.status & MCDDSKIN))
		for (retry = 0; retry < DISK_SENSE_SECS * WAIT_FRAC; retry++) {
			(void) tsleep((caddr_t)sc, PSOCK | PCATCH, "mcdsn1", hz/WAIT_FRAC);
			if ((r = mcd_getstat(sc, 1)) == -1)
				return (EIO);
			if (r != -2)
				break;
		}

	if (sc->data.status & MCDDOOROPEN) {
		device_printf(sc->dev, "door is open\n");
		return (ENXIO);
	}
	if (!(sc->data.status & MCDDSKIN)) {
		device_printf(sc->dev, "no CD inside\n");
		return (ENXIO);
	}
	if (sc->data.status & MCDDSKCHNG) {
		device_printf(sc->dev, "CD not sensed\n");
		return (ENXIO);
	}

	if (mcdsize(dev) < 0) {
		device_printf(sc->dev, "failed to get disk size\n");
		return (ENXIO);
	}

	dev->si_bsize_phys = sc->data.blksize;

	sc->data.openflags = 1;
	sc->data.partflags |= MCDREADRAW;
	sc->data.flags |= MCDVALID;

	(void) mcd_lock_door(sc, MCD_LK_LOCK);
	if (!(sc->data.flags & MCDVALID))
		return (ENXIO);

	return mcd_read_toc(sc);
}
Пример #3
0
Файл: mcd.c Проект: MarginC/kame
static int
mcd_toc_entry(struct mcd_softc *sc, struct ioc_read_toc_single_entry *te)
{
	struct ioc_toc_header th;
	int rc, trk;

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

	/* Copy the toc header */
	if ((rc = mcd_toc_header(sc, &th)) != 0)
		return (rc);

	/* verify starting track */
	trk = te->track;
	if (trk == 0)
		trk = th.starting_track;
	else if (trk == MCD_LASTPLUS1)
		trk = th.ending_track + 1;
	else if (trk < th.starting_track || trk > th.ending_track + 1)
		return (EINVAL);

	/* Make sure we have a valid toc */
	if ((rc=mcd_read_toc(sc)) != 0)
		return (rc);

	/* Copy the TOC data. */
	if (sc->data.toc[trk].idx_no == 0)
		return (EIO);

	te->entry.control = sc->data.toc[trk].control;
	te->entry.addr_type = sc->data.toc[trk].addr_type;
	te->entry.track =
		sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no :
		bcd2bin(sc->data.toc[trk].idx_no);
	switch (te->address_format) {
	case CD_MSF_FORMAT:
		te->entry.addr.msf.unused = 0;
		te->entry.addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0]);
		te->entry.addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1]);
		te->entry.addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2]);
		break;
	case CD_LBA_FORMAT:
		te->entry.addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0));
		break;
	}
	return (0);
}
Пример #4
0
Файл: mcd.c Проект: MarginC/kame
static int
mcd_toc_entrys(struct mcd_softc *sc, struct ioc_read_toc_entry *te)
{
	struct cd_toc_entry entries[MCD_MAXTOCS];
	struct ioc_toc_header th;
	int rc, n, trk, len;

	if (   te->data_len < sizeof(entries[0])
	    || (te->data_len % sizeof(entries[0])) != 0
	    || (te->address_format != CD_MSF_FORMAT
	        && te->address_format != CD_LBA_FORMAT)
	   )
		return (EINVAL);

	/* Copy the toc header */
	if ((rc = mcd_toc_header(sc, &th)) != 0)
		return (rc);

	/* verify starting track */
	trk = te->starting_track;
	if (trk == 0)
		trk = th.starting_track;
	else if (trk == MCD_LASTPLUS1)
		trk = th.ending_track + 1;
	else if (trk < th.starting_track || trk > th.ending_track + 1)
		return (EINVAL);

	len = ((th.ending_track + 1 - trk) + 1) *
		sizeof(entries[0]);
	if (te->data_len < len)
		len = te->data_len;
	if (len > sizeof(entries))
		return (EINVAL);

	/* Make sure we have a valid toc */
	if ((rc=mcd_read_toc(sc)) != 0)
		return (rc);

	/* Copy the TOC data. */
	for (n = 0; len > 0 && trk <= th.ending_track + 1; trk++) {
		if (sc->data.toc[trk].idx_no == 0)
			continue;
		entries[n].control = sc->data.toc[trk].control;
		entries[n].addr_type = sc->data.toc[trk].addr_type;
		entries[n].track =
			sc->data.toc[trk].idx_no > 0x99 ? sc->data.toc[trk].idx_no :
			bcd2bin(sc->data.toc[trk].idx_no);
		switch (te->address_format) {
		case CD_MSF_FORMAT:
			entries[n].addr.msf.unused = 0;
			entries[n].addr.msf.minute = bcd2bin(sc->data.toc[trk].hd_pos_msf[0]);
			entries[n].addr.msf.second = bcd2bin(sc->data.toc[trk].hd_pos_msf[1]);
			entries[n].addr.msf.frame = bcd2bin(sc->data.toc[trk].hd_pos_msf[2]);
			break;
		case CD_LBA_FORMAT:
			entries[n].addr.lba = htonl(msf2hsg(sc->data.toc[trk].hd_pos_msf, 0));
			break;
		}
		len -= sizeof(struct cd_toc_entry);
		n++;
	}

	/* copy the data back */
	return copyout(entries, te->data, n * sizeof(struct cd_toc_entry));
}
Пример #5
0
int
mcdopen(dev_t dev, int flag, int fmt, struct lwp *l)
{
	int error, part;
	struct mcd_softc *sc;

	sc = device_lookup_private(&mcd_cd, MCDUNIT(dev));
	if (sc == NULL)
		return ENXIO;

	mutex_enter(&sc->sc_lock);

	if (sc->sc_dk.dk_openmask != 0) {
		/*
		 * If any partition is open, but the disk has been invalidated,
		 * disallow further opens.
		 */
		if ((sc->flags & MCDF_LOADED) == 0) {
			error = EIO;
			goto bad3;
		}
	} else {
		/*
		 * Lock the drawer.  This will also notice any pending disk
		 * change or door open indicator and clear the MCDF_LOADED bit
		 * if necessary.
		 */
		(void) mcd_setlock(sc, MCD_LK_LOCK);

		if ((sc->flags & MCDF_LOADED) == 0) {
			/* Partially reset the state. */
			sc->lastmode = MCD_MD_UNKNOWN;
			sc->lastupc = MCD_UPC_UNKNOWN;

			sc->flags |= MCDF_LOADED;

			/* Set the mode, causing the disk to spin up. */
			if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
				goto bad2;

			/* Load the physical device parameters. */
			if (mcd_get_parms(sc) != 0) {
				error = ENXIO;
				goto bad2;
			}

			/* Read the table of contents. */
			if ((error = mcd_read_toc(sc)) != 0)
				goto bad2;

			/* Fabricate a disk label. */
			mcdgetdisklabel(sc);
		}
	}

	part = MCDPART(dev);

	MCD_TRACE("open: partition=%d disksize=%ld blksize=%d\n", part,
	    sc->disksize, sc->blksize);

	/* Check that the partition exists. */
	if (part != RAW_PART &&
	    (part >= sc->sc_dk.dk_label->d_npartitions ||
	     sc->sc_dk.dk_label->d_partitions[part].p_fstype == FS_UNUSED)) {
		error = ENXIO;
		goto bad;
	}

	/* Insure only one open at a time. */
	switch (fmt) {
	case S_IFCHR:
		sc->sc_dk.dk_copenmask |= (1 << part);
		break;
	case S_IFBLK:
		sc->sc_dk.dk_bopenmask |= (1 << part);
		break;
	}
	sc->sc_dk.dk_openmask = sc->sc_dk.dk_copenmask | sc->sc_dk.dk_bopenmask;

	mutex_exit(&sc->sc_lock);
	return 0;

bad2:
	sc->flags &= ~MCDF_LOADED;

bad:
	if (sc->sc_dk.dk_openmask == 0) {
#if 0
		(void) mcd_setmode(sc, MCD_MD_SLEEP);
#endif
		(void) mcd_setlock(sc, MCD_LK_UNLOCK);
	}

bad3:
	mutex_exit(&sc->sc_lock);
	return error;
}