Esempio n. 1
0
int
mcd_playtracks(struct mcd_softc *sc, struct ioc_play_track *p)
{
	struct mcd_mbox mbx;
	int a = p->start_track;
	int z = p->end_track;
	int error;

	if (sc->debug)
		printf("%s: playtracks: from %d:%d to %d:%d\n",
		    device_xname(sc->sc_dev),
		    a, p->start_index, z, p->end_index);

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

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

	mbx.cmd.opcode = MCD_CMDREADSINGLESPEED;
	mbx.cmd.length = sizeof(mbx.cmd.data.play);
	mbx.cmd.data.play.start_msf[0] = sc->toc[a].toc.absolute_pos[0];
	mbx.cmd.data.play.start_msf[1] = sc->toc[a].toc.absolute_pos[1];
	mbx.cmd.data.play.start_msf[2] = sc->toc[a].toc.absolute_pos[2];
	mbx.cmd.data.play.end_msf[0] = sc->toc[z+1].toc.absolute_pos[0];
	mbx.cmd.data.play.end_msf[1] = sc->toc[z+1].toc.absolute_pos[1];
	mbx.cmd.data.play.end_msf[2] = sc->toc[z+1].toc.absolute_pos[2];
	sc->lastpb = mbx.cmd;
	mbx.res.length = 0;
	return mcd_send(sc, &mbx, 1);
}
Esempio n. 2
0
int
mcd_getqchan(struct mcd_softc *sc, union mcd_qchninfo *q, int qchn)
{
	struct mcd_mbox mbx;
	int error;

	if (qchn == CD_TRACK_INFO) {
		if ((error = mcd_setmode(sc, MCD_MD_TOC)) != 0)
			return error;
	} else {
		if ((error = mcd_setmode(sc, MCD_MD_COOKED)) != 0)
			return error;
	}
	if (qchn == CD_MEDIA_CATALOG) {
		if ((error = mcd_setupc(sc, MCD_UPC_ENABLE)) != 0)
			return error;
	} else {
		if ((error = mcd_setupc(sc, MCD_UPC_DISABLE)) != 0)
			return error;
	}

	mbx.cmd.opcode = MCD_CMDGETQCHN;
	mbx.cmd.length = 0;
	mbx.res.length = sizeof(mbx.res.data.qchninfo);
	if ((error = mcd_send(sc, &mbx, 1)) != 0)
		return error;

	*q = mbx.res.data.qchninfo;
	return 0;
}
Esempio n. 3
0
int
mcd_playblocks(struct mcd_softc *sc, struct ioc_play_blocks *p)
{
	struct mcd_mbox mbx;
	int error;

	if (sc->debug)
		printf("%s: playblocks: blkno %d length %d\n",
		    device_xname(sc->sc_dev), p->blk, p->len);

	if (p->blk > sc->disksize || p->len > sc->disksize ||
	    (p->blk + p->len) > sc->disksize)
		return 0;

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

	mbx.cmd.opcode = MCD_CMDREADSINGLESPEED;
	mbx.cmd.length = sizeof(mbx.cmd.data.play);
	hsg2msf(p->blk, mbx.cmd.data.play.start_msf);
	hsg2msf(p->blk + p->len, mbx.cmd.data.play.end_msf);
	sc->lastpb = mbx.cmd;
	mbx.res.length = 0;
	return mcd_send(sc, &mbx, 1);
}
Esempio n. 4
0
int
mcd_get_parms(struct mcd_softc *sc)
{
	struct mcd_mbox mbx;
	daddr_t size;
	int error;

	/* Send volume info command. */
	mbx.cmd.opcode = MCD_CMDGETVOLINFO;
	mbx.cmd.length = 0;
	mbx.res.length = sizeof(mbx.res.data.volinfo);
	if ((error = mcd_send(sc, &mbx, 1)) != 0)
		return error;

	if (mbx.res.data.volinfo.trk_low == 0x00 &&
	    mbx.res.data.volinfo.trk_high == 0x00)
		return EINVAL;

	/* Volinfo is OK. */
	sc->volinfo = mbx.res.data.volinfo;
	sc->blksize = MCD_BLKSIZE_COOKED;
	size = msf2hsg(sc->volinfo.vol_msf, 0);
	sc->disksize = size * (MCD_BLKSIZE_COOKED / DEV_BSIZE);
	return 0;
}
Esempio n. 5
0
int
mcd_playmsf(struct mcd_softc *sc, struct ioc_play_msf *p)
{
	struct mcd_mbox mbx;
	int error;

	if (sc->debug)
		printf("%s: playmsf: from %d:%d.%d to %d:%d.%d\n",
		    device_xname(sc->sc_dev),
		    p->start_m, p->start_s, p->start_f,
		    p->end_m, p->end_s, p->end_f);

	if ((p->start_m * 60 * 75 + p->start_s * 75 + p->start_f) >=
	    (p->end_m * 60 * 75 + p->end_s * 75 + p->end_f))
		return EINVAL;

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

	mbx.cmd.opcode = MCD_CMDREADSINGLESPEED;
	mbx.cmd.length = sizeof(mbx.cmd.data.play);
	mbx.cmd.data.play.start_msf[0] = bin2bcd(p->start_m);
	mbx.cmd.data.play.start_msf[1] = bin2bcd(p->start_s);
	mbx.cmd.data.play.start_msf[2] = bin2bcd(p->start_f);
	mbx.cmd.data.play.end_msf[0] = bin2bcd(p->end_m);
	mbx.cmd.data.play.end_msf[1] = bin2bcd(p->end_s);
	mbx.cmd.data.play.end_msf[2] = bin2bcd(p->end_f);
	sc->lastpb = mbx.cmd;
	mbx.res.length = 0;
	return mcd_send(sc, &mbx, 1);
}
Esempio n. 6
0
File: mcd.c Progetto: MarginC/kame
static int
mcd_volinfo(struct mcd_softc *sc)
{

	/* Just return if we already have it */
	if (sc->data.flags & MCDVOLINFO) return (0);

/*MCD_TRACE("mcd_volinfo: enter\n",0,0,0,0);*/

	/* send volume info command */
	if (mcd_send(sc, MCD_CMDGETVOLINFO,MCD_RETRYS) < 0)
		return (EIO);

	/* get data */
	if (mcd_get(sc, (char*) &sc->data.volinfo,sizeof(struct mcd_volinfo)) < 0) {
		device_printf(sc->dev, "mcd_volinfo: error read data\n");
		return (EIO);
	}

	if (sc->data.volinfo.trk_low > 0 &&
	    sc->data.volinfo.trk_high >= sc->data.volinfo.trk_low
	   ) {
		sc->data.flags |= MCDVOLINFO;	/* volinfo is OK */
		return (0);
	}

	return (EINVAL);
}
Esempio n. 7
0
int
mcd_eject(struct mcd_softc *sc)
{
	struct mcd_mbox mbx;

	mbx.cmd.opcode = MCD_CMDEJECTDISK;
	mbx.cmd.length = 0;
	mbx.res.length = 0;
	return mcd_send(sc, &mbx, 0);
}
Esempio n. 8
0
int
mcd_getstat(struct mcd_softc *sc)
{
	struct mcd_mbox mbx;

	mbx.cmd.opcode = MCD_CMDGETSTAT;
	mbx.cmd.length = 0;
	mbx.res.length = 0;
	return mcd_send(sc, &mbx, 1);
}
Esempio n. 9
0
int
mcd_setlock(struct mcd_softc *sc, int mode)
{
	struct mcd_mbox mbx;

	mbx.cmd.opcode = MCD_CMDSETLOCK;
	mbx.cmd.length = sizeof(mbx.cmd.data.lockmode);
	mbx.cmd.data.lockmode.mode = mode;
	mbx.res.length = 0;
	return mcd_send(sc, &mbx, 1);
}
Esempio n. 10
0
int
mcd_hard_reset(struct mcd_softc *sc)
{
	struct mcd_mbox mbx;

	mcd_soft_reset(sc);

	mbx.cmd.opcode = MCD_CMDRESET;
	mbx.cmd.length = 0;
	mbx.res.length = 0;
	return mcd_send(sc, &mbx, 0);
}
Esempio n. 11
0
void
mcdattach(struct device *parent, struct device *self, void *aux)
{
	struct mcd_softc *sc = (void *)self;
	struct isa_attach_args *ia = aux;
	bus_space_tag_t iot = ia->ia_iot;
	bus_space_handle_t ioh;
	struct mcd_mbox mbx;

	/* Map i/o space */
	if (bus_space_map(iot, ia->ia_io[0].ir_addr, MCD_NPORT, 0, &ioh)) {
		printf(": can't map i/o space\n");
		return;
	}

	mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);

	sc->sc_iot = iot;
	sc->sc_ioh = ioh;

	sc->probe = 0;
	sc->debug = 0;

	if (!mcd_find(iot, ioh, sc)) {
		printf(": mcd_find failed\n");
		return;
	}

	bufq_alloc(&sc->buf_queue, "disksort", BUFQ_SORT_RAWBLOCK);
	callout_init(&sc->sc_pintr_ch, 0);

	/*
	 * Initialize and attach the disk structure.
	 */
	disk_init(&sc->sc_dk, device_xname(&sc->sc_dev), &mcddkdriver);
	disk_attach(&sc->sc_dk);

	printf(": model %s\n", sc->type != 0 ? sc->type : "unknown");

	(void) mcd_setlock(sc, MCD_LK_UNLOCK);

	mbx.cmd.opcode = MCD_CMDCONFIGDRIVE;
	mbx.cmd.length = sizeof(mbx.cmd.data.config) - 1;
	mbx.cmd.data.config.subcommand = MCD_CF_IRQENABLE;
	mbx.cmd.data.config.data1 = 0x01;
	mbx.res.length = 0;
	(void) mcd_send(sc, &mbx, 0);

	mcd_soft_reset(sc);

	sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
	    IST_EDGE, IPL_BIO, mcdintr, sc);
}
Esempio n. 12
0
int
mcd_resume(struct mcd_softc *sc)
{
	struct mcd_mbox mbx;
	int error;

	if (sc->audio_status != CD_AS_PLAY_PAUSED)
		return EINVAL;

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

	mbx.cmd = sc->lastpb;
	mbx.res.length = 0;
	return mcd_send(sc, &mbx, 1);
}
Esempio n. 13
0
int
mcd_stop(struct mcd_softc *sc)
{
	struct mcd_mbox mbx;
	int error;

	if (sc->debug)
		printf("%s: mcd_stop: stopping play\n", device_xname(sc->sc_dev));

	mbx.cmd.opcode = MCD_CMDSTOPAUDIO;
	mbx.cmd.length = 0;
	mbx.res.length = 0;
	if ((error = mcd_send(sc, &mbx, 1)) != 0)
		return error;

	sc->audio_status = CD_AS_PLAY_COMPLETED;
	return 0;
}
Esempio n. 14
0
File: mcd.c Progetto: MarginC/kame
static int
mcd_stop(struct mcd_softc *sc)
{

	/* Verify current status */
	if (sc->data.audio_status != CD_AS_PLAY_IN_PROGRESS &&
	    sc->data.audio_status != CD_AS_PLAY_PAUSED &&
	    sc->data.audio_status != CD_AS_PLAY_COMPLETED) {
		if (sc->data.debug)
			device_printf(sc->dev,
				"stop attempted when not playing, audio status %d\n",
				sc->data.audio_status);
		return (EINVAL);
	}
	if (sc->data.audio_status == CD_AS_PLAY_IN_PROGRESS)
		if (mcd_send(sc, MCD_CMDSTOPAUDIO, MCD_RETRYS) < 0)
			return (EIO);
	sc->data.audio_status = CD_AS_PLAY_COMPLETED;
	return (0);
}
Esempio n. 15
0
int
mcd_setmode(struct mcd_softc *sc, int mode)
{
	struct mcd_mbox mbx;
	int error;

	if (sc->lastmode == mode)
		return 0;
	if (sc->debug)
		printf("%s: setting mode to %d\n", device_xname(sc->sc_dev), mode);
	sc->lastmode = MCD_MD_UNKNOWN;

	mbx.cmd.opcode = MCD_CMDSETMODE;
	mbx.cmd.length = sizeof(mbx.cmd.data.datamode);
	mbx.cmd.data.datamode.mode = mode;
	mbx.res.length = 0;
	if ((error = mcd_send(sc, &mbx, 1)) != 0)
		return error;

	sc->lastmode = mode;
	return 0;
}
Esempio n. 16
0
File: mcd.c Progetto: MarginC/kame
static int
mcd_getqchan(struct mcd_softc *sc, struct mcd_qchninfo *q)
{

	if (mcd_send(sc, MCD_CMDGETQCHN, MCD_RETRYS) < 0)
		return (-1);
	if (mcd_get(sc, (char *) q, sizeof(struct mcd_qchninfo)) < 0)
		return (-1);
	if (sc->data.debug) {
		device_printf(sc->dev,
			"getqchan control=0x%x addr_type=0x%x trk=%d ind=%d ttm=%d:%d.%d dtm=%d:%d.%d\n",
			q->control, q->addr_type,
			bcd2bin(q->trk_no),
			bcd2bin(q->idx_no),
			bcd2bin(q->trk_size_msf[0]),
			bcd2bin(q->trk_size_msf[1]),
			bcd2bin(q->trk_size_msf[2]),
			bcd2bin(q->hd_pos_msf[0]),
			bcd2bin(q->hd_pos_msf[1]),
			bcd2bin(q->hd_pos_msf[2]));
	}
	return (0);
}
Esempio n. 17
0
int
mcd_setupc(struct mcd_softc *sc, int upc)
{
	struct mcd_mbox mbx;
	int error;

	if (sc->lastupc == upc)
		return 0;
	if (sc->debug)
		printf("%s: setting upc to %d\n", device_xname(sc->sc_dev), upc);
	sc->lastupc = MCD_UPC_UNKNOWN;

	mbx.cmd.opcode = MCD_CMDCONFIGDRIVE;
	mbx.cmd.length = sizeof(mbx.cmd.data.config) - 1;
	mbx.cmd.data.config.subcommand = MCD_CF_READUPC;
	mbx.cmd.data.config.data1 = upc;
	mbx.res.length = 0;
	if ((error = mcd_send(sc, &mbx, 1)) != 0)
		return error;

	sc->lastupc = upc;
	return 0;
}
Esempio n. 18
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. 19
0
/*
 * Find the board and fill in the softc.
 */
int
mcd_find(bus_space_tag_t iot, bus_space_handle_t ioh, struct mcd_softc *sc)
{
	int i;
	struct mcd_mbox mbx;

        sc->sc_iot = iot;
	sc->sc_ioh = ioh;

	/* Send a reset. */
	bus_space_write_1(iot, ioh, MCD_RESET, 0);
	delay(1000000);
	/* Get any pending status and throw away. */
	for (i = 10; i; i--)
		bus_space_read_1(iot, ioh, MCD_STATUS);
	delay(1000);

	/* Send get status command. */
	mbx.cmd.opcode = MCD_CMDGETSTAT;
	mbx.cmd.length = 0;
	mbx.res.length = 0;
	if (mcd_send(sc, &mbx, 0) != 0)
		return 0;

	/* Get info about the drive. */
	mbx.cmd.opcode = MCD_CMDCONTINFO;
	mbx.cmd.length = 0;
	mbx.res.length = sizeof(mbx.res.data.continfo);
	if (mcd_send(sc, &mbx, 0) != 0)
		return 0;

	/*
	 * The following is code which is not guaranteed to work for all
	 * drives, because the meaning of the expected 'M' is not clear
	 * (M_itsumi is an obvious assumption, but I don't trust that).
	 * Also, the original hack had a bogus condition that always
	 * returned true.
	 *
	 * Note:  Which models support interrupts?  >=LU005S?
	 */
	sc->readcmd = MCD_CMDREADSINGLESPEED;
	switch (mbx.res.data.continfo.code) {
	case 'M':
		if (mbx.res.data.continfo.version <= 2)
			sc->type = "LU002S";
		else if (mbx.res.data.continfo.version <= 5)
			sc->type = "LU005S";
		else
			sc->type = "LU006S";
		break;
	case 'F':
		sc->type = "FX001";
		break;
	case 'D':
		sc->type = "FX001D";
		sc->readcmd = MCD_CMDREADDOUBLESPEED;
		break;
	default:
		/*
		 * mcd_send() says the  response looked OK but the
		 * drive type is unknown. If mcd_promisc,  match anyway.
		 */
		if (mcd_promisc != 0)
			return 0;

#ifdef MCDDEBUG
		printf("%s: unrecognized drive version %c%02x; will try to use it anyway\n",
		    device_xname(sc->sc_dev),
		    mbx.res.data.continfo.code, mbx.res.data.continfo.version);
#endif
		sc->type = 0;
		break;
	}

	return 1;

}