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

📄 mmc.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <disk.h>#include "dat.h"#include "fns.h"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 ulongbige(void *p){	uchar *a;	a = p;	return (a[0]<<24)|(a[1]<<16)|(a[2]<<8)|(a[3]<<0);}static ushortbiges(void *p){	uchar *a;	a = p;	return (a[0]<<8) | a[1];}static voidhexdump(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 intmmcgetpage10(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 intmmcgetpage6(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 intmmcsetpage10(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 intmmcsetpage6(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 intmmcgetpage(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 intmmcsetpage(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;}intmmcstatus(Drive *drive){	uchar cmd[12];	memset(cmd, 0, sizeof(cmd));	cmd[0] = 0xBD;	return scsi(drive, cmd, sizeof(cmd), nil, 0, Sread);}voidmmcgetspeed(Drive *drive){	int n, maxread, curread, maxwrite, curwrite;	uchar buf[Pagesz];	n = mmcgetpage(drive, 0x2A, buf);	maxread = (buf[8]<<8)|buf[9];	curread = (buf[14]<<8)|buf[15];	maxwrite = (buf[18]<<8)|buf[19];	curwrite = (buf[20]<<8)|buf[21];	if(n < 22 || (maxread && maxread < 170) || (curread && curread < 170))		return;	/* bogus data */	drive->readspeed = curread;	drive->writespeed = curwrite;	drive->maxreadspeed = maxread;	drive->maxwritespeed = maxwrite;}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;	mmcgetspeed(drive);	return drive;}static intmmctrackinfo(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 intmmcreadtoc(Drive *drive, int type, int track, void *data, int nbytes){	uchar cmd[10];	memset(cmd, 0, sizeof(cmd));	cmd[0] = 0x43;	cmd[1] = type;	cmd[6] = track;	cmd[7] = nbytes>>8;	cmd[8] = nbytes;	return scsi(drive, cmd, sizeof(cmd), data, nbytes, Sread);}static intmmcreaddiscinfo(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 Msfrdmsf(uchar *p){	Msf msf;	msf.m = p[0];	msf.s = p[1];	msf.f = p[2];	return msf;}static intmmcgettoc(Drive *drive){	uchar resp[1024];	int i, n, 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, 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;	for(i=0; i<nelem(drive->track); i++){		memset(&drive->track[i].mbeg, 0, sizeof(Msf));		memset(&drive->track[i].mend, 0, sizeof(Msf));	}	/*	 * find number of tracks	 */	if((n=mmcreadtoc(drive, 0x02, 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(n >= 4+8*(last-first+2)) {			for(i=0; i<=last-first+1; i++)	/* <=: track[last-first+1] = end */				drive->track[i].mbeg = rdmsf(resp+4+i*8+5);			for(i=0; i<last-first+1; i++)				drive->track[i].mend = drive->track[i+1].mbeg;		}	}	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;

⌨️ 快捷键说明

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