9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
* [9fans] Errors Writing To CD-R
@ 2002-04-22  8:41 Christopher Nielsen
  0 siblings, 0 replies; 4+ messages in thread
From: Christopher Nielsen @ 2002-04-22  8:41 UTC (permalink / raw)
  To: 9fans

I have a cpu server that i'm trying to use to write audio tracks
to a CD-R using cdfs. When writing to the CD-R, I'm receiving the
following error:

cp: error writing /mnt/cdrw/wa/a000: cmd #2a: write error - recovery needed

I've poked around a bit in the source, but I haven't been able
to find what might be causing this error.

The CDRW is a Plextor PX-W1610A.

Any ideas on what the problem might be?

--
Christopher Nielsen - Metal-wielding pyro techie
cnielsen@pobox.com
"Those who are willing to trade freedom for security deserve
 neither freedom nor security." --Benjamin Franklin


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9fans] Errors Writing To CD-R
@ 2002-04-22 16:42 forsyth
  0 siblings, 0 replies; 4+ messages in thread
From: forsyth @ 2002-04-22 16:42 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 327 bytes --]

>>here's a temporary replacement for /sys/src/cmd/cdfs/mmc.c
>>that supports speed control through the ctl file.  i've used it
>>to write CDs on a fairly cheap ATAPI CD-RW drive.

 Include: apparently messed up that gzip'd version.  let's try again.
here's the text.
i only gzip'd it to hide it from gateway mangling.


[-- Attachment #2: Type: message/rfc822, Size: 17170 bytes --]



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2.1: Type: text/plain, Size: 17078 bytes --]


enum
{
	Pagesz		= 255,
};

static Dev mmcdev;

typedef struct Mmcaux Mmcaux;
struct Mmcaux {
	uchar page05[Pagesz];
	int page05ok;

	int pagecmdsz;
	ulong mmcnwa;

	int nropen;
	int nwopen;
	long ntotby;
	long ntotbk;
};

static ulong
bige(void *p)
{
	uchar *a;

	a = p;
	return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);
}

static ushort
biges(void *p)
{
	uchar *a;

	a = p;
	return (a[0]<<8) | a[1];
}

static void
hexdump(void *v, int n)
{
	int i;
	uchar *p;

	p = v;
	for(i=0; i<n; i++){
		print("%.2ux ", p[i]);
		if((i%8) == 7)
			print("\n");
	}
	if(i%8)
		print("\n");
}

static int
mmcgetpage10(Drive *drive, int page, void *v)
{
	uchar cmd[10], resp[512];
	int n, r;

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x5A;
	cmd[2] = page;
	cmd[8] = 255;
	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
	if(n < 8)
		return -1;

	r = (resp[6]<<8) | resp[7];
	n -= 8+r;

	if(n < 0)
		return -1;
	if(n > Pagesz)
		n = Pagesz;

	memmove(v, &resp[8+r], n);
	return n;
}

static int
mmcgetpage6(Drive *drive, int page, void *v)
{
	uchar cmd[6], resp[512];
	int n;

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x1A;
	cmd[2] = page;
	cmd[4] = 255;
	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
	if(n < 4)
		return -1;

	n -= 4+resp[3];
	if(n < 0)
		return -1;
	if(n > Pagesz)
		n = Pagesz;

	memmove(v, &resp[4+resp[3]], n);
	return n;
}

static int
mmcsetpage10(Drive *drive, int page, void *v)
{
	uchar cmd[10], *p, *pagedata;
	int len, n;

	pagedata = v;
	assert(pagedata[0] == page);
	len = 8+2+pagedata[1];
	p = emalloc(len);
	memmove(p+8, pagedata, pagedata[1]);
	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x55;
	cmd[1] = 0x10;
	cmd[8] = len;

//	print("cmd\n");
//	hexdump(cmd, 10);
//	print("page\n");
//	hexdump(p, len);

	n = scsi(drive, cmd, sizeof(cmd), p, len, Swrite);
	free(p);
	if(n < len)
		return -1;
	return 0;
}

