1*74a4d8c2SCharles.Forsyth /*
2*74a4d8c2SCharles.Forsyth * SCCn ethernet
3*74a4d8c2SCharles.Forsyth */
4*74a4d8c2SCharles.Forsyth
5*74a4d8c2SCharles.Forsyth #include "u.h"
6*74a4d8c2SCharles.Forsyth #include "lib.h"
7*74a4d8c2SCharles.Forsyth #include "mem.h"
8*74a4d8c2SCharles.Forsyth #include "dat.h"
9*74a4d8c2SCharles.Forsyth #include "fns.h"
10*74a4d8c2SCharles.Forsyth #include "io.h"
11*74a4d8c2SCharles.Forsyth
12*74a4d8c2SCharles.Forsyth #include "etherif.h"
13*74a4d8c2SCharles.Forsyth
14*74a4d8c2SCharles.Forsyth enum {
15*74a4d8c2SCharles.Forsyth Nrdre = 32, /* receive descriptor ring entries */
16*74a4d8c2SCharles.Forsyth Ntdre = 4, /* transmit descriptor ring entries */
17*74a4d8c2SCharles.Forsyth
18*74a4d8c2SCharles.Forsyth Rbsize = ETHERMAXTU+4, /* ring buffer size (+4 for CRC) */
19*74a4d8c2SCharles.Forsyth Bufsize = (Rbsize+7)&~7, /* aligned */
20*74a4d8c2SCharles.Forsyth };
21*74a4d8c2SCharles.Forsyth
22*74a4d8c2SCharles.Forsyth enum {
23*74a4d8c2SCharles.Forsyth /* ether-specific Rx BD bits */
24*74a4d8c2SCharles.Forsyth RxMiss= 1<<8,
25*74a4d8c2SCharles.Forsyth RxeLG= 1<<5,
26*74a4d8c2SCharles.Forsyth RxeNO= 1<<4,
27*74a4d8c2SCharles.Forsyth RxeSH= 1<<3,
28*74a4d8c2SCharles.Forsyth RxeCR= 1<<2,
29*74a4d8c2SCharles.Forsyth RxeOV= 1<<1,
30*74a4d8c2SCharles.Forsyth RxeCL= 1<<0,
31*74a4d8c2SCharles.Forsyth RxError= (RxeLG|RxeNO|RxeSH|RxeCR|RxeOV|RxeCL), /* various error flags */
32*74a4d8c2SCharles.Forsyth
33*74a4d8c2SCharles.Forsyth /* ether-specific Tx BD bits */
34*74a4d8c2SCharles.Forsyth TxPad= 1<<14, /* pad short frames */
35*74a4d8c2SCharles.Forsyth TxTC= 1<<10, /* transmit CRC */
36*74a4d8c2SCharles.Forsyth TxeDEF= 1<<9,
37*74a4d8c2SCharles.Forsyth TxeHB= 1<<8,
38*74a4d8c2SCharles.Forsyth TxeLC= 1<<7,
39*74a4d8c2SCharles.Forsyth TxeRL= 1<<6,
40*74a4d8c2SCharles.Forsyth TxeUN= 1<<1,
41*74a4d8c2SCharles.Forsyth TxeCSL= 1<<0,
42*74a4d8c2SCharles.Forsyth
43*74a4d8c2SCharles.Forsyth /* scce */
44*74a4d8c2SCharles.Forsyth RXB= 1<<0,
45*74a4d8c2SCharles.Forsyth TXB= 1<<1,
46*74a4d8c2SCharles.Forsyth BSY= 1<<2,
47*74a4d8c2SCharles.Forsyth RXF= 1<<3,
48*74a4d8c2SCharles.Forsyth TXE= 1<<4,
49*74a4d8c2SCharles.Forsyth
50*74a4d8c2SCharles.Forsyth /* gsmrl */
51*74a4d8c2SCharles.Forsyth ENR= 1<<5,
52*74a4d8c2SCharles.Forsyth ENT= 1<<4,
53*74a4d8c2SCharles.Forsyth
54*74a4d8c2SCharles.Forsyth /* port A */
55*74a4d8c2SCharles.Forsyth RXD1= SIBIT(15),
56*74a4d8c2SCharles.Forsyth TXD1= SIBIT(14),
57*74a4d8c2SCharles.Forsyth
58*74a4d8c2SCharles.Forsyth /* port B */
59*74a4d8c2SCharles.Forsyth RTS1= IBIT(19),
60*74a4d8c2SCharles.Forsyth
61*74a4d8c2SCharles.Forsyth /* port C */
62*74a4d8c2SCharles.Forsyth CTS1= SIBIT(11),
63*74a4d8c2SCharles.Forsyth CD1= SIBIT(10),
64*74a4d8c2SCharles.Forsyth };
65*74a4d8c2SCharles.Forsyth
66*74a4d8c2SCharles.Forsyth typedef struct Etherparam Etherparam;
67*74a4d8c2SCharles.Forsyth struct Etherparam {
68*74a4d8c2SCharles.Forsyth SCCparam;
69*74a4d8c2SCharles.Forsyth ulong c_pres; /* preset CRC */
70*74a4d8c2SCharles.Forsyth ulong c_mask; /* constant mask for CRC */
71*74a4d8c2SCharles.Forsyth ulong crcec; /* CRC error counter */
72*74a4d8c2SCharles.Forsyth ulong alec; /* alighnment error counter */
73*74a4d8c2SCharles.Forsyth ulong disfc; /* discard frame counter */
74*74a4d8c2SCharles.Forsyth ushort pads; /* short frame PAD characters */
75*74a4d8c2SCharles.Forsyth ushort ret_lim; /* retry limit threshold */
76*74a4d8c2SCharles.Forsyth ushort ret_cnt; /* retry limit counter */
77*74a4d8c2SCharles.Forsyth ushort mflr; /* maximum frame length reg */
78*74a4d8c2SCharles.Forsyth ushort minflr; /* minimum frame length reg */
79*74a4d8c2SCharles.Forsyth ushort maxd1; /* maximum DMA1 length reg */
80*74a4d8c2SCharles.Forsyth ushort maxd2; /* maximum DMA2 length reg */
81*74a4d8c2SCharles.Forsyth ushort maxd; /* rx max DMA */
82*74a4d8c2SCharles.Forsyth ushort dma_cnt; /* rx dma counter */
83*74a4d8c2SCharles.Forsyth ushort max_b; /* max bd byte count */
84*74a4d8c2SCharles.Forsyth ushort gaddr[4]; /* group address filter */
85*74a4d8c2SCharles.Forsyth ulong tbuf0_data0; /* save area 0 - current frm */
86*74a4d8c2SCharles.Forsyth ulong tbuf0_data1; /* save area 1 - current frm */
87*74a4d8c2SCharles.Forsyth ulong tbuf0_rba0;
88*74a4d8c2SCharles.Forsyth ulong tbuf0_crc;
89*74a4d8c2SCharles.Forsyth ushort tbuf0_bcnt;
90*74a4d8c2SCharles.Forsyth ushort paddr[3]; /* physical address LSB to MSB increasing */
91*74a4d8c2SCharles.Forsyth ushort p_per; /* persistence */
92*74a4d8c2SCharles.Forsyth ushort rfbd_ptr; /* rx first bd pointer */
93*74a4d8c2SCharles.Forsyth ushort tfbd_ptr; /* tx first bd pointer */
94*74a4d8c2SCharles.Forsyth ushort tlbd_ptr; /* tx last bd pointer */
95*74a4d8c2SCharles.Forsyth ulong tbuf1_data0; /* save area 0 - next frame */
96*74a4d8c2SCharles.Forsyth ulong tbuf1_data1; /* save area 1 - next frame */
97*74a4d8c2SCharles.Forsyth ulong tbuf1_rba0;
98*74a4d8c2SCharles.Forsyth ulong tbuf1_crc;
99*74a4d8c2SCharles.Forsyth ushort tbuf1_bcnt;
100*74a4d8c2SCharles.Forsyth ushort tx_len; /* tx frame length counter */
101*74a4d8c2SCharles.Forsyth ushort iaddr[4]; /* individual address filter*/
102*74a4d8c2SCharles.Forsyth ushort boff_cnt; /* back-off counter */
103*74a4d8c2SCharles.Forsyth ushort taddr[3]; /* temp address */
104*74a4d8c2SCharles.Forsyth };
105*74a4d8c2SCharles.Forsyth
106*74a4d8c2SCharles.Forsyth typedef struct {
107*74a4d8c2SCharles.Forsyth SCC* scc;
108*74a4d8c2SCharles.Forsyth int port;
109*74a4d8c2SCharles.Forsyth int cpm;
110*74a4d8c2SCharles.Forsyth
111*74a4d8c2SCharles.Forsyth BD* rdr; /* receive descriptor ring */
112*74a4d8c2SCharles.Forsyth void* rrb; /* receive ring buffers */
113*74a4d8c2SCharles.Forsyth int rdrx; /* index into rdr */
114*74a4d8c2SCharles.Forsyth
115*74a4d8c2SCharles.Forsyth BD* tdr; /* transmit descriptor ring */
116*74a4d8c2SCharles.Forsyth void* trb; /* transmit ring buffers */
117*74a4d8c2SCharles.Forsyth int tdrx; /* index into tdr */
118*74a4d8c2SCharles.Forsyth } Mot;
119*74a4d8c2SCharles.Forsyth static Mot mot[MaxEther];
120*74a4d8c2SCharles.Forsyth
121*74a4d8c2SCharles.Forsyth static int sccid[] = {-1, SCC1ID, SCC2ID, SCC3ID, SCC4ID};
122*74a4d8c2SCharles.Forsyth static int sccparam[] = {-1, SCC1P, SCC2P, SCC3P, SCC4P};
123*74a4d8c2SCharles.Forsyth static int sccreg[] = {-1, 0xA00, 0xA20, 0xA40, 0xA60};
124*74a4d8c2SCharles.Forsyth static int sccirq[] = {-1, 0x1E, 0x1D, 0x1C, 0x1B};
125*74a4d8c2SCharles.Forsyth
126*74a4d8c2SCharles.Forsyth static void
attach(Ctlr * ctlr)127*74a4d8c2SCharles.Forsyth attach(Ctlr *ctlr)
128*74a4d8c2SCharles.Forsyth {
129*74a4d8c2SCharles.Forsyth mot[ctlr->ctlrno].scc->gsmrl |= ENR|ENT;
130*74a4d8c2SCharles.Forsyth eieio();
131*74a4d8c2SCharles.Forsyth }
132*74a4d8c2SCharles.Forsyth
133*74a4d8c2SCharles.Forsyth static void
transmit(Ctlr * ctlr)134*74a4d8c2SCharles.Forsyth transmit(Ctlr *ctlr)
135*74a4d8c2SCharles.Forsyth {
136*74a4d8c2SCharles.Forsyth int len;
137*74a4d8c2SCharles.Forsyth Mot *motp;
138*74a4d8c2SCharles.Forsyth Block *b;
139*74a4d8c2SCharles.Forsyth BD *tdre;
140*74a4d8c2SCharles.Forsyth
141*74a4d8c2SCharles.Forsyth motp = &mot[ctlr->ctlrno];
142*74a4d8c2SCharles.Forsyth while(((tdre = &motp->tdr[motp->tdrx])->status & BDReady) == 0){
143*74a4d8c2SCharles.Forsyth b = qget(ctlr->oq);
144*74a4d8c2SCharles.Forsyth if(b == 0)
145*74a4d8c2SCharles.Forsyth break;
146*74a4d8c2SCharles.Forsyth
147*74a4d8c2SCharles.Forsyth /*
148*74a4d8c2SCharles.Forsyth * Copy the packet to the transmit buffer.
149*74a4d8c2SCharles.Forsyth */
150*74a4d8c2SCharles.Forsyth len = BLEN(b);
151*74a4d8c2SCharles.Forsyth memmove(KADDR(tdre->addr), b->rp, len);
152*74a4d8c2SCharles.Forsyth
153*74a4d8c2SCharles.Forsyth /*
154*74a4d8c2SCharles.Forsyth * Give ownership of the descriptor to the chip, increment the
155*74a4d8c2SCharles.Forsyth * software ring descriptor pointer and tell the chip to poll.
156*74a4d8c2SCharles.Forsyth */
157*74a4d8c2SCharles.Forsyth tdre->length = len;
158*74a4d8c2SCharles.Forsyth eieio();
159*74a4d8c2SCharles.Forsyth tdre->status = (tdre->status & BDWrap) | BDReady|TxPad|BDInt|BDLast|TxTC;
160*74a4d8c2SCharles.Forsyth eieio();
161*74a4d8c2SCharles.Forsyth motp->scc->todr = 1<<15; /* transmit now */
162*74a4d8c2SCharles.Forsyth eieio();
163*74a4d8c2SCharles.Forsyth motp->tdrx = NEXT(motp->tdrx, Ntdre);
164*74a4d8c2SCharles.Forsyth
165*74a4d8c2SCharles.Forsyth freeb(b);
166*74a4d8c2SCharles.Forsyth
167*74a4d8c2SCharles.Forsyth }
168*74a4d8c2SCharles.Forsyth }
169*74a4d8c2SCharles.Forsyth
170*74a4d8c2SCharles.Forsyth static void
interrupt(Ureg *,void * ap)171*74a4d8c2SCharles.Forsyth interrupt(Ureg*, void *ap)
172*74a4d8c2SCharles.Forsyth {
173*74a4d8c2SCharles.Forsyth int len, events, status;
174*74a4d8c2SCharles.Forsyth Mot *motp;
175*74a4d8c2SCharles.Forsyth BD *rdre;
176*74a4d8c2SCharles.Forsyth Block *b;
177*74a4d8c2SCharles.Forsyth Ctlr *ctlr;
178*74a4d8c2SCharles.Forsyth
179*74a4d8c2SCharles.Forsyth ctlr = ap;
180*74a4d8c2SCharles.Forsyth motp = &mot[ctlr->ctlrno];
181*74a4d8c2SCharles.Forsyth
182*74a4d8c2SCharles.Forsyth /*
183*74a4d8c2SCharles.Forsyth * Acknowledge all interrupts and whine about those that shouldn't
184*74a4d8c2SCharles.Forsyth * happen.
185*74a4d8c2SCharles.Forsyth */
186*74a4d8c2SCharles.Forsyth events = motp->scc->scce;
187*74a4d8c2SCharles.Forsyth eieio();
188*74a4d8c2SCharles.Forsyth motp->scc->scce = events;
189*74a4d8c2SCharles.Forsyth eieio();
190*74a4d8c2SCharles.Forsyth if(events & (TXE|BSY|RXB))
191*74a4d8c2SCharles.Forsyth print("ETHER.SCC#%d: scce = 0x%uX\n", ctlr->ctlrno, events);
192*74a4d8c2SCharles.Forsyth //print(" %ux|", events);
193*74a4d8c2SCharles.Forsyth /*
194*74a4d8c2SCharles.Forsyth * Receiver interrupt: run round the descriptor ring logging
195*74a4d8c2SCharles.Forsyth * errors and passing valid receive data up to the higher levels
196*74a4d8c2SCharles.Forsyth * until we encounter a descriptor still owned by the chip.
197*74a4d8c2SCharles.Forsyth */
198*74a4d8c2SCharles.Forsyth if(events & (RXF|RXB) || 1){
199*74a4d8c2SCharles.Forsyth rdre = &motp->rdr[motp->rdrx];
200*74a4d8c2SCharles.Forsyth while(((status = rdre->status) & BDEmpty) == 0){
201*74a4d8c2SCharles.Forsyth if(status & RxError || (status & (BDFirst|BDLast)) != (BDFirst|BDLast)){
202*74a4d8c2SCharles.Forsyth //if(status & RxBuff)
203*74a4d8c2SCharles.Forsyth // ctlr->buffs++;
204*74a4d8c2SCharles.Forsyth if(status & (1<<2))
205*74a4d8c2SCharles.Forsyth ctlr->crcs++;
206*74a4d8c2SCharles.Forsyth if(status & (1<<1))
207*74a4d8c2SCharles.Forsyth ctlr->overflows++;
208*74a4d8c2SCharles.Forsyth //print("eth rx: %ux\n", status);
209*74a4d8c2SCharles.Forsyth if(status & RxError)
210*74a4d8c2SCharles.Forsyth print("~");
211*74a4d8c2SCharles.Forsyth else if((status & BDLast) == 0)
212*74a4d8c2SCharles.Forsyth print("@");
213*74a4d8c2SCharles.Forsyth }
214*74a4d8c2SCharles.Forsyth else{
215*74a4d8c2SCharles.Forsyth /*
216*74a4d8c2SCharles.Forsyth * We have a packet. Read it into the next
217*74a4d8c2SCharles.Forsyth * free ring buffer, if any.
218*74a4d8c2SCharles.Forsyth */
219*74a4d8c2SCharles.Forsyth len = rdre->length-4;
220*74a4d8c2SCharles.Forsyth if((b = iallocb(len)) != 0){
221*74a4d8c2SCharles.Forsyth memmove(b->wp, KADDR(rdre->addr), len);
222*74a4d8c2SCharles.Forsyth b->wp += len;
223*74a4d8c2SCharles.Forsyth etheriq(ctlr, b, 1);
224*74a4d8c2SCharles.Forsyth }
225*74a4d8c2SCharles.Forsyth }
226*74a4d8c2SCharles.Forsyth
227*74a4d8c2SCharles.Forsyth /*
228*74a4d8c2SCharles.Forsyth * Finished with this descriptor, reinitialise it,
229*74a4d8c2SCharles.Forsyth * give it back to the chip, then on to the next...
230*74a4d8c2SCharles.Forsyth */
231*74a4d8c2SCharles.Forsyth rdre->length = 0;
232*74a4d8c2SCharles.Forsyth rdre->status = (rdre->status & BDWrap) | BDEmpty | BDInt;
233*74a4d8c2SCharles.Forsyth eieio();
234*74a4d8c2SCharles.Forsyth
235*74a4d8c2SCharles.Forsyth motp->rdrx = NEXT(motp->rdrx, Nrdre);
236*74a4d8c2SCharles.Forsyth rdre = &motp->rdr[motp->rdrx];
237*74a4d8c2SCharles.Forsyth }
238*74a4d8c2SCharles.Forsyth }
239*74a4d8c2SCharles.Forsyth
240*74a4d8c2SCharles.Forsyth /*
241*74a4d8c2SCharles.Forsyth * Transmitter interrupt: handle anything queued for a free descriptor.
242*74a4d8c2SCharles.Forsyth */
243*74a4d8c2SCharles.Forsyth if(events & TXB)
244*74a4d8c2SCharles.Forsyth transmit(ctlr);
245*74a4d8c2SCharles.Forsyth if(events & TXE)
246*74a4d8c2SCharles.Forsyth cpmop(RestartTx, motp->cpm, 0);
247*74a4d8c2SCharles.Forsyth }
248*74a4d8c2SCharles.Forsyth
249*74a4d8c2SCharles.Forsyth static void
ringinit(Mot * motp)250*74a4d8c2SCharles.Forsyth ringinit(Mot* motp)
251*74a4d8c2SCharles.Forsyth {
252*74a4d8c2SCharles.Forsyth int i, x;
253*74a4d8c2SCharles.Forsyth
254*74a4d8c2SCharles.Forsyth /*
255*74a4d8c2SCharles.Forsyth * Initialise the receive and transmit buffer rings. The ring
256*74a4d8c2SCharles.Forsyth * entries must be aligned on 16-byte boundaries.
257*74a4d8c2SCharles.Forsyth */
258*74a4d8c2SCharles.Forsyth if(motp->rdr == 0)
259*74a4d8c2SCharles.Forsyth motp->rdr = bdalloc(Nrdre);
260*74a4d8c2SCharles.Forsyth if(motp->rrb == 0)
261*74a4d8c2SCharles.Forsyth motp->rrb = ialloc(Nrdre*Bufsize, 0);
262*74a4d8c2SCharles.Forsyth x = PADDR(motp->rrb);
263*74a4d8c2SCharles.Forsyth for(i = 0; i < Nrdre; i++){
264*74a4d8c2SCharles.Forsyth motp->rdr[i].length = 0;
265*74a4d8c2SCharles.Forsyth motp->rdr[i].addr = x;
266*74a4d8c2SCharles.Forsyth motp->rdr[i].status = BDEmpty|BDInt;
267*74a4d8c2SCharles.Forsyth x += Bufsize;
268*74a4d8c2SCharles.Forsyth }
269*74a4d8c2SCharles.Forsyth motp->rdr[i-1].status |= BDWrap;
270*74a4d8c2SCharles.Forsyth motp->rdrx = 0;
271*74a4d8c2SCharles.Forsyth
272*74a4d8c2SCharles.Forsyth if(motp->tdr == 0)
273*74a4d8c2SCharles.Forsyth motp->tdr = bdalloc(Ntdre);
274*74a4d8c2SCharles.Forsyth if(motp->trb == 0)
275*74a4d8c2SCharles.Forsyth motp->trb = ialloc(Ntdre*Bufsize, 0);
276*74a4d8c2SCharles.Forsyth x = PADDR(motp->trb);
277*74a4d8c2SCharles.Forsyth for(i = 0; i < Ntdre; i++){
278*74a4d8c2SCharles.Forsyth motp->tdr[i].addr = x;
279*74a4d8c2SCharles.Forsyth motp->tdr[i].length = 0;
280*74a4d8c2SCharles.Forsyth motp->tdr[i].status = TxPad|BDInt|BDLast|TxTC;
281*74a4d8c2SCharles.Forsyth x += Bufsize;
282*74a4d8c2SCharles.Forsyth }
283*74a4d8c2SCharles.Forsyth motp->tdr[i-1].status |= BDWrap;
284*74a4d8c2SCharles.Forsyth motp->tdrx = 0;
285*74a4d8c2SCharles.Forsyth }
286*74a4d8c2SCharles.Forsyth
287*74a4d8c2SCharles.Forsyth /*
288*74a4d8c2SCharles.Forsyth * This follows the MPC823 user guide: section16.9.23.7's initialisation sequence,
289*74a4d8c2SCharles.Forsyth * except that it sets the right bits for the MPC823ADS board when SCC2 is used,
290*74a4d8c2SCharles.Forsyth * and those for the 860/821 development board for SCC1.
291*74a4d8c2SCharles.Forsyth */
292*74a4d8c2SCharles.Forsyth static void
sccsetup(Mot * ctlr,SCC * scc,uchar * ea)293*74a4d8c2SCharles.Forsyth sccsetup(Mot *ctlr, SCC *scc, uchar *ea)
294*74a4d8c2SCharles.Forsyth {
295*74a4d8c2SCharles.Forsyth int i, rcs, tcs, w;
296*74a4d8c2SCharles.Forsyth Etherparam *p;
297*74a4d8c2SCharles.Forsyth IMM *io;
298*74a4d8c2SCharles.Forsyth
299*74a4d8c2SCharles.Forsyth
300*74a4d8c2SCharles.Forsyth i = 2*(ctlr->port-1);
301*74a4d8c2SCharles.Forsyth io = ioplock();
302*74a4d8c2SCharles.Forsyth w = (TXD1|RXD1)<<i; /* TXDn and RXDn in port A */
303*74a4d8c2SCharles.Forsyth io->papar |= w; /* enable TXDn and RXDn pins */
304*74a4d8c2SCharles.Forsyth io->padir &= ~w;
305*74a4d8c2SCharles.Forsyth io->paodr &= ~w; /* not open drain */
306*74a4d8c2SCharles.Forsyth
307*74a4d8c2SCharles.Forsyth w = (CD1|CTS1)<<i; /* CLSN and RENA: CDn and CTSn in port C */
308*74a4d8c2SCharles.Forsyth io->pcpar &= ~w; /* enable CLSN (CTSn) and RENA (CDn) */
309*74a4d8c2SCharles.Forsyth io->pcdir &= ~w;
310*74a4d8c2SCharles.Forsyth io->pcso |= w;
311*74a4d8c2SCharles.Forsyth iopunlock();
312*74a4d8c2SCharles.Forsyth
313*74a4d8c2SCharles.Forsyth /* clocks and transceiver control: details depend on the board's wiring */
314*74a4d8c2SCharles.Forsyth archetherenable(ctlr->cpm, &rcs, &tcs);
315*74a4d8c2SCharles.Forsyth
316*74a4d8c2SCharles.Forsyth sccnmsi(ctlr->port, rcs, tcs); /* connect the clocks */
317*74a4d8c2SCharles.Forsyth
318*74a4d8c2SCharles.Forsyth p = (Etherparam*)KADDR(sccparam[ctlr->port]);
319*74a4d8c2SCharles.Forsyth memset(p, 0, sizeof(*p));
320*74a4d8c2SCharles.Forsyth p->rfcr = 0x18;
321*74a4d8c2SCharles.Forsyth p->tfcr = 0x18;
322*74a4d8c2SCharles.Forsyth p->mrblr = Bufsize;
323*74a4d8c2SCharles.Forsyth p->rbase = PADDR(ctlr->rdr);
324*74a4d8c2SCharles.Forsyth p->tbase = PADDR(ctlr->tdr);
325*74a4d8c2SCharles.Forsyth
326*74a4d8c2SCharles.Forsyth cpmop(InitRxTx, ctlr->cpm, 0);
327*74a4d8c2SCharles.Forsyth
328*74a4d8c2SCharles.Forsyth p->c_pres = ~0;
329*74a4d8c2SCharles.Forsyth p->c_mask = 0xDEBB20E3;
330*74a4d8c2SCharles.Forsyth p->crcec = 0;
331*74a4d8c2SCharles.Forsyth p->alec = 0;
332*74a4d8c2SCharles.Forsyth p->disfc = 0;
333*74a4d8c2SCharles.Forsyth p->pads = 0x8888;
334*74a4d8c2SCharles.Forsyth p->ret_lim = 0xF;
335*74a4d8c2SCharles.Forsyth p->mflr = Rbsize;
336*74a4d8c2SCharles.Forsyth p->minflr = ETHERMINTU+4;
337*74a4d8c2SCharles.Forsyth p->maxd1 = Bufsize;
338*74a4d8c2SCharles.Forsyth p->maxd2 = Bufsize;
339*74a4d8c2SCharles.Forsyth p->p_per = 0; /* only moderate aggression */
340*74a4d8c2SCharles.Forsyth
341*74a4d8c2SCharles.Forsyth for(i=0; i<Eaddrlen; i+=2)
342*74a4d8c2SCharles.Forsyth p->paddr[2-i/2] = (ea[i+1]<<8)|ea[i]; /* it's not the obvious byte order */
343*74a4d8c2SCharles.Forsyth
344*74a4d8c2SCharles.Forsyth scc->psmr = (2<<10)|(5<<1); /* 32-bit CRC, ignore 22 bits before SFD */
345*74a4d8c2SCharles.Forsyth scc->dsr = 0xd555;
346*74a4d8c2SCharles.Forsyth scc->gsmrh = 0; /* normal operation */
347*74a4d8c2SCharles.Forsyth scc->gsmrl = (1<<28)|(4<<21)|(1<<19)|0xC; /* transmit clock invert, 48 bit preamble, repetitive 10 preamble, ethernet */
348*74a4d8c2SCharles.Forsyth eieio();
349*74a4d8c2SCharles.Forsyth scc->scce = ~0; /* clear all events */
350*74a4d8c2SCharles.Forsyth eieio();
351*74a4d8c2SCharles.Forsyth scc->sccm = TXE | RXF | TXB; /* enable interrupts */
352*74a4d8c2SCharles.Forsyth eieio();
353*74a4d8c2SCharles.Forsyth
354*74a4d8c2SCharles.Forsyth io = ioplock();
355*74a4d8c2SCharles.Forsyth w = RTS1<<(ctlr->port-1); /* enable TENA pin (RTSn) */
356*74a4d8c2SCharles.Forsyth io->pbpar |= w;
357*74a4d8c2SCharles.Forsyth io->pbdir |= w;
358*74a4d8c2SCharles.Forsyth iopunlock();
359*74a4d8c2SCharles.Forsyth
360*74a4d8c2SCharles.Forsyth /* gsmrl enable is deferred until attach */
361*74a4d8c2SCharles.Forsyth }
362*74a4d8c2SCharles.Forsyth
363*74a4d8c2SCharles.Forsyth /*
364*74a4d8c2SCharles.Forsyth * Prepare the SCCx ethernet for booting.
365*74a4d8c2SCharles.Forsyth */
366*74a4d8c2SCharles.Forsyth int
sccethreset(Ctlr * ctlr)367*74a4d8c2SCharles.Forsyth sccethreset(Ctlr* ctlr)
368*74a4d8c2SCharles.Forsyth {
369*74a4d8c2SCharles.Forsyth uchar ea[Eaddrlen];
370*74a4d8c2SCharles.Forsyth Mot *motp;
371*74a4d8c2SCharles.Forsyth SCC *scc;
372*74a4d8c2SCharles.Forsyth char line[50], def[50];
373*74a4d8c2SCharles.Forsyth
374*74a4d8c2SCharles.Forsyth /*
375*74a4d8c2SCharles.Forsyth * Since there's no EPROM, insist that the configuration entry
376*74a4d8c2SCharles.Forsyth * (see conf.c and flash.c) holds the Ethernet address.
377*74a4d8c2SCharles.Forsyth */
378*74a4d8c2SCharles.Forsyth memset(ea, 0, Eaddrlen);
379*74a4d8c2SCharles.Forsyth if(memcmp(ea, ctlr->card.ea, Eaddrlen) == 0){
380*74a4d8c2SCharles.Forsyth print("no preset Ether address\n");
381*74a4d8c2SCharles.Forsyth for(;;){
382*74a4d8c2SCharles.Forsyth strcpy(def, "00108bf12900"); /* valid MAC address to be used only for initial configuration */
383*74a4d8c2SCharles.Forsyth if(getstr("ether MAC address", line, sizeof(line), def) < 0)
384*74a4d8c2SCharles.Forsyth return -1;
385*74a4d8c2SCharles.Forsyth if(parseether(ctlr->card.ea, line) >= 0 || ctlr->card.ea[0] == 0xFF)
386*74a4d8c2SCharles.Forsyth break;
387*74a4d8c2SCharles.Forsyth print("invalid MAC address\n");
388*74a4d8c2SCharles.Forsyth }
389*74a4d8c2SCharles.Forsyth }
390*74a4d8c2SCharles.Forsyth
391*74a4d8c2SCharles.Forsyth scc = IOREGS(sccreg[ctlr->card.port], SCC);
392*74a4d8c2SCharles.Forsyth ctlr->card.irq = VectorCPIC+sccirq[ctlr->card.port];
393*74a4d8c2SCharles.Forsyth
394*74a4d8c2SCharles.Forsyth motp = &mot[ctlr->ctlrno];
395*74a4d8c2SCharles.Forsyth motp->scc = scc;
396*74a4d8c2SCharles.Forsyth motp->port = ctlr->card.port;
397*74a4d8c2SCharles.Forsyth motp->cpm = sccid[ctlr->card.port];
398*74a4d8c2SCharles.Forsyth
399*74a4d8c2SCharles.Forsyth ringinit(motp);
400*74a4d8c2SCharles.Forsyth
401*74a4d8c2SCharles.Forsyth sccsetup(motp, scc, ctlr->card.ea);
402*74a4d8c2SCharles.Forsyth
403*74a4d8c2SCharles.Forsyth /* enable is deferred until attach */
404*74a4d8c2SCharles.Forsyth
405*74a4d8c2SCharles.Forsyth ctlr->card.reset = sccethreset;
406*74a4d8c2SCharles.Forsyth ctlr->card.attach = attach;
407*74a4d8c2SCharles.Forsyth ctlr->card.transmit = transmit;
408*74a4d8c2SCharles.Forsyth ctlr->card.intr = interrupt;
409*74a4d8c2SCharles.Forsyth
410*74a4d8c2SCharles.Forsyth return 0;
411*74a4d8c2SCharles.Forsyth }
412