henesyinit from p9fce6d0435 years agoHistory
766 lines · 12.5 KB · C
RawDownload
#include	"u.h"#include	"../port/lib.h"#include	"mem.h"#include	"dat.h"#include	"fns.h"#include	"../port/error.h"#include	"devtab.h"#include	"io.h"/* * CD-ROM driver for Panasonic and Mitsumi drives on SB16 and SBPRO cards */  typedef struct Drive		Drive; enum{	FRAMESIZE	= 2048,		/* max in a transfer */	Panasonic 	= 1,	Mitsumi	  	= 2, 	Qdir		= 0,	Qcd,	Qcdctl, 	CMDLEN		= 7, 	DTEN		= 0x02,		/* Status register */	STEN		= 0x04, 	DRIVE0		= 0, 	CMD		= 0,		/* Ports */	DATA		= 0,	PHASE		= 1,	STATUS		= 1,	RESET 		= 2,	SELECT		= 3, 	ABORT		= 0x08,	BLOCKPARAM	= 0x00,	DOORCLOSE	= 0x07,	DOOROPEN	= 0x06,	LOCK		= 0x0c,	MODESELECT	= 0x09,	NOP		= 0x05,	PAUSE		= 0x0d,	PLAYBLOCKS	= 0x0e,	PLAYTRKS	= 0x0f,	READ		= 0x10,	READDINFO	= 0x8b,	READERROR	= 0x82,	READID		= 0x83,	RESUME		= 0x80, 	ST_DOOROPEN	= 0x80,	ST_DSKIN	= 0x40,	ST_SPIN		= 0x20,	ST_ERROR	= 0x10,	ST_BUSY		= 0x04,	ST_AUDIOBSY	= 0x02, 	MEDIA_CHANGED	= 0x11,	NOT_READY	= 0x03,	HARD_RESET	= 0x12,	DISC_OUT	= 0x15, 	MST_CMD_CHECK	= 0x01,		/* command error */	MST_BUSY	= 0x02,		/* now playing */	MST_READ_ERR	= 0x04,		/* read error */	MST_DSK_TYPE	= 0x08,		/* cdda */	MST_SERVO_CHECK	= 0x10,	MST_DSK_CHG	= 0x20,		/* disk removed or changed */	MST_READY	= 0x40,		/* disk in the drive */	MST_DOOR_OPEN	= 0x80,		/* door is open */ 	MFL_DATA	= 0x02,		/* data available */	MFL_STATUS	= 0x04,		/* status available */ 	MCMD_RESET		= 0x00,	MCMD_GET_DISK_INFO	= 0x10,		/* read info from disk */	MCMD_GET_Q_CHANNEL	= 0x20,		/* read info from q channel */	MCMD_GET_STATUS		= 0x40,	MCMD_SET_MODE		= 0x50,	MCMD_SOFT_RESET		= 0x60,	MCMD_STOP		= 0x70,		/* stop play */	MCMD_CONFIG_DRIVE	= 0x90,	MCMD_SET_VOLUME		= 0xAE,		/* set audio level */	MCMD_PLAY_READ		= 0xC0,		/* play or read data */	MCMD_GET_VERSION  	= 0xDC,	MCMD_EJECT		= 0xF6,		/* eject (FX drive) */ 	MSTAT_DOOR		= 1,	MSTAT_CHNG,	MSTAT_CDDA,	MSTAT_READY,	MSTAT_ERROR,}; static char *etable[] ={	"no error",	"soft read error after retry",	"soft read error after error correction",	"not ready",	"unable to read TOC",	"hard read error of data track",	"seek failed",	"tracking servo failure",	"drive RAM failure",	"drive self-test failed",	"focusing servo failure",	"spindle servo failure",	"data path failure",	"illegal logical block address",	"illegal field in CDB",	"end of user encountered on this track",	"illegal data mode for this track",	"media changed",	"power-on or drive reset occurred",	"drive ROM failure",	"illegal drive command received from host",	"disc removed during operation",	"drive Hardware error",	"illegal request from host"}; static char *metable[] ={	[MSTAT_DOOR]	= "cdrom door is open",	[MSTAT_CHNG]	= "cdrom media changed",	[MSTAT_CDDA]	= "cd is not a cdrom",	[MSTAT_READY]	= "cdrom is not ready",	[MSTAT_ERROR]	= "cannot get cd status",}; struct Drive{	int		type;	Ref		opens;	QLock;	Rendez		rendez;	ulong		blocks;			/* blocks on disk */	int		port;	uchar		buf[FRAMESIZE]; 	void		(*sbcdio)(int, ulong);	void		(*initdrive)(int);}; Dirtabcdtab[] ={	"cd",		{Qcd},			0,	0666,	"cdctl",	{Qcdctl},		0,	0666,};#define	Ncdtab		(sizeof cdtab/sizeof(Dirtab))#define CDFILE		0		/* Array index of Qcd direntry */ static Drive	sbcd; static void	pansbcdio(int, ulong);static void	mitsbcdio(int, ulong);static void	paninitdrive(int);static void	mitinitdrive(int); static voiddrain(int port){	outb(port+STATUS, 1);	while((inb(port+STATUS) & (DTEN|STEN)) == STEN)		inb(port+DATA);	outb(port+STATUS,0);} static intstatus(int port){	int sr; 	sr = inb(port+DATA); 	for(;;) {		if(inb(port+STATUS) == 0xff)			break;		if((sr&DTEN|STEN) == STEN)			drain(port); 		print("devsbcd: busy for sr\n");		sr = inb(port+DATA);	} 	return sr;} static voidissue(int port, uchar *cmd){	ulong s;	uchar sr;	int i, len; 	i = inb(port+STATUS);	if(i != 0xff) {		if ((i & DTEN|STEN) == STEN)			drain(port);		i = status(port);		USED(i);		sr = inb(port+STATUS);		if(sr != 0xff) {			print("devsbcd: device wedged, sr=%2.2ux\n", inb(port+STATUS));			outb(port+RESET, 0);			tsleep(&sbcd.rendez, return0, 0, 500);		}	} 	outb(port+SELECT, DRIVE0); 	len = CMDLEN;	if(cmd[0] == ABORT)		len=1; 	s = splhi();	for (i = 0; i < len; i++)		outb(port+CMD,*cmd++);	splx(s);} voidsbcdreset(void){} voidsbcdinit(void){	ISAConf sbconf; 	sbconf.port = 0;	if(isaconfig("cdrom", 0, &sbconf) == 0)		return;	if(strcmp(sbconf.type, "panasonic") == 0 || strcmp(sbconf.type, "matsushita") == 0) {		sbcd.sbcdio = pansbcdio;		sbcd.initdrive = paninitdrive;		if(sbconf.port == 0)			sbconf.port = 0x230;	}	else	if(strcmp(sbconf.type, "mitsumi") == 0) {		sbcd.sbcdio = mitsbcdio;		sbcd.initdrive = mitinitdrive;		if(sbconf.port == 0)			sbconf.port = 0x340;	}	if(sbcd.sbcdio == 0) {		print("devsbcd: %s is not a valid cd-rom type\n", sbconf.type);		return;	}	switch(sbconf.port) {	case 0x230:	case 0x250:	case 0x270:	case 0x290:	case 0x340:		break;	default:		print("devsbcd: bad port 0x%x\n", sbconf.port);		return;	}	sbcd.port = sbconf.port;	} Chan*sbcdattach(char *param){	if(sbcd.port == 0)		error("no cd-rom configured"); 	return devattach('m', param);} Chan*sbcdclone(Chan *c, Chan *nc){	return devclone(c, nc);} intsbcdwalk(Chan *c, char *name){	return devwalk(c, name, cdtab, Ncdtab, devgen);} voidsbcdstat(Chan *c, char *dp){	devstat(c, dp, cdtab, Ncdtab, devgen);} static intpoll(int timeo, int state, int port, int delay){	int i, sr; 	sr = 0;	for(i = 0; i < timeo; i++) {		sr = inb(port+STATUS) & (STEN|DTEN);		if(sr != (STEN|DTEN))			break;		if(delay != 0)			tsleep(&sbcd.rendez, return0, 0, TK2MS(1));	}	return sr != state;} static intreqsense(int port){	int i;	uchar cmd[CMDLEN], data[12]; 	memset(cmd, 0, sizeof(cmd));	cmd[0] = READERROR;	issue(port, cmd);	i = poll(2000, DTEN, port, 0);	if(i < 0) {		print("devsbcd: get error failed\n");		error(Eio);	}	insb(port, data, 8);	status(port); 	return data[2];} static voidgetcap(Drive *d){	int port, i, sr, retry;	uchar cmd[CMDLEN], data[12]; 	port = d->port; 	for(retry = 0; retry < 10; retry++) {		memset(cmd, 0, sizeof(cmd));		cmd[0] = READDINFO;		issue(port, cmd);		i = poll(10, DTEN, port, 1);		if(i < 0) {			print("devsbcd: cmd error, sr=%2.2ux\n", status(port));			error(Eio);		}		insb(port, data, 6);		sr = status(port); 		sbcd.blocks = (data[3]*4500) + (data[4]*75) + data[5];		sbcd.blocks -= 150;			cdtab[CDFILE].length = sbcd.blocks*FRAMESIZE; 		if((sr & ST_ERROR) == 0)				break;	}	if(retry >= 10)		error(Eio);} Chan*sbcdopen(Chan *c, int omode){	switch(c->qid.path) {	case Qcd:		if(incref(&sbcd.opens) == 1) {			if(waserror()) {				decref(&sbcd.opens);				nexterror();			}			sbcd.initdrive(sbcd.port);			poperror();		}		break;	}	return devopen(c, omode, cdtab, Ncdtab, devgen);} voidsbcdcreate(Chan *c, char *name, int omode, ulong perm){	USED(c, name, omode, perm);	error(Eperm);} voidsbcdclose(Chan *c){	switch(c->qid.path) {	default:		break;	case Qcd:		if(c->flag & COPEN)			decref(&sbcd.opens);		break;	}} voidsbcdremove(Chan *c){	USED(c);	error(Eperm);} voidsbcdwstat(Chan *c, char *dp){	USED(c, dp);	error(Eperm);} longsbcdread(Chan *c, char *a, long n, ulong offset){	char *t, buf[64];	long m, o, n0, bn; 	if(c->qid.path & CHDIR)		return devdirread(c, a, n, cdtab, Ncdtab, devgen); 	n0 = n;	switch(c->qid.path) {	case Qcdctl:		t = "panasonic";		if(sbcd.sbcdio != pansbcdio)			t = "mitsumi";		sprint(buf, "port=0x%ux drive=%s\n", sbcd.port, t);		return readstr(offset, a, n, buf);	case Qcd:		qlock(&sbcd);		if(waserror()) {			qunlock(&sbcd);			nexterror();		}		while(n > 0) {			bn = offset / FRAMESIZE;			o = offset % FRAMESIZE;			m = FRAMESIZE - o;			if(m > n)				m = n;			if(bn >= sbcd.blocks)				break;			sbcd.sbcdio(sbcd.port, bn);			memmove(a, sbcd.buf+o, m);			n -= m;			offset += m;			a += m;		}		qunlock(&sbcd);		poperror();		break;	}	return n0-n;} longsbcdwrite(Chan *c, char *a, long n, ulong offset){ 	USED(c, a, n, offset);	error(Eperm);	return 0;} static voidbin2bcd(uchar *p){	int u, t; 	u = *p % 10;	t = *p / 10;	*p = u | (t << 4);} static voidbin2msf(uchar *msf, long addr){	addr += 150;	msf[0] = addr / 4500;	addr %= 4500;	msf[1] = addr / 75;	msf[2] = addr % 75;} static intbcd2bin(uchar bcd){	return (bcd >> 4) * 10 + (bcd & 0xF);} /* * panasonic specific */

Lines 1–500 of 766.