static int
mmcsetpage6(Drive *drive, int page, void *v)
{
	uchar cmd[6], *p, *pagedata;
	int len, n;

	pagedata = v;
	assert(pagedata[0] == page);
	len = 4+2+pagedata[1];
	p = emalloc(len);
	memmove(p+4, pagedata, pagedata[1]);
	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x15;
	cmd[1] = 0x10;
	cmd[4] = len;

	n = scsi(drive, cmd, sizeof(cmd), p, len, Swrite);
	free(p);
	if(n < len)
		return -1;
	return 0;
}

static int
mmcgetpage(Drive *drive, int page, void *v)
{
	Mmcaux *aux;

	aux = drive->aux;
	switch(aux->pagecmdsz) {
	case 10:
		return mmcgetpage10(drive, page, v);
	case 6:
		return mmcgetpage6(drive, page, v);
	default:
		assert(0);
	}
	return -1;
}

static int
mmcsetpage(Drive *drive, int page, void *v)
{
	Mmcaux *aux;

	aux = drive->aux;
	switch(aux->pagecmdsz) {
	case 10:
		return mmcsetpage10(drive, page, v);
	case 6:
		return mmcsetpage6(drive, page, v);
	default:
		assert(0);
	}
	return -1;
}

int
mmcstatus(Drive *drive)
{
	uchar cmd[12];

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0xBD;
	return scsi(drive, cmd, sizeof(cmd), nil, 0, Sread);
}

Drive*
mmcprobe(Scsi *scsi)
{
	Mmcaux *aux;
	Drive *drive;
	uchar buf[Pagesz];
	int cap;

	/* BUG: confirm mmc better? */

	drive = emalloc(sizeof(Drive));
	drive->Scsi = *scsi;
	drive->Dev = mmcdev;
	aux = emalloc(sizeof(Mmcaux));
	drive->aux = aux;

	/* attempt to read CD capabilities page */
	if(mmcgetpage10(drive, 0x2A, buf) >= 0)
		aux->pagecmdsz = 10;
	else if(mmcgetpage6(drive, 0x2A, buf) >= 0)
		aux->pagecmdsz = 6;
	else {
		werrstr("not an mmc device");
		free(drive);
		return nil;
	}

	cap = 0;
	if(buf[3] & 3)	/* 2=cdrw, 1=cdr */
		cap |= Cwrite;
	if(buf[5] & 1)
		cap |= Ccdda;

//	print("read %d max %d\n", biges(buf+14), biges(buf+8));
//	print("write %d max %d\n", biges(buf+20), biges(buf+18));

	/* cache page 05 (write parameter page) */
	if((cap & Cwrite) && mmcgetpage(drive, 0x05, aux->page05) >= 0)
		aux->page05ok = 1;
	else
		cap &= ~Cwrite;

	drive->cap = cap;

	return drive;
}

static int
mmctrackinfo(Drive *drive, int t, int i)
{
	uchar cmd[10], resp[255];
	int n, type, bs;
	uchar tmode;
	ulong beg, size;
	Mmcaux *aux;

	aux = drive->aux;
	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x52;	/* get track info */
	cmd[1] = 1;
	cmd[2] = t>>24;
	cmd[3] = t>>16;
	cmd[4] = t>>8;
	cmd[5] = t;
	cmd[7] = sizeof(resp)>>8;
	cmd[8] = sizeof(resp);
	n = scsi(drive, cmd, sizeof(cmd), resp, sizeof(resp), Sread);
	if(n < 28) {
		if(vflag)
			print("trackinfo %d fails n=%d %r\n", t, n);
		return -1;
	}

	beg = bige(&resp[8]);
	size = bige(&resp[24]);

	tmode = resp[5] & 0x0D;
//	dmode = resp[6] & 0x0F;

	if(vflag)
		print("track %d type 0x%x\n", t, tmode);
	type = TypeNone;
	bs = BScdda;
	switch(tmode){
	case 0:
		type = TypeAudio;
		bs = BScdda;
		break;
	case 1:	/* 2 audio channels, with pre-emphasis 50/15 μs */
		if(vflag)
			print("audio channels with preemphasis on track %d (u%.3d)\n", t, i);
		type = TypeNone;
		break;
	case 4:	/* data track, recorded uninterrupted */
		type = TypeData;
		bs = BScdrom;
		break;
	case 5:	/* data track, recorded interrupted */
	default:
		if(vflag)
			print("unknown track type %d\n", tmode);
	}

	drive->track[i].mtime = drive->changetime;
	drive->track[i].beg = beg;
	drive->track[i].end = beg+size;
	drive->track[i].type = type;
	drive->track[i].bs = bs;
	drive->track[i].size = (vlong)(size-2)*bs;	/* -2: skip lead out */

	if(resp[6] & (1<<6)) {
		drive->track[i].type = TypeBlank;
		drive->writeok = 1;
	}

	if(t == 0xFF)
		aux->mmcnwa = bige(&resp[12]);

	return 0;
}

static int
mmcreadtoc(Drive *drive, int track, void *data, int nbytes)
{
	uchar cmd[10];

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x43;
	cmd[6] = track;
	cmd[7] = nbytes>>8;
	cmd[8] = nbytes;

	return scsi(drive, cmd, sizeof(cmd), data, nbytes, Sread);
}

static int
mmcreaddiscinfo(Drive *drive, void *data, int nbytes)
{
	uchar cmd[10];
	int n;

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x51;
	cmd[7] = nbytes>>8;
	cmd[8] = nbytes;
	n = scsi(drive, cmd, sizeof(cmd), data, nbytes, Sread);
	if(n < 24) {
		if(n >= 0)
			werrstr("rdiscinfo returns %d", n);
		return -1;
	}

	return n;
}

static int
mmcgettoc(Drive *drive)
{
	uchar resp[32];
	int i, first, last;
	ulong tot;
	Track *t;

	/*
	 * if someone has swapped the cd,
	 * mmcreadtoc will get ``medium changed'' and the
	 * scsi routines will set nchange and changetime in the
	 * scsi device.
	 */
	mmcreadtoc(drive, 0, resp, sizeof(resp));
	if(drive->Scsi.changetime == 0) {	/* no media present */
		drive->ntrack = 0;
		return 0;
	}

	if(drive->nchange == drive->Scsi.nchange && drive->changetime != 0)
		return 0;

	drive->ntrack = 0;
	drive->nameok = 0;
	drive->nchange = drive->Scsi.nchange;
	drive->changetime = drive->Scsi.changetime;
	drive->writeok = 0;

	/*
	 * find number of tracks
	 */
	if(mmcreadtoc(drive, 0, resp, sizeof(resp)) < 4) {
		/*
		 * on a blank disc in a cd-rw, use readdiscinfo
		 * to find the track info.
		 */
		if(mmcreaddiscinfo(drive, resp, sizeof(resp)) < 0)
			return -1;
		if(resp[4] != 1)
			print("multi-session disc %d\n", resp[4]);
		first = resp[3];
		last = resp[6];
		if(vflag)
			print("blank disc %d %d\n", first, last);
		drive->writeok = 1;
	} else {
		first = resp[2];
		last = resp[3];
	}

	if(vflag)
		print("first %d last %d\n", first, last);

	if(first == 0 && last == 0)
		first = 1;

	if(first <= 0 || first >= Maxtrack) {
		werrstr("first table %d not in range", first);
		return -1;
	}
	if(last <= 0 || last >= Maxtrack) {
		werrstr("last table %d not in range", last);
		return -1;
	}

	if(drive->cap & Cwrite) {	/* CDR drives are easy */
		for(i = first; i <= last; i++)
			mmctrackinfo(drive, i, i-first);
	} else {
		/*
		 * otherwise we need to infer endings from the
		 * beginnings of other tracks.
		 */
		for(i = first; i <= last; i++) {
			memset(resp, 0, sizeof(resp));
			if(mmcreadtoc(drive, i, resp, sizeof(resp)) < 0)
				break;
			t = &drive->track[i-first];
			t->mtime = drive->changetime;
			t->type = TypeData;
			t->bs = BScdrom;
			t->beg = bige(resp+8);
			if(!(resp[5] & 4)) {
				t->type = TypeAudio;
				t->bs = BScdda;
			}
		}

		if((long)drive->track[0].beg < 0)	/* i've seen negative track 0's */
			drive->track[0].beg = 0;

		tot = 0;
		memset(resp, 0, sizeof(resp));
		if(mmcreadtoc(drive, 0xAA, resp, sizeof(resp)) < 0)
			print("bad\n");
		if(resp[6])
			tot = bige(resp+8);

		for(i=last; i>=first; i--) {
			t = &drive->track[i-first];
			t->end = tot;
			tot = t->beg;
			if(t->end <= t->beg) {
				t->beg = 0;
				t->end = 0;
			}
			t->size = (t->end - t->beg - 2) * (vlong)t->bs;	/* -2: skip lead out */
		}
	}

	drive->firsttrack = first;
	drive->ntrack = last+1-first;
	return 0;
}

static int
mmcsetbs(Drive *drive, int bs)
{
	uchar *p;
	Mmcaux *aux;

	aux = drive->aux;

	assert(aux->page05ok);

	p = aux->page05;
	p[2] = 0x01;				/* track-at-once */
//	if(xflag)
//		p[2] |= 0x10;			/* test-write */

	switch(bs){
	case BScdrom:
		p[3] = (p[3] & ~0x07)|0x04;	/* data track, uninterrupted */
		p[4] = 0x08;			/* mode 1 CD-ROM */
		p[8] = 0;			/* session format CD-DA or CD-ROM */
		break;

	case BScdda:
		p[3] = (p[3] & ~0x07)|0x00;	/* 2 audio channels without pre-emphasis */
		p[4] = 0x00;			/* raw data */
		p[8] = 0;			/* session format CD-DA or CD-ROM */
		break;

	case BScdxa:
		p[3] = (p[3] & ~0x07)|0x04;	/* data track, uninterrupted */
		p[4] = 0x09;			/* mode 2 */
		p[8] = 0x20;			/* session format CD-ROM XA */
		break;

	default:
		assert(0);
	}

	if(mmcsetpage(drive, 0x05, p) < 0)
		return -1;
}

static long
mmcread(Buf *buf, void *v, long nblock, long off)
{
	Drive *drive;
	int bs;
	uchar cmd[12];
	long n, nn;
	Otrack *o;

	o = buf->otrack;
	drive = o->drive;
	bs = o->track->bs;
	off += o->track->beg;

	if(nblock >= (1<<10)) {
		werrstr("mmcread too big");
		if(vflag)
			fprint(2, "mmcread too big\n");
		return -1;
	}

	/* truncate nblock modulo size of track */
	if(off > o->track->end - 2) {
		werrstr("read past end of track");
		if(vflag)
			fprint(2, "end of track (%ld->%ld off %ld)", o->track->beg, o->track->end-2, off);
		return -1;
	}
	if(off == o->track->end - 2)
		return 0;

	if(off+nblock > o->track->end - 2)
		nblock = o->track->end - 2 - off;

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0xBE;
	cmd[2] = off>>24;
	cmd[3] = off>>16;
	cmd[4] = off>>8;
	cmd[5] = off>>0;
	cmd[6] = nblock>>16;
	cmd[7] = nblock>>8;
	cmd[8] = nblock>>0;
	cmd[9] = 0x10;

	switch(bs){
	case BScdda:
		cmd[1] = 0x04;
		break;

	case BScdrom:
		cmd[1] = 0x08;
		break;

	case BScdxa:
		cmd[1] = 0x0C;
		break;

	default:
		werrstr("unknown bs %d", bs);
		return -1;
	}

	n = nblock*bs;
	nn = scsi(drive, cmd, sizeof(cmd), v, n, Sread);
	if(nn != n) {
		werrstr("short read %ld/%ld", nn, n);
		if(vflag)
			print("read off %lud nblock %ld bs %d failed\n", off, nblock, bs);
		return -1;
	}

	return nblock;
}

static Otrack*
mmcopenrd(Drive *drive, int trackno)
{
	Otrack *o;
	Mmcaux *aux;

	if(trackno < 0 || trackno >= drive->ntrack) {
		werrstr("track number out of range");
		return nil;
	}

	aux = drive->aux;
	if(aux->nwopen) {
		werrstr("disk in use for writing");
		return nil;
	}

	o = emalloc(sizeof(Otrack));
	o->drive = drive;
	o->track = &drive->track[trackno];
	o->nchange = drive->nchange;
	o->omode = OREAD;
	o->buf = bopen(mmcread, OREAD, o->track->bs, Nblock);
	o->buf->otrack = o;

	aux->nropen++;

	return o;
}

static long
mmcxwrite(Otrack *o, void *v, long nblk)
{
	uchar cmd[10];
	Mmcaux *aux;

	assert(o->omode == OWRITE);

	aux = o->drive->aux;
	aux->ntotby += nblk*o->track->bs;
	aux->ntotbk += nblk;
	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x2a;	/* write */
	cmd[2] = aux->mmcnwa>>24;
	cmd[3] = aux->mmcnwa>>16;
	cmd[4] = aux->mmcnwa>>8;
	cmd[5] = aux->mmcnwa;
	cmd[7] = nblk>>8;
	cmd[8] = nblk>>0;
	if(vflag)
		print("%lld: write %ld at 0x%lux\n", nsec(), nblk, aux->mmcnwa);
	aux->mmcnwa += nblk;
	return scsi(o->drive, cmd, sizeof(cmd), v, nblk*o->track->bs, Swrite);
}

static long
mmcwrite(Buf *buf, void *v, long nblk, long)
{
	return mmcxwrite(buf->otrack, v, nblk);
}

static Otrack*
mmccreate(Drive *drive, int type)
{
	int bs;
	Mmcaux *aux;
	Track *t;
	Otrack *o;

	aux = drive->aux;

	if(aux->nropen || aux->nwopen) {
		werrstr("drive in use");
		return nil;
	}

	switch(type){
	case TypeAudio:
		bs = BScdda;
		break;
	case TypeData:
		bs = BScdrom;
		break;
	default:
		werrstr("bad type %d", type);
		return nil;
	}

	if(mmctrackinfo(drive, 0xFF, Maxtrack)) {		/* the invisible track */
		werrstr("CD not writable");
		return nil;
	}
	if(mmcsetbs(drive, bs) < 0) {
		werrstr("cannot set bs mode");
		return nil;
	}
	if(mmctrackinfo(drive, 0xFF, Maxtrack)) {		/* the invisible track */
		werrstr("CD not writable 2");
		return nil;
	}

	aux->ntotby = 0;
	aux->ntotbk = 0;

	t = &drive->track[drive->ntrack++];
	t->size = 0;
	t->bs = bs;
	t->beg = aux->mmcnwa;
	t->end = 0;
	t->type = type;
	drive->nameok = 0;

	o = emalloc(sizeof(Otrack));
	o->drive = drive;
	o->nchange = drive->nchange;
	o->omode = OWRITE;
	o->track = t;
	o->buf = bopen(mmcwrite, OWRITE, bs, Nblock);
	o->buf->otrack = o;

	aux->nwopen++;

	if(vflag)
		print("mmcinit: nwa = 0x%luX\n", aux->mmcnwa);

	return o;
}

void
mmcsynccache(Drive *drive)
{
	uchar cmd[10];
	Mmcaux *aux;

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x35;	/* flush */
	scsi(drive, cmd, sizeof(cmd), cmd, 0, Snone);
	if(vflag) {
		aux = drive->aux;
		print("mmcsynccache: bytes = %ld blocks = %ld, mmcnwa 0x%luX\n",
			aux->ntotby, aux->ntotbk, aux->mmcnwa);
	}
/* rsc: seems not to work on some drives; 	mmcclose(1, 0xFF); */
}

static void
mmcclose(Otrack *o)
{
	Mmcaux *aux;
	static uchar zero[2*BSmax];

	aux = o->drive->aux;
	if(o->omode == OREAD)
		aux->nropen--;
	else if(o->omode == OWRITE) {
		aux->nwopen--;
		mmcxwrite(o, zero, 2);	/* write lead out */
		mmcsynccache(o->drive);
		o->drive->nchange = -1;	/* force reread toc */
	}
	free(o);
}

static int
mmcxclose(Drive *drive, int ts, int trackno)
{
	uchar cmd[10];

	/*
	 * ts: 1 == track, 2 == session
	 */
	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x5B;
	cmd[2] = ts;
	if(ts == 1)
		cmd[5] = trackno;
	return scsi(drive, cmd, sizeof(cmd), cmd, 0, Snone);
}

static int
mmcfixate(Drive *drive)
{
	uchar *p;
	Mmcaux *aux;

	if((drive->cap & Cwrite) == 0) {
		werrstr("not a writer");
		return -1;
	}

	drive->nchange = -1;	/* force reread toc */

	aux = drive->aux;
	p = aux->page05;
	p[3] = (p[3] & ~0xC0);
	if(mmcsetpage(drive, 0x05, p) < 0)
		return -1;

/* rsc: seems not to work on some drives; 	mmcclose(1, 0xFF); */
	return mmcxclose(drive, 0x02, 0);
}

static int
mmcsession(Drive *drive)
{
	uchar *p;
	Mmcaux *aux;

	drive->nchange = -1;	/* force reread toc */

	aux = drive->aux;
	p = aux->page05;
	p[3] = (p[3] & ~0xC0);
	if(mmcsetpage(drive, 0x05, p) < 0)
		return -1;

/* rsc: seems not to work on some drives; 	mmcclose(1, 0xFF); */
	return mmcxclose(drive, 0x02, 0);
}

static int
mmcblank(Drive *drive, int quick)
{
	uchar cmd[12];

	drive->nchange = -1;	/* force reread toc */

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0xA1;	/* blank */
	/* cmd[1] = 0 means blank the whole disc; = 1 just the header */
	cmd[1] = quick ? 0x01 : 0x00;

	return scsi(drive, cmd, sizeof(cmd), cmd, 0, Snone);
}

static int
start(Drive *drive, int code)
{
	uchar cmd[6];

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0x1B;
	cmd[4] = code;
	return scsi(drive, cmd, sizeof(cmd), cmd, 0, Snone);
}

static int
setspeed(Drive *drive, int rspeed, int wspeed)
{
	uchar cmd[12];

	memset(cmd, 0, sizeof(cmd));
	cmd[0] = 0xBB;
	cmd[2] = rspeed>>8;
	cmd[3] = rspeed;
	cmd[4] = wspeed>>8;
	cmd[5] = wspeed;
	return scsi(drive, cmd, sizeof(cmd), cmd, 0, Snone);
}

static char*
e(int status)
{
	if(status < 0)
		return geterrstr();
	return nil;
}

static char*
mmcctl(Drive *drive, int argc, char **argv)
{
	if(argc < 1)
		return nil;

	if(strcmp(argv[0], "blank") == 0)
		return e(mmcblank(drive, 0));
	if(strcmp(argv[0], "quickblank") == 0)
		return e(mmcblank(drive, 1));
	if(strcmp(argv[0], "eject") == 0)
		return e(start(drive, 2));
	if(strcmp(argv[0], "ingest") == 0)
		return e(start(drive, 3));
	if(strcmp(argv[0], "wspeed") == 0)
		return e(setspeed(drive, -1, argc<2? -1: atol(argv[1])*177));
	if(strcmp(argv[0], "rspeed") == 0)
		return e(setspeed(drive, argc<2? -1: atol(argv[1])*177, -1));
	return "bad arg";
}

static Dev mmcdev = {
	mmcopenrd,
	mmccreate,
	bufread,
	bufwrite,
	mmcclose,
	mmcgettoc,
	mmcfixate,
	mmcctl,
};

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9fans] Errors Writing To CD-R
@ 2002-04-22 16:35 forsyth
  0 siblings, 0 replies; 4+ messages in thread
From: forsyth @ 2002-04-22 16:35 UTC (permalink / raw)
  To: 9fans

