📄 scsincr53c8xx.c
字号:
/* * NCR/Symbios/LSI Logic 53c8xx driver for Plan 9 * Nigel Roles (nigel@9fs.org) * * 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 *//* Define one or the other ... *///#define CPU#ifndef FS#define FS#endif#include "u.h"#include "../port/lib.h"#include "mem.h"#include "dat.h"#include "fns.h"#include "io.h"#ifndef FS#include "../port/error.h"#endif#include "ureg.h"#ifdef NAINCLUDE#include "na/na.h"#include "na/nasupport.h"#endif /* NAINCLUDE *//**********************************//* Portable configuration macros *//**********************************///#define BOOTDEBUG//#define SINGLE_TARGET//#define ASYNC_ONLY//#define QUICK_TIMEOUT//#define INTERNAL_SCLK//#define ALWAYS_DO_WDTR#define WMR_DEBUG/**********************************//* CPU specific macros *//**********************************/#ifdef CPU#ifdef BOOTDEBUG#define KPRINT oprint#define IPRINT iprint#define DEBUG(n) 0#define IFLUSH() iflush()#else#define KPRINT kprint#define IPRINT kprint#define DEBUG(n) scsidebugs[n]#define IFLUSH()#endif#endif/*******************************//* Fileserver specific defines *//*******************************/#ifdef FS#define DEVICENAME "ncr53c8xx"#define PRINTPREFIX DEVICENAME ": "#define xalloc(n) ialloc(n, 1)#define KADDR(a) ((void*)((ulong)(a)|KZERO))#define KPRINT if(0)print#define IPRINT if(0)print#define DEBUG(n) 0#define IFLUSH()#endif/*******************************//* General *//*******************************/#ifndef DMASEG#define DMASEG(x) PADDR(x)#define legetl(x) (*(ulong*)(x))#define lesetl(x,v) (*(ulong*)(x) = (v))#define swabl(a,b,c)#define IRQBASE Int0vec#else#define IRQBASE (PCIvec + 5)#endif#define DMASEG_TO_KADDR(x) KADDR(PADDR(x))#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#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 3#ifndef NAINCLUDEstruct na_patch { unsigned lwoff; unsigned char type;};#endif /* NAINCLUDE */extern int scsidebugs[];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 { union { uchar state[4]; struct { 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; ushort 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 - must be power of 2 */ 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; int ctlrno; 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 */ struct { Lock; uchar head[4]; /* head of free list (NCR byte order) */ Dsa *tail; 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)static Controller *ctlrxx[MaxScsi];/* 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 };#define STATUS_COMPLETE 0x6000#define STATUS_FAIL 0x8000#define STATUS_SELECTION_TIMEOUT 0x0200static 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;voidiprint(char *format, ...){ if (debuglast == 0) debuglast = debugbuf; debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1));}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);}voidoprint(char *format, ...){ int s; iflush(); s = splhi(); if (debuglast == 0) debuglast = debugbuf; debuglast = doprint(debuglast, debugbuf + (DEBUGSIZE - 1), format, (&format + 1)); splx(s); iflush();}#endif#include "script.i"static Dsa *dsaalloc(Controller *c, int target, int lun){ Dsa *d; ilock(&c->dsalist); if ((d = c->dsalist.freechain) == 0) { d = xalloc(sizeof(*d)); if (DEBUG(1)) KPRINT(PRINTPREFIX "%d/%d: allocated new dsa %lux\n", target, lun, (ulong)d); lesetl(d->next, 0); lesetl(d->state, A_STATE_ALLOCATED); if (legetl(c->dsalist.head) == 0) lesetl(c->dsalist.head, DMASEG(d)); /* ATOMIC?!? */ else lesetl(c->dsalist.tail->next, DMASEG(d)); /* ATOMIC?!? */ c->dsalist.tail = d; } else { if (DEBUG(1)) KPRINT(PRINTPREFIX "%d/%d: reused dsa %lux\n", target, lun, (ulong)d); c->dsalist.freechain = d->freechain; lesetl(d->state, 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->state, A_STATE_FREE); iunlock(&c->dsalist);}static Dsa *dsafind(Controller *c, uchar target, uchar lun, uchar state){ Dsa *d; for (d = KPTR(legetl(c->dsalist.head)); d; 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; 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) { besttpf = v; bestscfi = scf; bestxferp = xferp; } } } if (besttpf == 1000) return 0; if (scfp) *scfp = bestscfi; if (xferpp) *xferpp = bestxferp; return besttpf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -