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

📄 sd53c8xx.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * NCR/Symbios/LSI Logic 53c8xx driver for Plan 9 * Nigel Roles (nigel@9fs.org) * * 27/5/02	Fixed problems with transfers >= 256 * 512 * * 13/3/01	Fixed microcode to support targets > 7 * * 01/12/00	Removed previous comments. Fixed a small problem in *			mismatch recovery for targets with synchronous offsets of >=16 *			connected to >=875s. Thanks, Jean. * * Known problems * * Read/write mismatch recovery may fail on 53c1010s. Really need to get a manual. */#define MAXTARGET	16		/* can be 8 or 16 */#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#include "../port/sd.h"extern SDifc sd53c8xxifc;/**********************************//* Portable configuration macros  *//**********************************///#define BOOTDEBUG//#define ASYNC_ONLY//#define	INTERNAL_SCLK//#define ALWAYS_DO_WDTR#define WMR_DEBUG/**********************************//* CPU specific macros            *//**********************************/#define PRINTPREFIX "sd53c8xx: "#ifdef BOOTDEBUG#define KPRINT oprint#define IPRINT intrprint#define DEBUG(n) 1#define IFLUSH() iflush()#elsestatic int idebug = 1;#define KPRINT	if(0) iprint#define IPRINT	if(idebug) iprint#define DEBUG(n)	(0)#define IFLUSH()#endif /* BOOTDEBUG *//*******************************//* General                     *//*******************************/#ifndef DMASEG#define DMASEG(x) PCIWADDR(x)#define legetl(x) (*(ulong*)(x))#define lesetl(x,v) (*(ulong*)(x) = (v))#define swabl(a,b,c)#else#endif /*DMASEG */#define DMASEG_TO_KADDR(x) KADDR((x)-PCIWINDOW)#define KPTR(x) ((x) == 0 ? 0 : DMASEG_TO_KADDR(x))#define MEGA 1000000L#ifdef INTERNAL_SCLK#define	SCLK (33 * MEGA)#else#define SCLK (40 * MEGA)#endif /* INTERNAL_SCLK */#define ULTRA_NOCLOCKDOUBLE_SCLK (80 * MEGA)#define MAXSYNCSCSIRATE (5 * MEGA)#define MAXFASTSYNCSCSIRATE (10 * MEGA)#define MAXULTRASYNCSCSIRATE (20 * MEGA)#define MAXULTRA2SYNCSCSIRATE (40 * MEGA)#define MAXASYNCCORERATE (25 * MEGA)#define MAXSYNCCORERATE (25 * MEGA)#define MAXFASTSYNCCORERATE (50 * MEGA)#define MAXULTRASYNCCORERATE (80 * MEGA)#define MAXULTRA2SYNCCORERATE (160 * MEGA)#define X_MSG	1#define X_MSG_SDTR 1#define X_MSG_WDTR 3struct na_patch {	unsigned lwoff;	unsigned char type;};typedef struct Ncr {	uchar scntl0;	/* 00 */	uchar scntl1;	uchar scntl2;	uchar scntl3;	uchar scid;	/* 04 */	uchar sxfer;	uchar sdid;	uchar gpreg;	uchar sfbr;	/* 08 */	uchar socl;	uchar ssid;	uchar sbcl;	uchar dstat;	/* 0c */	uchar sstat0;	uchar sstat1;	uchar sstat2;	uchar dsa[4];	/* 10 */	uchar istat;	/* 14 */	uchar istatpad[3];	uchar ctest0;	/* 18 */	uchar ctest1;	uchar ctest2;	uchar ctest3;	uchar temp[4];	/* 1c */	uchar dfifo;	/* 20 */	uchar ctest4;	uchar ctest5;	uchar ctest6;	uchar dbc[3];	/* 24 */	uchar dcmd;	/* 27 */	uchar dnad[4];	/* 28 */	uchar dsp[4];	/* 2c */	uchar dsps[4];	/* 30 */	uchar scratcha[4];	/* 34 */	uchar dmode;	/* 38 */	uchar dien;	uchar dwt;	uchar dcntl;	uchar adder[4];	/* 3c */	uchar sien0;	/* 40 */	uchar sien1;	uchar sist0;	uchar sist1;	uchar slpar;	/* 44 */	uchar slparpad0;	uchar macntl;	uchar gpcntl;	uchar stime0;	/* 48 */	uchar stime1;	uchar respid;	uchar respidpad0;	uchar stest0;	/* 4c */	uchar stest1;	uchar stest2;	uchar stest3;	uchar sidl;	/* 50 */	uchar sidlpad[3];	uchar sodl;	/* 54 */	uchar sodlpad[3];	uchar sbdl;	/* 58 */	uchar sbdlpad[3];	uchar scratchb[4];	/* 5c */} Ncr;typedef struct Movedata {	uchar dbc[4];	uchar pa[4];} Movedata;typedef enum NegoState {	NeitherDone, WideInit, WideResponse, WideDone,	SyncInit, SyncResponse, BothDone} NegoState;typedef enum State {	Allocated, Queued, Active, Done} State;typedef struct Dsa {	uchar stateb;	uchar result;	uchar dmablks;	uchar flag;	/* setbyte(state,3,...) */	union {		ulong dmancr;		/* For block transfer: NCR order (little-endian) */		uchar dmaaddr[4];	};	uchar target;			/* Target */	uchar pad0[3];	uchar lun;			/* Logical Unit Number */	uchar pad1[3];	uchar scntl3;	uchar sxfer;	uchar pad2[2];	uchar next[4];			/* chaining for SCRIPT (NCR byte order) */	struct Dsa *freechain;		/* chaining for freelist */	Rendez;	uchar scsi_id_buf[4];	Movedata msg_out_buf;	Movedata cmd_buf;	Movedata data_buf;	Movedata status_buf;	uchar msg_out[10];		/* enough to include SDTR */	uchar status;	int p9status;	uchar parityerror;} Dsa;typedef enum Feature {	BigFifo = 1,			/* 536 byte fifo */	BurstOpCodeFetch = 2,		/* burst fetch opcodes */	Prefetch = 4,			/* prefetch 8 longwords */	LocalRAM = 8,			/* 4K longwords of local RAM */	Differential = 16,		/* Differential support */	Wide = 32,			/* Wide capable */	Ultra = 64,			/* Ultra capable */	ClockDouble = 128,		/* Has clock doubler */	ClockQuad = 256,		/* Has clock quadrupler (same as Ultra2) */	Ultra2 = 256,} Feature;typedef enum Burst {	Burst2 = 0,	Burst4 = 1,	Burst8 = 2,	Burst16 = 3,	Burst32 = 4,	Burst64 = 5,	Burst128 = 6} Burst;typedef struct Variant {	ushort did;	uchar maxrid;			/* maximum allowed revision ID */	char *name;	Burst burst;			/* codings for max burst */	uchar maxsyncoff;		/* max synchronous offset */	uchar registers;		/* number of 32 bit registers */	unsigned feature;} Variant;static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 };#define NULTRA2SCF (sizeof(cf2)/sizeof(cf2[0]))#define NULTRASCF (NULTRA2SCF - 2)#define NSCF (NULTRASCF - 1)typedef struct Controller {	Lock;	struct {		uchar scntl3;		uchar stest2;	} bios;	uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */	NegoState s[MAXTARGET];	uchar scntl3[MAXTARGET];	uchar sxfer[MAXTARGET];	uchar cap[MAXTARGET];		/* capabilities byte from Identify */	ushort capvalid;		/* bit per target for validity of cap[] */	ushort wide;			/* bit per target set if wide negotiated */	ulong sclk;			/* clock speed of controller */	uchar clockmult;		/* set by synctabinit */	uchar ccf;			/* CCF bits */	uchar tpf;			/* best tpf value for this controller */	uchar feature;			/* requested features */	int running;			/* is the script processor running? */	int ssm;			/* single step mode */	Ncr *n;				/* pointer to registers */	Variant *v;			/* pointer to variant type */	ulong *script;			/* where the real script is */	ulong scriptpa;			/* where the real script is */	Pcidev* pcidev;	SDev*	sdev;	struct {		Lock;		uchar head[4];		/* head of free list (NCR byte order) */		Dsa	*freechain;	} dsalist;	QLock q[MAXTARGET];		/* queues for each target */} Controller;#define SYNCOFFMASK(c)		(((c)->v->maxsyncoff * 2) - 1)#define SSIDMASK(c)		(((c)->v->feature & Wide) ? 15 : 7)/* ISTAT */enum { Abrt = 0x80, Srst = 0x40, Sigp = 0x20, Sem = 0x10, Con = 0x08, Intf = 0x04, Sip = 0x02, Dip = 0x01 };/* DSTAT */enum { Dfe = 0x80, Mdpe = 0x40, Bf = 0x20, Abrted = 0x10, Ssi = 0x08, Sir = 0x04, Iid = 0x01 };/* SSTAT */enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, MessageIn };static void setmovedata(Movedata*, ulong, ulong);static void advancedata(Movedata*, long);static int bios_set_differential(Controller *c);static char *phase[] = {	"data out", "data in", "command", "status",	"reserved out", "reserved in", "message out", "message in"};#ifdef BOOTDEBUG#define DEBUGSIZE 10240char debugbuf[DEBUGSIZE];char *debuglast;static voidintrprint(char *format, ...){	if (debuglast == 0)		debuglast = debugbuf;	debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));}static voidiflush(){	int s;	char *endp;	s = splhi();	if (debuglast == 0)		debuglast = debugbuf;	if (debuglast == debugbuf) {		splx(s);		return;	}	endp = debuglast;	splx(s);	screenputs(debugbuf, endp - debugbuf);	s = splhi();	memmove(debugbuf, endp, debuglast - endp);	debuglast -= endp - debugbuf;	splx(s);}static voidoprint(char *format, ...){	int s;	iflush();	s = splhi();	if (debuglast == 0)		debuglast = debugbuf;	debuglast = vseprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));	splx(s);	iflush();	}#endif#include "sd53c8xx.i"/* * We used to use a linked list of Dsas with nil as the terminator, * but occasionally the 896 card seems not to notice that the 0 * is really a 0, and then it tries to reference the Dsa at address 0. * To address this, we use a sentinel dsa that links back to itself * and has state A_STATE_END.  If the card takes an iteration or * two to notice that the state says A_STATE_END, that's no big  * deal.  Clearly this isn't the right approach, but I'm just * stumped.  Even with this, we occasionally get prints about * "WSR set", usually with about the same frequency that the * card used to walk past 0.  */static Dsa *dsaend;static Dsa*dsaallocnew(Controller *c){	Dsa *d;		/* c->dsalist must be ilocked */	d = xalloc(sizeof *d);	lesetl(d->next, legetl(c->dsalist.head));	lesetl(&d->stateb, A_STATE_FREE);	coherence();	lesetl(c->dsalist.head, DMASEG(d));	coherence();	return d;}static Dsa *dsaalloc(Controller *c, int target, int lun){	Dsa *d;	ilock(&c->dsalist);	if ((d = c->dsalist.freechain) != 0) {		if (DEBUG(1))			IPRINT(PRINTPREFIX "%d/%d: reused dsa %lux\n", target, lun, (ulong)d);	} else {			d = dsaallocnew(c);		if (DEBUG(1))			IPRINT(PRINTPREFIX "%d/%d: allocated dsa %lux\n", target, lun, (ulong)d);	}	c->dsalist.freechain = d->freechain;	lesetl(&d->stateb, A_STATE_ALLOCATED);	iunlock(&c->dsalist);	d->target = target;	d->lun = lun;	return d;}static voiddsafree(Controller *c, Dsa *d){	ilock(&c->dsalist);	d->freechain = c->dsalist.freechain;	c->dsalist.freechain = d;	lesetl(&d->stateb, A_STATE_FREE);	iunlock(&c->dsalist);}static voiddsadump(Controller *c){	Dsa *d;	u32int *a;		iprint("dsa controller list: c=%p head=%.8lux\n", c, legetl(c->dsalist.head));	for(d=KPTR(legetl(c->dsalist.head)); d != dsaend; d=KPTR(legetl(d->next))){		if(d == (void*)-1){			iprint("\t dsa %p\n", d);			break;		}		a = (u32int*)d;		iprint("\tdsa %p %.8ux %.8ux %.8ux %.8ux %.8ux %.8ux\n", a, a[0], a[1], a[2], a[3], a[4], a[5]);	}/*	a = KPTR(c->scriptpa+E_dsa_addr);	iprint("dsa_addr: %.8ux %.8ux %.8ux %.8ux %.8ux\n",		a[0], a[1], a[2], a[3], a[4]);	a = KPTR(c->scriptpa+E_issue_addr);	iprint("issue_addr: %.8ux %.8ux %.8ux %.8ux %.8ux\n",		a[0], a[1], a[2], a[3], a[4]);	a = KPTR(c->scriptpa+E_issue_test_begin);	e = KPTR(c->scriptpa+E_issue_test_end);	iprint("issue_test code (at offset %.8ux):\n", E_issue_test_begin);		i = 0;	for(; a<e; a++){		iprint(" %.8ux", *a);		if(++i%8 == 0)			iprint("\n");	}	if(i%8)		iprint("\n");*/}static Dsa *dsafind(Controller *c, uchar target, uchar lun, uchar state){	Dsa *d;	for (d = KPTR(legetl(c->dsalist.head)); d != dsaend; d = KPTR(legetl(d->next))) {		if (d->target != 0xff && d->target != target)			continue;		if (lun != 0xff && d->lun != lun)			continue;		if (state != 0xff && d->stateb != state)			continue;		break;	}	return d;}static voiddumpncrregs(Controller *c, int intr){	int i;	Ncr *n = c->n;	int depth = c->v->registers / 4;	if (intr) {		IPRINT("sa = %.8lux\n", c->scriptpa);	}	else {		KPRINT("sa = %.8lux\n", c->scriptpa);	}	for (i = 0; i < depth; i++) {		int j;		for (j = 0; j < 4; j++) {			int k = j * depth + i;			uchar *p;			/* display little-endian to make 32-bit values readable */			p = (uchar*)n+k*4;			if (intr) {				IPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);			}			else {				KPRINT(" %.2x%.2x%.2x%.2x %.2x %.2x", p[3], p[2], p[1], p[0], k * 4, (k * 4) + 0x80);			}			USED(p);		}		if (intr) {			IPRINT("\n");		}		else {			KPRINT("\n");		}	}}	static intchooserate(Controller *c, int tpf, int *scfp, int *xferpp){	/* find lowest entry >= tpf */	int besttpf = 1000;	int bestscfi = 0;	int bestxferp = 0;	int scf, xferp;	int maxscf;	if (c->v->feature & Ultra2)		maxscf = NULTRA2SCF;	else if (c->v->feature & Ultra)		maxscf = NULTRASCF;	else		maxscf = NSCF;	/*	 * search large clock factors first since this should	 * result in more reliable transfers	 */	for (scf = maxscf; scf >= 1; scf--) {		for (xferp = 0; xferp < 8; xferp++) {			unsigned char v = c->synctab[scf - 1][xferp];			if (v == 0)				continue;			if (v >= tpf && v < besttpf) {

⌨️ 快捷键说明

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