[-- Attachment #1: Type: text/plain, Size: 178 bytes --]

here's a temporary replacement for /sys/src/cmd/cdfs/mmc.c
that supports speed control through the ctl file.  i've used it
to write CDs on a fairly cheap ATAPI CD-RW drive.


[-- Attachment #2: Type: message/rfc822, Size: 5415 bytes --]



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2.1: Type: text/plain, Size: 5415 bytes --]


\x1f�\b՘>�\x1aK z�q|'[�i<\x11���,�k�\x14�\x18�\x05��d��\x12�
o�ۋ����\x01\x1e\x03x\fN��\x0f�g�t\fO�\a�T���iV�<�\x13':��\a�\x13���D�^�'��B�{�
Z?�ŧxX�_ �\x05�\aE5�i֊G�P�\x17	���x0���`L����\x0f�9���M|\vKh4�i�\x15\x1f\x02\x17��x�A�����\x04��\vA�PZ�\x05�d\x06t��ͩV)����I{#q֡�(
~�\x02�_
v\x14�����\x12�<}\x04^[��gD\x18ȁ�\x12�2�d�BN���S�:���`�.N��.N6tA�>��\x02�o�_N�%�=$�\x7f�+�\x17�?�\x02�\x0e��g\x12\x1c���?(w\x0f�\fEK��\x06X��"\f\x13h|�N�\x01���B���,�Z�\a���.:g]�{WO0N���\x1d\a�=P&���8C\fo�x�\x11\x05>0�@��=�#��Q�Cn6:��x
�\x18\x15w\x06CZeqA2�f\x12Vm�\x14\x12�يz�����8�.E7���O����/��`��O*M�/\x14��o/��ĥM�\f�\x1a�G�F�.�����"�o�K���X<Lu�0�`��\x15gV,T��9Iv8������\x1d��p9+��2\x01_\x05fC\x10���\x7f������?\x7f�z� �en��\x0e�\x18Ӟ`ޯ�+3�m�I<#Z:F\x01W�G^[\x19[d�X��\x02\x01�F2��o�L\x0f5��崖?G!�{/�����|.�4���\x1c�(Ʋ(d��h��\x0eD��~�+�B�T\x1a&�F�UՊ���L��M�H1�&-���\b8\f����\x10E*P(��5�\x1f��Y\�2'E#���.�����.��\x13�#\x0e��
�l�7r\x06Ve\x119}
�SM\x02s���2�д\x0e��\x10!\x19�\x7f .�2i\v\x02�;��g��yV �ɶ����؀\x06�B�0���6\x7f ZLf\x11f�\��q4�
m!����<���\x01t�r�AW���\a\x0e%�f\x11��t�$�l$~�2+��E�<D)F��\x06B\x16Y\x18=��4u`d�\x7f��;\x15�a��
n�A`y���<��\x0f��t,�\x18*��`��)V\x7f�*\x01�
Z��Ő��h\x1c\f�<���쟨�c�\x10���\x1a\x1a�������K|1\x13���Y���K���3
0��8��w����\x1d��4�g�HF�x��%\x17*C�R\x05tM�\x04�F���^,2�\x03̾\x0f�8\x17\x03�E0\x10��W�P�R�M��Q�H\x13Q.��<<:�xz�1�hs�6�'�-%�D\b�'J����e\x02,
��\x17�G q/�\f!'e\bIʼ���2�~����a\x0f����u��%\x19���QYI��\x02��\x1c�o\x16�\x18`9G(R|����]p��l�6$�"O�\x12�Q�!(U���Ɖ�y\x14�O$ܛ�VH\x04��\ar6|�
���3���\x15��^�]Ǒ1\x05z5(\v!%I\x05�\x1eb\x18�eR0��q	�+�׆\x7fk|���BF%�҄�\x19r�
�\x15_��"�o��֬�
r޴ަ�u�Zu3�m�t�\x7f\x05��a\x16�\x18T�,�cȺ�)#I�\x14����tB%T�\x11���!^�b�P,�=P�!XZ\x0fw-K\b�&n�\b��\x117h�U"zD\x1fU�P�^[œ�!�R���p\x02Y*h)��\x11w�\x10��^.�<\x06މg\x15w�\x10޴���l���
��*\x7f^[n	��(0�dʆ\a{�#�(������ى���̑���4�9?�SS���u3ue�z���z�]?|`Z��߇kR�g���{\x11�g�a�M1�D���9qW�\9�n^i~\x1d{ٛ�M�5]�@�x�\x03�y2$���3;scI��gH�vd�����cs=7��j��,u��5|ժ�a'*��S/w@6}�\x06�a��P}�\x12ZkY>��(\x02���9\x04�\J\b��\x0e"��\x068���\x11����StB�\x06�t\x1d�>�"7f���v+I�T��O*�<��\x0ẽ-LmV#eH�#m]��\x12��5��
N[�4�<�-��B�^[�*��0�����M�;�瞢\x02\x0f}\x0f�G�GH��w"D��v�\x1at0�Uo\x06y\x14K'��ϻ\x0f\x7f�v��3汙-�����>�\x01�U���Ѿ�
�\x16\���~0D\x11����^X��$����\x17��5�\x13x�A\x1f�\x11�\x1a$���E<\x14VYd��"\x1c�`]%�S\x06�~W�;kl��?���$
�\x7f���p�PR�(�\x05zS��_\x1a�3��k���\vL�𻦱�_��h\x1d�&�K�\a5&��\a)�%2�\x15���\x04*םE"��)s�v�ުq׎փ{��� \a����\x1d
~;4��0�^`�&��NMV��Z���)�?�Ic�K��V*�F=���\f~^[�3:�G\x04�-NDR�o�<s�\o�|mu4:uK�ڲ6]R�^&62Xѹ1^w�&۪�IJ�h�[=��<�{"\x1a�FL�^��G�ڐ1I]a��\b���1����$\v榴�/m���UU��aM\x01���,\x04�B[�#b�N�y���\x1a�5\x03ܤ�9;�U˿�>^[\x05��V\x03_Su����o���	�\x06\x06\x0f\�Nػ��¸�+~ �z�0\x1dm��U
\b����NǨ(��$�U*�\x11(\x1f�\x05�z����Z^[,��o��ӷ^��jij52�t�\x16�\x1fNծ�Ū˃�2|\x02��C�n�D�\x04U��_\aW��
��'\vl�/5lu ��UGQ�p6��+~��!y�׀	|���2jy��\x0f]sJO�J�YT�2+�Z�۰�.\x7f��Ԧ����ȯTvE�S��Q�f�m9�5��T�\v���\x11n��k�d.�����mgi�=R	)�7\bg;\x10�8a��\x02+�L\x159�1�,"`��u��k\x19V��\x19�+��É>\x1e<��\x03n�8�ިC��W�*�a��\x12�{\�c��XC���j���TWC�b��)�*��}��\x10�\x17e��t#�6\x015<5��#��"�_[��o�G%jqi�\x04)U��,sX!��A\b�j\x11>�Ug�e)��\x15��Q����W����\x05�=�\x17��\x1d\x12\vg0#���\x01��}�ت
b\x0e�\x04�q\x12\x17炏i	(\x7f&����\x16\x01�G\x10h��\x1d����
v{ǟ�\x01ş�l�ߓ��N05��I�Hό\x10�"�L�\x10E��sA��Е\x12H��z��_�\x18��\x1c԰h%:6��\x10���%�<:���<'\x7f)R�J�\a<���DU\x18\x1f
,uG�4�����^[�\x04j�E);�Ɯ�R��]dC\x14�x]�\x16>Q2Ŋ�>^�\x0e{�ѱ\x19$��&k:s�N��T���U����^�
\x1d�T#�|�5\x139�\�ڇ\x7f]
Q\x16�\x14��_�5\x19�Y�ý������\x19�C\x7f�\f�v�+�‡׸\x1a��[�g�\�I��bʵ�O!��C�!|\x0fįK<��\x0f�0���K��\x1a�
�>�s.�7�\b.�#lN7�\x17�����g�\x14�\x03
t�?��v���X\x16�BJW�&�\x0f������%�\x05�L�ڴ\x1eW��RW�n����%�Ki7e\v�ȿ��}޴�o5Ǽ�;�\x04�^57e�u�����!�0����\x11�

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [9fans] Errors Writing To CD-R
@ 2002-04-22 15:32 Russ Cox
  0 siblings, 0 replies; 4+ messages in thread
From: Russ Cox @ 2002-04-22 15:32 UTC (permalink / raw)
  To: 9fans

Most of the CD write errors are buffer underrun in
various disguises.  I eventually had to add a command
to the cdfs ctl file to use write speeds below the
maximum (the default on most drives) so that we could
keep up.  That change will be in the new distribution
(it's rather hard to separate out or I'd post it).

In the mean time, if you can use DMA transfers that
might help you keep up.  Try echo dma on >/dev/sdD0/ctl
replacing sdD0 with your cd drive.  Then cat /dev/sdD0/ctl
to see if the dma number isn't 0.

Russ


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2002-04-22 16:42 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2002-04-22  8:41 [9fans] Errors Writing To CD-R Christopher Nielsen
2002-04-22 15:32 Russ Cox
2002-04-22 16:35 forsyth
2002-04-22 16:42 forsyth

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).