⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mmc.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	}	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, 0x00, 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, 0x00, 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 intmmcsetbs(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;	return 0;}static longmmcread(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) {		if(nn != -1)			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 longmmcxwrite(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 longmmcwrite(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;}voidmmcsynccache(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 voidmmcclose(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 intmmcxclose(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 intmmcfixate(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 intmmcsession(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 intmmcblank(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 intstart(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 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));	return "bad arg";}static char*mmcsetspeed(Drive *drive, int r, int w){	char *rv;	uchar cmd[12];	memset(cmd, 0, sizeof(cmd));	cmd[0] = 0xBB;	cmd[2] = r>>8;	cmd[3] = r;	cmd[4] = w>>8;	cmd[5] = w;	rv = e(scsi(drive, cmd, sizeof(cmd), nil, 0, Snone));	mmcgetspeed(drive);	return rv;}static Dev mmcdev = {	mmcopenrd,	mmccreate,	bufread,	bufwrite,	mmcclose,	mmcgettoc,	mmcfixate,	mmcctl,	mmcsetspeed,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -