xref: /inferno-os/os/mpc/cpm.c (revision 74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a)
1*74a4d8c2SCharles.Forsyth #include "u.h"
2*74a4d8c2SCharles.Forsyth #include "lib.h"
3*74a4d8c2SCharles.Forsyth #include "mem.h"
4*74a4d8c2SCharles.Forsyth #include "dat.h"
5*74a4d8c2SCharles.Forsyth #include "fns.h"
6*74a4d8c2SCharles.Forsyth #include "io.h"
7*74a4d8c2SCharles.Forsyth 
8*74a4d8c2SCharles.Forsyth typedef struct Chanuse Chanuse;
9*74a4d8c2SCharles.Forsyth struct Chanuse {
10*74a4d8c2SCharles.Forsyth 	Lock;
11*74a4d8c2SCharles.Forsyth 	void*	owner;
12*74a4d8c2SCharles.Forsyth } ;
13*74a4d8c2SCharles.Forsyth 
14*74a4d8c2SCharles.Forsyth enum {
15*74a4d8c2SCharles.Forsyth 	BDSIZE=	1024,	/* IO memory reserved for buffer descriptors */
16*74a4d8c2SCharles.Forsyth 	CPMSIZE=	1024,	/* IO memory reserved for other uses */
17*74a4d8c2SCharles.Forsyth 
18*74a4d8c2SCharles.Forsyth 	/* channel IDs */
19*74a4d8c2SCharles.Forsyth 	SCC1ID=	0,
20*74a4d8c2SCharles.Forsyth 	I2CID=	1,
21*74a4d8c2SCharles.Forsyth 	IDMA1ID= 1,
22*74a4d8c2SCharles.Forsyth 	SCC2ID=	4,
23*74a4d8c2SCharles.Forsyth 	SPIID=	5,
24*74a4d8c2SCharles.Forsyth 	IDMA2ID= 5,
25*74a4d8c2SCharles.Forsyth 	TIMERID=	5,
26*74a4d8c2SCharles.Forsyth 	SCC3ID=	8,
27*74a4d8c2SCharles.Forsyth 	SMC1ID=	9,
28*74a4d8c2SCharles.Forsyth 	DSP1ID=	9,
29*74a4d8c2SCharles.Forsyth 	SCC4ID=	12,
30*74a4d8c2SCharles.Forsyth 	SMC2ID=	13,
31*74a4d8c2SCharles.Forsyth 	DSP2ID=	13,
32*74a4d8c2SCharles.Forsyth 	NCPMID=	16,
33*74a4d8c2SCharles.Forsyth 
34*74a4d8c2SCharles.Forsyth 	NSCC = 4,
35*74a4d8c2SCharles.Forsyth 
36*74a4d8c2SCharles.Forsyth 	/* SCC.gsmr_l */
37*74a4d8c2SCharles.Forsyth 	ENR = 1<<5,	/* enable receiver */
38*74a4d8c2SCharles.Forsyth 	ENT = 1<<4,	/* enable transmitter */
39*74a4d8c2SCharles.Forsyth 
40*74a4d8c2SCharles.Forsyth 	NSMC = 2,
41*74a4d8c2SCharles.Forsyth 
42*74a4d8c2SCharles.Forsyth 	/* SMC.smcmr */
43*74a4d8c2SCharles.Forsyth 	TEN = 1<<1,	/* transmitter enable */
44*74a4d8c2SCharles.Forsyth 	REN = 1<<0,	/* receiver enable */
45*74a4d8c2SCharles.Forsyth };
46*74a4d8c2SCharles.Forsyth 
47*74a4d8c2SCharles.Forsyth static	Map	bdmapv[BDSIZE/sizeof(BD)];
48*74a4d8c2SCharles.Forsyth static	RMap	bdmap = {"buffer descriptors"};
49*74a4d8c2SCharles.Forsyth 
50*74a4d8c2SCharles.Forsyth static	Map	cpmmapv[CPMSIZE/sizeof(ulong)];
51*74a4d8c2SCharles.Forsyth static	RMap	cpmmap = {"CPM memory"};
52*74a4d8c2SCharles.Forsyth 
53*74a4d8c2SCharles.Forsyth static	Lock	cpmlock;
54*74a4d8c2SCharles.Forsyth 
55*74a4d8c2SCharles.Forsyth static struct {
56*74a4d8c2SCharles.Forsyth 	Lock;
57*74a4d8c2SCharles.Forsyth 	ulong	avail;
58*74a4d8c2SCharles.Forsyth } brgens;
59*74a4d8c2SCharles.Forsyth 
60*74a4d8c2SCharles.Forsyth static	Chanuse	cpmids[NCPMID];
61*74a4d8c2SCharles.Forsyth static	CPMdev	cpmdevinfo[] = {
62*74a4d8c2SCharles.Forsyth 	[CPscc1] {SCC1ID, 0x1E, 0xA00, 0x3C00},
63*74a4d8c2SCharles.Forsyth 	[CPscc2] {SCC2ID, 0x1D, 0xA20, 0x3D00},
64*74a4d8c2SCharles.Forsyth 	[CPscc3] {SCC3ID, 0x1C, 0xA40, 0x3E00},
65*74a4d8c2SCharles.Forsyth 	[CPscc4] {SCC4ID, 0x1B, 0xA60, 0x3F00},
66*74a4d8c2SCharles.Forsyth 	[CPsmc1] {SMC1ID, 0x04, 0xA80, 0x3E80},
67*74a4d8c2SCharles.Forsyth 	[CPsmc2] {SMC2ID, 0x03, 0xA90, 0x3F80},
68*74a4d8c2SCharles.Forsyth 	[CPdsp1] {DSP1ID, 0x16, 0, 0x3EC0},
69*74a4d8c2SCharles.Forsyth 	[CPdsp2] {DSP2ID, 0x16, 0, 0x3FC0},
70*74a4d8c2SCharles.Forsyth 	[CPidma1] {IDMA1ID, 0x15, 0, 0x3CC0},
71*74a4d8c2SCharles.Forsyth 	[CPidma2] {IDMA2ID, 0x14, 0, 0x3DC0},
72*74a4d8c2SCharles.Forsyth 	[CPtimer] {TIMERID, 0x11, 0, 0x3DB0},
73*74a4d8c2SCharles.Forsyth 	[CPspi] {SPIID, 0x05, 0xAA0, 0x3D80},	/* parameters relocated below */
74*74a4d8c2SCharles.Forsyth 	[CPi2c] {I2CID, 0x10, 0x860, 0x3C80},	/* parameters relocated below */
75*74a4d8c2SCharles.Forsyth };
76*74a4d8c2SCharles.Forsyth 
77*74a4d8c2SCharles.Forsyth static	void	i2cspireloc(void);
78*74a4d8c2SCharles.Forsyth static	void*	relocateparam(ulong, int);
79*74a4d8c2SCharles.Forsyth 
80*74a4d8c2SCharles.Forsyth /*
81*74a4d8c2SCharles.Forsyth  * initialise the communications processor module
82*74a4d8c2SCharles.Forsyth  * and associated device registers
83*74a4d8c2SCharles.Forsyth  */
84*74a4d8c2SCharles.Forsyth void
cpminit(void)85*74a4d8c2SCharles.Forsyth cpminit(void)
86*74a4d8c2SCharles.Forsyth {
87*74a4d8c2SCharles.Forsyth 	IMM *io;
88*74a4d8c2SCharles.Forsyth 
89*74a4d8c2SCharles.Forsyth 	io = m->iomem;
90*74a4d8c2SCharles.Forsyth 	io->sdcr = 1;
91*74a4d8c2SCharles.Forsyth 	io->rccr = 0;
92*74a4d8c2SCharles.Forsyth 	io->rmds = 0;
93*74a4d8c2SCharles.Forsyth 	io->lccr = 0;	/* disable LCD */
94*74a4d8c2SCharles.Forsyth 	io->vccr = 0;	/* disable video */
95*74a4d8c2SCharles.Forsyth 	io->i2mod = 0;	/* stop I2C */
96*74a4d8c2SCharles.Forsyth 	io->pcint = 0;	/* disable all port C interrupts */
97*74a4d8c2SCharles.Forsyth 	io->pcso = 0;
98*74a4d8c2SCharles.Forsyth 	io->pcdir =0;
99*74a4d8c2SCharles.Forsyth 	io->pcpar = 0;
100*74a4d8c2SCharles.Forsyth 	io->pcdat = 0;
101*74a4d8c2SCharles.Forsyth 	io->papar = 0;
102*74a4d8c2SCharles.Forsyth 	io->padir = 0;
103*74a4d8c2SCharles.Forsyth 	io->paodr = 0;
104*74a4d8c2SCharles.Forsyth 	io->padat = 0;
105*74a4d8c2SCharles.Forsyth 	io->pbpar = 0;
106*74a4d8c2SCharles.Forsyth 	io->pbdir = 0;
107*74a4d8c2SCharles.Forsyth 	io->pbodr = 0;
108*74a4d8c2SCharles.Forsyth 	io->pbdat = 0;
109*74a4d8c2SCharles.Forsyth 	io->tgcr = 0x2222;	/* reset timers, low-power stop */
110*74a4d8c2SCharles.Forsyth 	eieio();
111*74a4d8c2SCharles.Forsyth 
112*74a4d8c2SCharles.Forsyth 	for(io->cpcr = 0x8001; io->cpcr & 1;)	/* reset all CPM channels */
113*74a4d8c2SCharles.Forsyth 		eieio();
114*74a4d8c2SCharles.Forsyth 
115*74a4d8c2SCharles.Forsyth 	mapinit(&bdmap, bdmapv, sizeof(bdmapv));
116*74a4d8c2SCharles.Forsyth 	mapfree(&bdmap, DPBASE, BDSIZE);
117*74a4d8c2SCharles.Forsyth 	mapinit(&cpmmap, cpmmapv, sizeof(cpmmapv));
118*74a4d8c2SCharles.Forsyth 	mapfree(&cpmmap, DPBASE+BDSIZE, CPMSIZE);
119*74a4d8c2SCharles.Forsyth 
120*74a4d8c2SCharles.Forsyth 	if(m->cputype == 0x50 && (getimmr() & 0xFFFF) <= 0x2001)
121*74a4d8c2SCharles.Forsyth 		brgens.avail = 0x3;
122*74a4d8c2SCharles.Forsyth 	else
123*74a4d8c2SCharles.Forsyth 		brgens.avail = 0xF;
124*74a4d8c2SCharles.Forsyth 	i2cspireloc();
125*74a4d8c2SCharles.Forsyth }
126*74a4d8c2SCharles.Forsyth 
127*74a4d8c2SCharles.Forsyth /*
128*74a4d8c2SCharles.Forsyth  * return parameters defining a CPM device, given logical ID
129*74a4d8c2SCharles.Forsyth  */
130*74a4d8c2SCharles.Forsyth CPMdev*
cpmdev(int n)131*74a4d8c2SCharles.Forsyth cpmdev(int n)
132*74a4d8c2SCharles.Forsyth {
133*74a4d8c2SCharles.Forsyth 	CPMdev *d;
134*74a4d8c2SCharles.Forsyth 
135*74a4d8c2SCharles.Forsyth 	if(n < 0 || n >= nelem(cpmdevinfo))
136*74a4d8c2SCharles.Forsyth 		panic("cpmdev");
137*74a4d8c2SCharles.Forsyth 	d = &cpmdevinfo[n];
138*74a4d8c2SCharles.Forsyth 	if(d->param == nil && d->pbase != 0){
139*74a4d8c2SCharles.Forsyth 		if((n == CPi2c || n == CPspi)){
140*74a4d8c2SCharles.Forsyth 			d->param = relocateparam(d->pbase, 0xB0-0x80);	/* relocate */
141*74a4d8c2SCharles.Forsyth 			if(d->param == nil)
142*74a4d8c2SCharles.Forsyth 				return nil;
143*74a4d8c2SCharles.Forsyth 		} else
144*74a4d8c2SCharles.Forsyth 			d->param = (char*)m->iomem+d->pbase;
145*74a4d8c2SCharles.Forsyth 	}
146*74a4d8c2SCharles.Forsyth 	if(d->rbase != 0)
147*74a4d8c2SCharles.Forsyth 		d->regs = (char*)m->iomem+d->rbase;
148*74a4d8c2SCharles.Forsyth 	return d;
149*74a4d8c2SCharles.Forsyth }
150*74a4d8c2SCharles.Forsyth 
151*74a4d8c2SCharles.Forsyth /*
152*74a4d8c2SCharles.Forsyth  * issue a request to a CPM device
153*74a4d8c2SCharles.Forsyth  */
154*74a4d8c2SCharles.Forsyth void
cpmop(CPMdev * cpd,int op,int param)155*74a4d8c2SCharles.Forsyth cpmop(CPMdev *cpd, int op, int param)
156*74a4d8c2SCharles.Forsyth {
157*74a4d8c2SCharles.Forsyth 	IMM *io;
158*74a4d8c2SCharles.Forsyth 
159*74a4d8c2SCharles.Forsyth 	ilock(&cpmlock);
160*74a4d8c2SCharles.Forsyth 	io = m->iomem;
161*74a4d8c2SCharles.Forsyth 	while(io->cpcr & 1)
162*74a4d8c2SCharles.Forsyth 		eieio();
163*74a4d8c2SCharles.Forsyth 	io->cpcr = (op<<8)|(cpd->id<<4)|(param<<1)|1;
164*74a4d8c2SCharles.Forsyth 	eieio();
165*74a4d8c2SCharles.Forsyth 	while(io->cpcr & 1)
166*74a4d8c2SCharles.Forsyth 		eieio();
167*74a4d8c2SCharles.Forsyth 	iunlock(&cpmlock);
168*74a4d8c2SCharles.Forsyth }
169*74a4d8c2SCharles.Forsyth 
170*74a4d8c2SCharles.Forsyth /*
171*74a4d8c2SCharles.Forsyth  * lock the shared IO memory and return a reference to it
172*74a4d8c2SCharles.Forsyth  */
173*74a4d8c2SCharles.Forsyth IMM*
ioplock(void)174*74a4d8c2SCharles.Forsyth ioplock(void)
175*74a4d8c2SCharles.Forsyth {
176*74a4d8c2SCharles.Forsyth 	ilock(&cpmlock);
177*74a4d8c2SCharles.Forsyth 	return m->iomem;
178*74a4d8c2SCharles.Forsyth }
179*74a4d8c2SCharles.Forsyth 
180*74a4d8c2SCharles.Forsyth /*
181*74a4d8c2SCharles.Forsyth  * release the lock on the shared IO memory
182*74a4d8c2SCharles.Forsyth  */
183*74a4d8c2SCharles.Forsyth void
iopunlock(void)184*74a4d8c2SCharles.Forsyth iopunlock(void)
185*74a4d8c2SCharles.Forsyth {
186*74a4d8c2SCharles.Forsyth 	eieio();
187*74a4d8c2SCharles.Forsyth 	iunlock(&cpmlock);
188*74a4d8c2SCharles.Forsyth }
189*74a4d8c2SCharles.Forsyth 
190*74a4d8c2SCharles.Forsyth /*
191*74a4d8c2SCharles.Forsyth  * connect SCCx clocks in NSMI mode (x=1 for USB)
192*74a4d8c2SCharles.Forsyth  */
193*74a4d8c2SCharles.Forsyth void
sccnmsi(int x,int rcs,int tcs)194*74a4d8c2SCharles.Forsyth sccnmsi(int x, int rcs, int tcs)
195*74a4d8c2SCharles.Forsyth {
196*74a4d8c2SCharles.Forsyth 	IMM *io;
197*74a4d8c2SCharles.Forsyth 	ulong v;
198*74a4d8c2SCharles.Forsyth 	int sh;
199*74a4d8c2SCharles.Forsyth 
200*74a4d8c2SCharles.Forsyth 	sh = (x-1)*8;	/* each SCCx field in sicr is 8 bits */
201*74a4d8c2SCharles.Forsyth 	v = (((rcs&7)<<3) | (tcs&7)) << sh;
202*74a4d8c2SCharles.Forsyth 	io = ioplock();
203*74a4d8c2SCharles.Forsyth 	io->sicr = (io->sicr & ~(0xFF<<sh)) | v;
204*74a4d8c2SCharles.Forsyth 	iopunlock();
205*74a4d8c2SCharles.Forsyth }
206*74a4d8c2SCharles.Forsyth 
207*74a4d8c2SCharles.Forsyth /*
208*74a4d8c2SCharles.Forsyth  * connect SMCx clock in NSMI mode
209*74a4d8c2SCharles.Forsyth  */
210*74a4d8c2SCharles.Forsyth void
smcnmsi(int x,int cs)211*74a4d8c2SCharles.Forsyth smcnmsi(int x, int cs)
212*74a4d8c2SCharles.Forsyth {
213*74a4d8c2SCharles.Forsyth 	IMM *io;
214*74a4d8c2SCharles.Forsyth 	ulong v;
215*74a4d8c2SCharles.Forsyth 	int sh;
216*74a4d8c2SCharles.Forsyth 
217*74a4d8c2SCharles.Forsyth 	if(x == 1)
218*74a4d8c2SCharles.Forsyth 		sh = 0;
219*74a4d8c2SCharles.Forsyth 	else
220*74a4d8c2SCharles.Forsyth 		sh = 16;
221*74a4d8c2SCharles.Forsyth 	v = cs << (12+sh);
222*74a4d8c2SCharles.Forsyth 	io = ioplock();
223*74a4d8c2SCharles.Forsyth 	io->simode = (io->simode & ~(0xF000<<sh)) | v;	/* SMCx to NMSI mode, set Tx/Rx clock */
224*74a4d8c2SCharles.Forsyth 	iopunlock();
225*74a4d8c2SCharles.Forsyth }
226*74a4d8c2SCharles.Forsyth 
227*74a4d8c2SCharles.Forsyth /*
228*74a4d8c2SCharles.Forsyth  * claim the use of a CPM ID (SCC, SMC) that might be used by two mutually exclusive devices,
229*74a4d8c2SCharles.Forsyth  * for the caller determined by the given parameter (which must be unique).
230*74a4d8c2SCharles.Forsyth  * returns non-zero if the resource is already in use.
231*74a4d8c2SCharles.Forsyth  */
232*74a4d8c2SCharles.Forsyth int
cpmidopen(int id,void * owner)233*74a4d8c2SCharles.Forsyth cpmidopen(int id, void *owner)
234*74a4d8c2SCharles.Forsyth {
235*74a4d8c2SCharles.Forsyth 	Chanuse *use;
236*74a4d8c2SCharles.Forsyth 
237*74a4d8c2SCharles.Forsyth 	use = &cpmids[id];
238*74a4d8c2SCharles.Forsyth 	ilock(use);
239*74a4d8c2SCharles.Forsyth 	if(use->owner != nil && use->owner != owner){
240*74a4d8c2SCharles.Forsyth 		iunlock(use);
241*74a4d8c2SCharles.Forsyth 		return -1;
242*74a4d8c2SCharles.Forsyth 	}
243*74a4d8c2SCharles.Forsyth 	use->owner = owner;
244*74a4d8c2SCharles.Forsyth 	iunlock(use);
245*74a4d8c2SCharles.Forsyth 	return 0;
246*74a4d8c2SCharles.Forsyth }
247*74a4d8c2SCharles.Forsyth 
248*74a4d8c2SCharles.Forsyth /*
249*74a4d8c2SCharles.Forsyth  * release a previously claimed CPM ID
250*74a4d8c2SCharles.Forsyth  */
251*74a4d8c2SCharles.Forsyth void
cpmidclose(int id)252*74a4d8c2SCharles.Forsyth cpmidclose(int id)
253*74a4d8c2SCharles.Forsyth {
254*74a4d8c2SCharles.Forsyth 	Chanuse *use;
255*74a4d8c2SCharles.Forsyth 
256*74a4d8c2SCharles.Forsyth 	use = &cpmids[id];
257*74a4d8c2SCharles.Forsyth 	ilock(use);
258*74a4d8c2SCharles.Forsyth 	use->owner = nil;
259*74a4d8c2SCharles.Forsyth 	iunlock(use);
260*74a4d8c2SCharles.Forsyth }
261*74a4d8c2SCharles.Forsyth 
262*74a4d8c2SCharles.Forsyth /*
263*74a4d8c2SCharles.Forsyth  * if SCC d is currently enabled, shut it down
264*74a4d8c2SCharles.Forsyth  */
265*74a4d8c2SCharles.Forsyth void
sccxstop(CPMdev * d)266*74a4d8c2SCharles.Forsyth sccxstop(CPMdev *d)
267*74a4d8c2SCharles.Forsyth {
268*74a4d8c2SCharles.Forsyth 	SCC *scc;
269*74a4d8c2SCharles.Forsyth 
270*74a4d8c2SCharles.Forsyth 	if(d == nil)
271*74a4d8c2SCharles.Forsyth 		return;
272*74a4d8c2SCharles.Forsyth 	scc = d->regs;
273*74a4d8c2SCharles.Forsyth 	if(scc->gsmrl & (ENT|ENR)){
274*74a4d8c2SCharles.Forsyth 		if(scc->gsmrl & ENT)
275*74a4d8c2SCharles.Forsyth 			cpmop(d, GracefulStopTx, 0);
276*74a4d8c2SCharles.Forsyth 		if(scc->gsmrl & ENR)
277*74a4d8c2SCharles.Forsyth 			cpmop(d, CloseRxBD, 0);
278*74a4d8c2SCharles.Forsyth 		delay(1);
279*74a4d8c2SCharles.Forsyth 		scc->gsmrl &= ~(ENT|ENR);	/* disable current use */
280*74a4d8c2SCharles.Forsyth 		eieio();
281*74a4d8c2SCharles.Forsyth 	}
282*74a4d8c2SCharles.Forsyth 	scc->sccm = 0;	/* mask interrupts */
283*74a4d8c2SCharles.Forsyth }
284*74a4d8c2SCharles.Forsyth 
285*74a4d8c2SCharles.Forsyth /*
286*74a4d8c2SCharles.Forsyth  * if SMC d is currently enabled, shut it down
287*74a4d8c2SCharles.Forsyth  */
288*74a4d8c2SCharles.Forsyth void
smcxstop(CPMdev * d)289*74a4d8c2SCharles.Forsyth smcxstop(CPMdev *d)
290*74a4d8c2SCharles.Forsyth {
291*74a4d8c2SCharles.Forsyth 	SMC *smc;
292*74a4d8c2SCharles.Forsyth 
293*74a4d8c2SCharles.Forsyth 	if(d == nil)
294*74a4d8c2SCharles.Forsyth 		return;
295*74a4d8c2SCharles.Forsyth 	smc = d->regs;
296*74a4d8c2SCharles.Forsyth 	if(smc->smcmr & (TEN|REN)){
297*74a4d8c2SCharles.Forsyth 		if(smc->smcmr & TEN)
298*74a4d8c2SCharles.Forsyth 			cpmop(d, StopTx, 0);
299*74a4d8c2SCharles.Forsyth 		if(smc->smcmr & REN)
300*74a4d8c2SCharles.Forsyth 			cpmop(d, CloseRxBD, 0);
301*74a4d8c2SCharles.Forsyth 		delay(1);
302*74a4d8c2SCharles.Forsyth 		smc->smcmr &= ~(TEN|REN);
303*74a4d8c2SCharles.Forsyth 		eieio();
304*74a4d8c2SCharles.Forsyth 	}
305*74a4d8c2SCharles.Forsyth 	smc->smcm = 0;	/* mask interrupts */
306*74a4d8c2SCharles.Forsyth }
307*74a4d8c2SCharles.Forsyth 
308*74a4d8c2SCharles.Forsyth /*
309*74a4d8c2SCharles.Forsyth  * allocate a buffer descriptor
310*74a4d8c2SCharles.Forsyth  */
311*74a4d8c2SCharles.Forsyth BD *
bdalloc(int n)312*74a4d8c2SCharles.Forsyth bdalloc(int n)
313*74a4d8c2SCharles.Forsyth {
314*74a4d8c2SCharles.Forsyth 	ulong a;
315*74a4d8c2SCharles.Forsyth 
316*74a4d8c2SCharles.Forsyth 	a = rmapalloc(&bdmap, 0, n*sizeof(BD), sizeof(BD));
317*74a4d8c2SCharles.Forsyth 	if(a == 0)
318*74a4d8c2SCharles.Forsyth 		panic("bdalloc");
319*74a4d8c2SCharles.Forsyth 	return KADDR(a);
320*74a4d8c2SCharles.Forsyth }
321*74a4d8c2SCharles.Forsyth 
322*74a4d8c2SCharles.Forsyth /*
323*74a4d8c2SCharles.Forsyth  * free a buffer descriptor
324*74a4d8c2SCharles.Forsyth  */
325*74a4d8c2SCharles.Forsyth void
bdfree(BD * b,int n)326*74a4d8c2SCharles.Forsyth bdfree(BD *b, int n)
327*74a4d8c2SCharles.Forsyth {
328*74a4d8c2SCharles.Forsyth 	if(b){
329*74a4d8c2SCharles.Forsyth 		eieio();
330*74a4d8c2SCharles.Forsyth 		mapfree(&bdmap, PADDR(b), n*sizeof(BD));
331*74a4d8c2SCharles.Forsyth 	}
332*74a4d8c2SCharles.Forsyth }
333*74a4d8c2SCharles.Forsyth 
334*74a4d8c2SCharles.Forsyth /*
335*74a4d8c2SCharles.Forsyth  * print a buffer descriptor and its data (when debugging)
336*74a4d8c2SCharles.Forsyth  */
337*74a4d8c2SCharles.Forsyth void
dumpbd(char * name,BD * b,int maxn)338*74a4d8c2SCharles.Forsyth dumpbd(char *name, BD *b, int maxn)
339*74a4d8c2SCharles.Forsyth {
340*74a4d8c2SCharles.Forsyth 	uchar *d;
341*74a4d8c2SCharles.Forsyth 	int i;
342*74a4d8c2SCharles.Forsyth 
343*74a4d8c2SCharles.Forsyth 	print("%s #%4.4lux: s=#%4.4ux l=%ud a=#%8.8lux", name, PADDR(b)&0xFFFF, b->status, b->length, b->addr);
344*74a4d8c2SCharles.Forsyth 	if(maxn > b->length)
345*74a4d8c2SCharles.Forsyth 		maxn = b->length;
346*74a4d8c2SCharles.Forsyth 	if(b->addr != 0){
347*74a4d8c2SCharles.Forsyth 		d = KADDR(b->addr);
348*74a4d8c2SCharles.Forsyth 		for(i=0; i<maxn; i++)
349*74a4d8c2SCharles.Forsyth 			print(" %2.2ux", d[i]);
350*74a4d8c2SCharles.Forsyth 		if(i < b->length)
351*74a4d8c2SCharles.Forsyth 			print(" ...");
352*74a4d8c2SCharles.Forsyth 	}
353*74a4d8c2SCharles.Forsyth 	print("\n");
354*74a4d8c2SCharles.Forsyth }
355*74a4d8c2SCharles.Forsyth 
356*74a4d8c2SCharles.Forsyth /*
357*74a4d8c2SCharles.Forsyth  * allocate memory from the shared IO memory space
358*74a4d8c2SCharles.Forsyth  */
359*74a4d8c2SCharles.Forsyth void *
cpmalloc(int n,int align)360*74a4d8c2SCharles.Forsyth cpmalloc(int n, int align)
361*74a4d8c2SCharles.Forsyth {
362*74a4d8c2SCharles.Forsyth 	ulong a;
363*74a4d8c2SCharles.Forsyth 
364*74a4d8c2SCharles.Forsyth 	a = rmapalloc(&cpmmap, 0, n, align);
365*74a4d8c2SCharles.Forsyth 	if(a == 0)
366*74a4d8c2SCharles.Forsyth 		panic("cpmalloc");
367*74a4d8c2SCharles.Forsyth 	return KADDR(a);
368*74a4d8c2SCharles.Forsyth }
369*74a4d8c2SCharles.Forsyth 
370*74a4d8c2SCharles.Forsyth /*
371*74a4d8c2SCharles.Forsyth  * free previously allocated shared memory
372*74a4d8c2SCharles.Forsyth  */
373*74a4d8c2SCharles.Forsyth void
cpmfree(void * p,int n)374*74a4d8c2SCharles.Forsyth cpmfree(void *p, int n)
375*74a4d8c2SCharles.Forsyth {
376*74a4d8c2SCharles.Forsyth 	if(p != nil && n > 0){
377*74a4d8c2SCharles.Forsyth 		eieio();
378*74a4d8c2SCharles.Forsyth 		mapfree(&cpmmap, PADDR(p), n);
379*74a4d8c2SCharles.Forsyth 	}
380*74a4d8c2SCharles.Forsyth }
381*74a4d8c2SCharles.Forsyth 
382*74a4d8c2SCharles.Forsyth /*
383*74a4d8c2SCharles.Forsyth  * allocate a baud rate generator, returning its index
384*74a4d8c2SCharles.Forsyth  * (or -1 if none is available)
385*74a4d8c2SCharles.Forsyth  */
386*74a4d8c2SCharles.Forsyth int
brgalloc(void)387*74a4d8c2SCharles.Forsyth brgalloc(void)
388*74a4d8c2SCharles.Forsyth {
389*74a4d8c2SCharles.Forsyth 	int n;
390*74a4d8c2SCharles.Forsyth 
391*74a4d8c2SCharles.Forsyth 	lock(&brgens);
392*74a4d8c2SCharles.Forsyth 	for(n=0; brgens.avail!=0; n++)
393*74a4d8c2SCharles.Forsyth 		if(brgens.avail & (1<<n)){
394*74a4d8c2SCharles.Forsyth 			brgens.avail &= ~(1<<n);
395*74a4d8c2SCharles.Forsyth 			unlock(&brgens);
396*74a4d8c2SCharles.Forsyth 			return n;
397*74a4d8c2SCharles.Forsyth 		}
398*74a4d8c2SCharles.Forsyth 	unlock(&brgens);
399*74a4d8c2SCharles.Forsyth 	return -1;
400*74a4d8c2SCharles.Forsyth }
401*74a4d8c2SCharles.Forsyth 
402*74a4d8c2SCharles.Forsyth /*
403*74a4d8c2SCharles.Forsyth  * free a previously allocated baud rate generator
404*74a4d8c2SCharles.Forsyth  */
405*74a4d8c2SCharles.Forsyth void
brgfree(int n)406*74a4d8c2SCharles.Forsyth brgfree(int n)
407*74a4d8c2SCharles.Forsyth {
408*74a4d8c2SCharles.Forsyth 	if(n >= 0){
409*74a4d8c2SCharles.Forsyth 		if(n > 3 || brgens.avail & (1<<n))
410*74a4d8c2SCharles.Forsyth 			panic("brgfree");
411*74a4d8c2SCharles.Forsyth 		lock(&brgens);
412*74a4d8c2SCharles.Forsyth 		brgens.avail |= 1 << n;
413*74a4d8c2SCharles.Forsyth 		unlock(&brgens);
414*74a4d8c2SCharles.Forsyth 	}
415*74a4d8c2SCharles.Forsyth }
416*74a4d8c2SCharles.Forsyth 
417*74a4d8c2SCharles.Forsyth /*
418*74a4d8c2SCharles.Forsyth  * return a value suitable for loading into a baud rate
419*74a4d8c2SCharles.Forsyth  * generator to produce the given rate if the generator
420*74a4d8c2SCharles.Forsyth  * is prescaled by the given amount (typically 16).
421*74a4d8c2SCharles.Forsyth  * the value must be or'd with BaudEnable to start the generator.
422*74a4d8c2SCharles.Forsyth  */
423*74a4d8c2SCharles.Forsyth ulong
baudgen(int rate,int scale)424*74a4d8c2SCharles.Forsyth baudgen(int rate, int scale)
425*74a4d8c2SCharles.Forsyth {
426*74a4d8c2SCharles.Forsyth 	int d;
427*74a4d8c2SCharles.Forsyth 
428*74a4d8c2SCharles.Forsyth 	rate *= scale;
429*74a4d8c2SCharles.Forsyth 	d = (2*m->cpuhz+rate)/(2*rate) - 1;
430*74a4d8c2SCharles.Forsyth 	if(d < 0)
431*74a4d8c2SCharles.Forsyth 		d = 0;
432*74a4d8c2SCharles.Forsyth 	if(d >= (1<<12))
433*74a4d8c2SCharles.Forsyth 		return ((d+15)>>(4-1))|1;	/* divider too big: enable prescale by 16 */
434*74a4d8c2SCharles.Forsyth 	return d<<1;
435*74a4d8c2SCharles.Forsyth }
436*74a4d8c2SCharles.Forsyth 
437*74a4d8c2SCharles.Forsyth /*
438*74a4d8c2SCharles.Forsyth  * initialise receive and transmit buffer rings.
439*74a4d8c2SCharles.Forsyth  */
440*74a4d8c2SCharles.Forsyth int
ioringinit(Ring * r,int nrdre,int ntdre,int bufsize)441*74a4d8c2SCharles.Forsyth ioringinit(Ring* r, int nrdre, int ntdre, int bufsize)
442*74a4d8c2SCharles.Forsyth {
443*74a4d8c2SCharles.Forsyth 	int i, x;
444*74a4d8c2SCharles.Forsyth 
445*74a4d8c2SCharles.Forsyth 	/* the ring entries must be aligned on sizeof(BD) boundaries */
446*74a4d8c2SCharles.Forsyth 	r->nrdre = nrdre;
447*74a4d8c2SCharles.Forsyth 	if(r->rdr == nil)
448*74a4d8c2SCharles.Forsyth 		r->rdr = bdalloc(nrdre);
449*74a4d8c2SCharles.Forsyth 	/* the buffer size must align with cache lines since the cache doesn't snoop */
450*74a4d8c2SCharles.Forsyth 	bufsize = (bufsize+CACHELINESZ-1)&~(CACHELINESZ-1);
451*74a4d8c2SCharles.Forsyth 	if(r->rrb == nil)
452*74a4d8c2SCharles.Forsyth 		r->rrb = malloc(nrdre*bufsize);
453*74a4d8c2SCharles.Forsyth 	if(r->rdr == nil || r->rrb == nil)
454*74a4d8c2SCharles.Forsyth 		return -1;
455*74a4d8c2SCharles.Forsyth 	dcflush(r->rrb, nrdre*bufsize);
456*74a4d8c2SCharles.Forsyth 	x = PADDR(r->rrb);
457*74a4d8c2SCharles.Forsyth 	for(i = 0; i < nrdre; i++){
458*74a4d8c2SCharles.Forsyth 		r->rdr[i].length = 0;
459*74a4d8c2SCharles.Forsyth 		r->rdr[i].addr = x;
460*74a4d8c2SCharles.Forsyth 		r->rdr[i].status = BDEmpty|BDInt;
461*74a4d8c2SCharles.Forsyth 		x += bufsize;
462*74a4d8c2SCharles.Forsyth 	}
463*74a4d8c2SCharles.Forsyth 	r->rdr[i-1].status |= BDWrap;
464*74a4d8c2SCharles.Forsyth 	r->rdrx = 0;
465*74a4d8c2SCharles.Forsyth 
466*74a4d8c2SCharles.Forsyth 	r->ntdre = ntdre;
467*74a4d8c2SCharles.Forsyth 	if(r->tdr == nil)
468*74a4d8c2SCharles.Forsyth 		r->tdr = bdalloc(ntdre);
469*74a4d8c2SCharles.Forsyth 	if(r->txb == nil)
470*74a4d8c2SCharles.Forsyth 		r->txb = malloc(ntdre*sizeof(Block*));
471*74a4d8c2SCharles.Forsyth 	if(r->tdr == nil || r->txb == nil)
472*74a4d8c2SCharles.Forsyth 		return -1;
473*74a4d8c2SCharles.Forsyth 	for(i = 0; i < ntdre; i++){
474*74a4d8c2SCharles.Forsyth 		r->txb[i] = nil;
475*74a4d8c2SCharles.Forsyth 		r->tdr[i].addr = 0;
476*74a4d8c2SCharles.Forsyth 		r->tdr[i].length = 0;
477*74a4d8c2SCharles.Forsyth 		r->tdr[i].status = 0;
478*74a4d8c2SCharles.Forsyth 	}
479*74a4d8c2SCharles.Forsyth 	r->tdr[i-1].status |= BDWrap;
480*74a4d8c2SCharles.Forsyth 	r->tdrh = 0;
481*74a4d8c2SCharles.Forsyth 	r->tdri = 0;
482*74a4d8c2SCharles.Forsyth 	r->ntq = 0;
483*74a4d8c2SCharles.Forsyth 	return 0;
484*74a4d8c2SCharles.Forsyth }
485*74a4d8c2SCharles.Forsyth 
486*74a4d8c2SCharles.Forsyth /*
487*74a4d8c2SCharles.Forsyth  * Allocate a new parameter block for I2C or SPI,
488*74a4d8c2SCharles.Forsyth  * and plant a pointer to it for the microcode, returning the kernel address.
489*74a4d8c2SCharles.Forsyth  * See Motorola errata and microcode package:
490*74a4d8c2SCharles.Forsyth  * the design botch is that the parameters for the SCC2 ethernet overlap the
491*74a4d8c2SCharles.Forsyth  * SPI/I2C parameter space; this compensates by relocating the latter.
492*74a4d8c2SCharles.Forsyth  * This routine may be used iff i2cspireloc is used (and it is, above).
493*74a4d8c2SCharles.Forsyth  */
494*74a4d8c2SCharles.Forsyth static void*
relocateparam(ulong olda,int nb)495*74a4d8c2SCharles.Forsyth relocateparam(ulong olda, int nb)
496*74a4d8c2SCharles.Forsyth {
497*74a4d8c2SCharles.Forsyth 	void *p;
498*74a4d8c2SCharles.Forsyth 
499*74a4d8c2SCharles.Forsyth 	if(olda < (ulong)m->iomem)
500*74a4d8c2SCharles.Forsyth 		olda += (ulong)m->iomem;
501*74a4d8c2SCharles.Forsyth 	p = cpmalloc(nb, 32);	/* ``RPBASE must be multiple of 32'' */
502*74a4d8c2SCharles.Forsyth 	if(p == nil)
503*74a4d8c2SCharles.Forsyth 		return p;
504*74a4d8c2SCharles.Forsyth 	*(ushort*)KADDR(olda+0x2C) = PADDR(p);	/* set RPBASE */
505*74a4d8c2SCharles.Forsyth 	eieio();
506*74a4d8c2SCharles.Forsyth 	return p;
507*74a4d8c2SCharles.Forsyth }
508*74a4d8c2SCharles.Forsyth 
509*74a4d8c2SCharles.Forsyth /*
510*74a4d8c2SCharles.Forsyth  * I2C/SPI microcode package from Motorola
511*74a4d8c2SCharles.Forsyth  * (to relocate I2C/SPI parameters), which was distributed
512*74a4d8c2SCharles.Forsyth  * on their web site in S-record format.
513*74a4d8c2SCharles.Forsyth  *
514*74a4d8c2SCharles.Forsyth  *	May 1998
515*74a4d8c2SCharles.Forsyth  */
516*74a4d8c2SCharles.Forsyth 
517*74a4d8c2SCharles.Forsyth /*S00600004844521B*/
518*74a4d8c2SCharles.Forsyth static	ulong	ubase1 = 0x2000;
519*74a4d8c2SCharles.Forsyth static	ulong	ucode1[] = {
520*74a4d8c2SCharles.Forsyth  /* #02202000 */ 0x7FFFEFD9,
521*74a4d8c2SCharles.Forsyth  /* #02202004 */ 0x3FFD0000,
522*74a4d8c2SCharles.Forsyth  /* #02202008 */ 0x7FFB49F7,
523*74a4d8c2SCharles.Forsyth  /* #0220200C */ 0x7FF90000,
524*74a4d8c2SCharles.Forsyth  /* #02202010 */ 0x5FEFADF7,
525*74a4d8c2SCharles.Forsyth  /* #02202014 */ 0x5F89ADF7,
526*74a4d8c2SCharles.Forsyth  /* #02202018 */ 0x5FEFAFF7,
527*74a4d8c2SCharles.Forsyth  /* #0220201C */ 0x5F89AFF7,
528*74a4d8c2SCharles.Forsyth  /* #02202020 */ 0x3A9CFBC8,
529*74a4d8c2SCharles.Forsyth  /* #02202024 */ 0xE7C0EDF0,
530*74a4d8c2SCharles.Forsyth  /* #02202028 */ 0x77C1E1BB,
531*74a4d8c2SCharles.Forsyth  /* #0220202C */ 0xF4DC7F1D,
532*74a4d8c2SCharles.Forsyth  /* #02202030 */ 0xABAD932F,
533*74a4d8c2SCharles.Forsyth  /* #02202034 */ 0x4E08FDCF,
534*74a4d8c2SCharles.Forsyth  /* #02202038 */ 0x6E0FAFF8,
535*74a4d8c2SCharles.Forsyth  /* #0220203C */ 0x7CCF76CF,
536*74a4d8c2SCharles.Forsyth  /* #02202040 */ 0xFD1FF9CF,
537*74a4d8c2SCharles.Forsyth  /* #02202044 */ 0xABF88DC6,
538*74a4d8c2SCharles.Forsyth  /* #02202048 */ 0xAB5679F7,
539*74a4d8c2SCharles.Forsyth  /* #0220204C */ 0xB0937383,
540*74a4d8c2SCharles.Forsyth  /* #02202050 */ 0xDFCE79F7,
541*74a4d8c2SCharles.Forsyth  /* #02202054 */ 0xB091E6BB,
542*74a4d8c2SCharles.Forsyth  /* #02202058 */ 0xE5BBE74F,
543*74a4d8c2SCharles.Forsyth  /* #0220205C */ 0xB3FA6F0F,
544*74a4d8c2SCharles.Forsyth  /* #02202060 */ 0x6FFB76CE,
545*74a4d8c2SCharles.Forsyth  /* #02202064 */ 0xEE0DF9CF,
546*74a4d8c2SCharles.Forsyth  /* #02202068 */ 0x2BFBEFEF,
547*74a4d8c2SCharles.Forsyth  /* #0220206C */ 0xCFEEF9CF,
548*74a4d8c2SCharles.Forsyth  /* #02202070 */ 0x76CEAD24,
549*74a4d8c2SCharles.Forsyth  /* #02202074 */ 0x90B2DF9A,
550*74a4d8c2SCharles.Forsyth  /* #02202078 */ 0x7FDDD0BF,
551*74a4d8c2SCharles.Forsyth  /* #0220207C */ 0x4BF847FD,
552*74a4d8c2SCharles.Forsyth  /* #02202080 */ 0x7CCF76CE,
553*74a4d8c2SCharles.Forsyth  /* #02202084 */ 0xCFEF7E1F,
554*74a4d8c2SCharles.Forsyth  /* #02202088 */ 0x7F1D7DFD,
555*74a4d8c2SCharles.Forsyth  /* #0220208C */ 0xF0B6EF71,
556*74a4d8c2SCharles.Forsyth  /* #02202090 */ 0x7FC177C1,
557*74a4d8c2SCharles.Forsyth  /* #02202094 */ 0xFBC86079,
558*74a4d8c2SCharles.Forsyth  /* #02202098 */ 0xE722FBC8,
559*74a4d8c2SCharles.Forsyth  /* #0220209C */ 0x5FFFDFFF,
560*74a4d8c2SCharles.Forsyth  /* #022020A0 */ 0x5FB2FFFB,
561*74a4d8c2SCharles.Forsyth  /* #022020A4 */ 0xFBC8F3C8,
562*74a4d8c2SCharles.Forsyth  /* #022020A8 */ 0x94A67F01,
563*74a4d8c2SCharles.Forsyth  /* #022020AC */ 0x7F1D5F39,
564*74a4d8c2SCharles.Forsyth  /* #022020B0 */ 0xAFE85F5E,
565*74a4d8c2SCharles.Forsyth  /* #022020B4 */ 0xFFDFDF96,
566*74a4d8c2SCharles.Forsyth  /* #022020B8 */ 0xCB9FAF7D,
567*74a4d8c2SCharles.Forsyth  /* #022020BC */ 0x5FC1AFED,
568*74a4d8c2SCharles.Forsyth  /* #022020C0 */ 0x8C1C5FC1,
569*74a4d8c2SCharles.Forsyth  /* #022020C4 */ 0xAFDD5FC3,
570*74a4d8c2SCharles.Forsyth  /* #022020C8 */ 0xDF9A7EFD,
571*74a4d8c2SCharles.Forsyth  /* #022020CC */ 0xB0B25FB2,
572*74a4d8c2SCharles.Forsyth  /* #022020D0 */ 0xFFFEABAD,
573*74a4d8c2SCharles.Forsyth  /* #022020D4 */ 0x5FB2FFFE,
574*74a4d8c2SCharles.Forsyth  /* #022020D8 */ 0x5FCE600B,
575*74a4d8c2SCharles.Forsyth  /* #022020DC */ 0xE6BB600B,
576*74a4d8c2SCharles.Forsyth  /* #022020E0 */ 0x5FCEDFC6,
577*74a4d8c2SCharles.Forsyth  /* #022020E4 */ 0x27FBEFDF,
578*74a4d8c2SCharles.Forsyth  /* #022020E8 */ 0x5FC8CFDE,
579*74a4d8c2SCharles.Forsyth  /* #022020EC */ 0x3A9CE7C0,
580*74a4d8c2SCharles.Forsyth  /* #022020F0 */ 0xEDF0F3C8,
581*74a4d8c2SCharles.Forsyth  /* #022020F4 */ 0x7F0154CD,
582*74a4d8c2SCharles.Forsyth  /* #022020F8 */ 0x7F1D2D3D,
583*74a4d8c2SCharles.Forsyth  /* #022020FC */ 0x363A7570,
584*74a4d8c2SCharles.Forsyth  /* #02202100 */ 0x7E0AF1CE,
585*74a4d8c2SCharles.Forsyth  /* #02202104 */ 0x37EF2E68,
586*74a4d8c2SCharles.Forsyth  /* #02202108 */ 0x7FEE10EC,
587*74a4d8c2SCharles.Forsyth  /* #0220210C */ 0xADF8EFDE,
588*74a4d8c2SCharles.Forsyth  /* #02202110 */ 0xCFEAE52F,
589*74a4d8c2SCharles.Forsyth  /* #02202114 */ 0x7D0FE12B,
590*74a4d8c2SCharles.Forsyth  /* #02202118 */ 0xF1CE5F65,
591*74a4d8c2SCharles.Forsyth  /* #0220211C */ 0x7E0A4DF8,
592*74a4d8c2SCharles.Forsyth  /* #02202120 */ 0xCFEA5F72,
593*74a4d8c2SCharles.Forsyth  /* #02202124 */ 0x7D0BEFEE,
594*74a4d8c2SCharles.Forsyth  /* #02202128 */ 0xCFEA5F74,
595*74a4d8c2SCharles.Forsyth  /* #0220212C */ 0xE522EFDE,
596*74a4d8c2SCharles.Forsyth  /* #02202130 */ 0x5F74CFDA,
597*74a4d8c2SCharles.Forsyth  /* #02202134 */ 0x0B627385,
598*74a4d8c2SCharles.Forsyth  /* #02202138 */ 0xDF627E0A,
599*74a4d8c2SCharles.Forsyth  /* #0220213C */ 0x30D8145B,
600*74a4d8c2SCharles.Forsyth  /* #02202140 */ 0xBFFFF3C8,
601*74a4d8c2SCharles.Forsyth  /* #02202144 */ 0x5FFFDFFF,
602*74a4d8c2SCharles.Forsyth  /* #02202148 */ 0xA7F85F5E,
603*74a4d8c2SCharles.Forsyth  /* #0220214C */ 0xBFFE7F7D,
604*74a4d8c2SCharles.Forsyth  /* #02202150 */ 0x10D31450,
605*74a4d8c2SCharles.Forsyth  /* #02202154 */ 0x5F36BFFF,
606*74a4d8c2SCharles.Forsyth  /* #02202158 */ 0xAF785F5E,
607*74a4d8c2SCharles.Forsyth  /* #0220215C */ 0xBFFDA7F8,
608*74a4d8c2SCharles.Forsyth  /* #02202160 */ 0x5F36BFFE,
609*74a4d8c2SCharles.Forsyth  /* #02202164 */ 0x77FD30C0,
610*74a4d8c2SCharles.Forsyth  /* #02202168 */ 0x4E08FDCF,
611*74a4d8c2SCharles.Forsyth  /* #0220216C */ 0xE5FF6E0F,
612*74a4d8c2SCharles.Forsyth  /* #02202170 */ 0xAFF87E1F,
613*74a4d8c2SCharles.Forsyth  /* #02202174 */ 0x7E0FFD1F,
614*74a4d8c2SCharles.Forsyth  /* #02202178 */ 0xF1CF5F1B,
615*74a4d8c2SCharles.Forsyth  /* #0220217C */ 0xABF80D5E,
616*74a4d8c2SCharles.Forsyth  /* #02202180 */ 0x5F5EFFEF,
617*74a4d8c2SCharles.Forsyth  /* #02202184 */ 0x79F730A2,
618*74a4d8c2SCharles.Forsyth  /* #02202188 */ 0xAFDD5F34,
619*74a4d8c2SCharles.Forsyth  /* #0220218C */ 0x47F85F34,
620*74a4d8c2SCharles.Forsyth  /* #02202190 */ 0xAFED7FDD,
621*74a4d8c2SCharles.Forsyth  /* #02202194 */ 0x50B24978,
622*74a4d8c2SCharles.Forsyth  /* #02202198 */ 0x47FD7F1D,
623*74a4d8c2SCharles.Forsyth  /* #0220219C */ 0x7DFD70AD,
624*74a4d8c2SCharles.Forsyth  /* #022021A0 */ 0xEF717EC1,
625*74a4d8c2SCharles.Forsyth  /* #022021A4 */ 0x6BA47F01,
626*74a4d8c2SCharles.Forsyth  /* #022021A8 */ 0x2D267EFD,
627*74a4d8c2SCharles.Forsyth  /* #022021AC */ 0x30DE5F5E,
628*74a4d8c2SCharles.Forsyth  /* #022021B0 */ 0xFFFD5F5E,
629*74a4d8c2SCharles.Forsyth  /* #022021B4 */ 0xFFEF5F5E,
630*74a4d8c2SCharles.Forsyth  /* #022021B8 */ 0xFFDF0CA0,
631*74a4d8c2SCharles.Forsyth  /* #022021BC */ 0xAFED0A9E,
632*74a4d8c2SCharles.Forsyth  /* #022021C0 */ 0xAFDD0C3A,
633*74a4d8c2SCharles.Forsyth  /* #022021C4 */ 0x5F3AAFBD,
634*74a4d8c2SCharles.Forsyth  /* #022021C8 */ 0x7FBDB082,
635*74a4d8c2SCharles.Forsyth  /* #022021CC */ 0x5F8247F8,
636*74a4d8c2SCharles.Forsyth };
637*74a4d8c2SCharles.Forsyth 
638*74a4d8c2SCharles.Forsyth /*S00600004844521B*/
639*74a4d8c2SCharles.Forsyth static	ulong	ubase2 = 0x2F00;
640*74a4d8c2SCharles.Forsyth static	ulong	ucode2[] = {
641*74a4d8c2SCharles.Forsyth  /* #02202F00 */ 0x3E303430,
642*74a4d8c2SCharles.Forsyth  /* #02202F04 */ 0x34343737,
643*74a4d8c2SCharles.Forsyth  /* #02202F08 */ 0xABF7BF9B,
644*74a4d8c2SCharles.Forsyth  /* #02202F0C */ 0x994B4FBD,
645*74a4d8c2SCharles.Forsyth  /* #02202F10 */ 0xBD599493,
646*74a4d8c2SCharles.Forsyth  /* #02202F14 */ 0x349FFF37,
647*74a4d8c2SCharles.Forsyth  /* #02202F18 */ 0xFB9B177D,
648*74a4d8c2SCharles.Forsyth  /* #02202F1C */ 0xD9936956,
649*74a4d8c2SCharles.Forsyth  /* #02202F20 */ 0xBBFDD697,
650*74a4d8c2SCharles.Forsyth  /* #02202F24 */ 0xBDD2FD11,
651*74a4d8c2SCharles.Forsyth  /* #02202F28 */ 0x31DB9BB3,
652*74a4d8c2SCharles.Forsyth  /* #02202F2C */ 0x63139637,
653*74a4d8c2SCharles.Forsyth  /* #02202F30 */ 0x93733693,
654*74a4d8c2SCharles.Forsyth  /* #02202F34 */ 0x193137F7,
655*74a4d8c2SCharles.Forsyth  /* #02202F38 */ 0x331737AF,
656*74a4d8c2SCharles.Forsyth  /* #02202F3C */ 0x7BB9B999,
657*74a4d8c2SCharles.Forsyth  /* #02202F40 */ 0xBB197957,
658*74a4d8c2SCharles.Forsyth  /* #02202F44 */ 0x7FDFD3D5,
659*74a4d8c2SCharles.Forsyth  /* #02202F48 */ 0x73B773F7,
660*74a4d8c2SCharles.Forsyth  /* #02202F4C */ 0x37933B99,
661*74a4d8c2SCharles.Forsyth  /* #02202F50 */ 0x1D115316,
662*74a4d8c2SCharles.Forsyth  /* #02202F54 */ 0x99315315,
663*74a4d8c2SCharles.Forsyth  /* #02202F58 */ 0x31694BF4,
664*74a4d8c2SCharles.Forsyth  /* #02202F5C */ 0xFBDBD359,
665*74a4d8c2SCharles.Forsyth  /* #02202F60 */ 0x31497353,
666*74a4d8c2SCharles.Forsyth  /* #02202F64 */ 0x76956D69,
667*74a4d8c2SCharles.Forsyth  /* #02202F68 */ 0x7B9D9693,
668*74a4d8c2SCharles.Forsyth  /* #02202F6C */ 0x13131979,
669*74a4d8c2SCharles.Forsyth  /* #02202F70 */ 0x79376935,
670*74a4d8c2SCharles.Forsyth };
671*74a4d8c2SCharles.Forsyth 
672*74a4d8c2SCharles.Forsyth /*
673*74a4d8c2SCharles.Forsyth  * compensate for chip design botch by installing
674*74a4d8c2SCharles.Forsyth  * microcode to relocate I2C and SPI parameters away
675*74a4d8c2SCharles.Forsyth  * from the ethernet parameters
676*74a4d8c2SCharles.Forsyth  */
677*74a4d8c2SCharles.Forsyth static void
i2cspireloc(void)678*74a4d8c2SCharles.Forsyth i2cspireloc(void)
679*74a4d8c2SCharles.Forsyth {
680*74a4d8c2SCharles.Forsyth 	IMM *io;
681*74a4d8c2SCharles.Forsyth 	static int done;
682*74a4d8c2SCharles.Forsyth 
683*74a4d8c2SCharles.Forsyth 	if(done)
684*74a4d8c2SCharles.Forsyth 		return;
685*74a4d8c2SCharles.Forsyth 	io = m->iomem;
686*74a4d8c2SCharles.Forsyth 	io->rccr &= ~3;
687*74a4d8c2SCharles.Forsyth 	memmove((uchar*)m->iomem+ubase1, ucode1, sizeof(ucode1));
688*74a4d8c2SCharles.Forsyth 	memmove((uchar*)m->iomem+ubase2, ucode2, sizeof(ucode2));
689*74a4d8c2SCharles.Forsyth 	io->rctr1 = 0x802a;	/* relocate SPI */
690*74a4d8c2SCharles.Forsyth 	io->rctr2 = 0x8028;	/* relocate SPI */
691*74a4d8c2SCharles.Forsyth 	io->rctr3 = 0x802e;	/* relocate I2C */
692*74a4d8c2SCharles.Forsyth 	io->rctr4 = 0x802c;	/* relocate I2C */
693*74a4d8c2SCharles.Forsyth 	io->rccr |= 1;
694*74a4d8c2SCharles.Forsyth 	done = 1;
695*74a4d8c2SCharles.Forsyth }
696