Annotation of sys/arch/vax/boot/boot/if_le.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_le.c,v 1.3 2003/11/07 10:16:45 jmc Exp $ */
2: /* $NetBSD: if_le.c,v 1.6 2000/05/20 13:30:03 ragge Exp $ */
3: /*
4: * Copyright (c) 1997, 1999 Ludd, University of Lule}, Sweden.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed at Ludd, University of
18: * Lule}, Sweden and its contributors.
19: * 4. The name of the author may not be used to endorse or promote products
20: * derived from this software without specific prior written permission
21: *
22: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32: */
33:
34: /*
35: * Standalone routine for MicroVAX LANCE chip.
36: */
37:
38: #include <sys/param.h>
39: #include <sys/types.h>
40: #include <sys/queue.h>
41: #include <sys/socket.h>
42:
43: #include <net/if.h>
44:
45: #include <netinet/in.h>
46: #include <netinet/in_systm.h>
47: #include <netinet/if_ether.h>
48:
49: #include <../include/sid.h>
50: #include <../include/rpb.h>
51:
52: #include <lib/libsa/netif.h>
53: #include <lib/libsa/stand.h>
54:
55: #include <dev/ic/am7990reg.h>
56:
57: #include "vaxstand.h"
58:
59: /*
60: * Buffer sizes.
61: */
62: #define TLEN 1
63: #define NTBUF (1 << TLEN)
64: #define RLEN 3
65: #define NRBUF (1 << RLEN)
66: #define BUFSIZE 1518
67:
68: #define ETHER_MIN_LEN 64 /* minimum frame length, including CRC */
69:
70: #define QW_ALLOC(x) (((int)alloc((x) + 7) + 7) & ~7)
71:
72: static int le_get(struct iodesc *, void *, size_t, time_t);
73: static int le_put(struct iodesc *, void *, size_t);
74: static void copyout(void *from, int dest, int len);
75: static void copyin(int src, void *to, int len);
76:
77: struct netif_driver le_driver = {
78: 0, 0, 0, 0, le_get, le_put,
79: };
80:
81: /*
82: * Init block & buffer descriptors according to DEC system
83: * specification documentation.
84: */
85: struct initblock {
86: short ib_mode;
87: char ib_padr[6]; /* Ethernet address */
88: int ib_ladrf1;
89: int ib_ladrf2;
90: int ib_rdr; /* Receive address */
91: int ib_tdr; /* Transmit address */
92: } *initblock = NULL;
93:
94: struct nireg {
95: volatile u_short ni_rdp; /* data port */
96: volatile short ni_pad0;
97: volatile short ni_rap; /* register select port */
98: } *nireg;
99:
100:
101: volatile struct buffdesc {
102: int bd_adrflg;
103: short bd_bcnt;
104: short bd_mcnt;
105: } *rdesc, *tdesc;
106:
107: static int addoff, kopiera = 0;
108:
109: /* Flags in the address field */
110: #define BR_OWN 0x80000000
111: #define BR_ERR 0x40000000
112: #define BR_FRAM 0x20000000
113: #define BR_OFLO 0x10000000
114: #define BR_CRC 0x08000000
115: #define BR_BUFF 0x04000000
116: #define BR_STP 0x02000000
117: #define BR_ENP 0x01000000
118:
119: #define BT_OWN 0x80000000
120: #define BT_ERR 0x40000000
121: #define BT_MORE 0x10000000
122: #define BT_ONE 0x08000000
123: #define BT_DEF 0x04000000
124: #define BT_STP 0x02000000
125: #define BT_ENP 0x01000000
126:
127: int next_rdesc, next_tdesc;
128:
129: #define LEWRCSR(port, val) { \
130: nireg->ni_rap = (port); \
131: nireg->ni_rdp = (val); \
132: }
133:
134: #define LERDCSR(port) \
135: (nireg->ni_rap = port, nireg->ni_rdp)
136:
137: int
138: leopen(struct open_file *f, int adapt, int ctlr, int unit, int part)
139: {
140: int i, *ea;
141: volatile int to = 100000;
142: u_char eaddr[6];
143:
144: next_rdesc = next_tdesc = 0;
145:
146: if (vax_boardtype == VAX_BTYP_650 &&
147: ((vax_siedata >> 8) & 0xff) == VAX_SIE_KA640) {
148: kopiera = 1;
149: ea = (void *)0x20084200;
150: nireg = (void *)0x20084400;
151: } else {
152: *(int *)0x20080014 = 0; /* Be sure we do DMA in low 16MB */
153: ea = (void *)0x20090000; /* XXX Ethernet address */
154: nireg = (void *)0x200e0000;
155: }
156: if (askname == 0) /* Override if autoboot */
157: nireg = (void *)bootrpb.csrphy;
158: else /* Tell kernel from where we booted */
159: bootrpb.csrphy = (int)nireg;
160:
161: if (vax_boardtype == VAX_BTYP_43)
162: addoff = 0x28000000;
163: else
164: addoff = 0;
165: igen:
166: LEWRCSR(LE_CSR0, LE_C0_STOP);
167: while (to--)
168: ;
169:
170: for (i = 0; i < 6; i++)
171: eaddr[i] = ea[i] & 0377;
172:
173: if (initblock == NULL) {
174: (void *)initblock =
175: (char *)QW_ALLOC(sizeof(struct initblock)) + addoff;
176: initblock->ib_mode = LE_MODE_NORMAL;
177: bcopy(eaddr, initblock->ib_padr, 6);
178: initblock->ib_ladrf1 = 0;
179: initblock->ib_ladrf2 = 0;
180:
181: (int)rdesc = QW_ALLOC(sizeof(struct buffdesc) * NRBUF) + addoff;
182: initblock->ib_rdr = (RLEN << 29) | (int)rdesc;
183: if (kopiera)
184: initblock->ib_rdr -= (int)initblock;
185: (int)tdesc = QW_ALLOC(sizeof(struct buffdesc) * NTBUF) + addoff;
186: initblock->ib_tdr = (TLEN << 29) | (int)tdesc;
187: if (kopiera)
188: initblock->ib_tdr -= (int)initblock;
189: if (kopiera)
190: copyout(initblock, 0, sizeof(struct initblock));
191:
192: for (i = 0; i < NRBUF; i++) {
193: rdesc[i].bd_adrflg = QW_ALLOC(BUFSIZE) | BR_OWN;
194: if (kopiera)
195: rdesc[i].bd_adrflg -= (int)initblock;
196: rdesc[i].bd_bcnt = -BUFSIZE;
197: rdesc[i].bd_mcnt = 0;
198: }
199: if (kopiera)
200: copyout((void *)rdesc, (int)rdesc - (int)initblock,
201: sizeof(struct buffdesc) * NRBUF);
202:
203: for (i = 0; i < NTBUF; i++) {
204: tdesc[i].bd_adrflg = QW_ALLOC(BUFSIZE);
205: if (kopiera)
206: tdesc[i].bd_adrflg -= (int)initblock;
207: tdesc[i].bd_bcnt = 0xf000;
208: tdesc[i].bd_mcnt = 0;
209: }
210: if (kopiera)
211: copyout((void *)tdesc, (int)tdesc - (int)initblock,
212: sizeof(struct buffdesc) * NTBUF);
213: }
214:
215: if (kopiera) {
216: LEWRCSR(LE_CSR1, 0);
217: LEWRCSR(LE_CSR2, 0);
218: } else {
219: LEWRCSR(LE_CSR1, (int)initblock & 0xffff);
220: LEWRCSR(LE_CSR2, ((int)initblock >> 16) & 0xff);
221: }
222:
223: LEWRCSR(LE_CSR0, LE_C0_INIT);
224:
225: to = 100000;
226: while (to--) {
227: if (LERDCSR(LE_CSR0) & LE_C0_IDON)
228: break;
229: if (LERDCSR(LE_CSR0) & LE_C0_ERR) {
230: printf("lance init error: csr0 %x\n", LERDCSR(LE_CSR0));
231: goto igen;
232: }
233: }
234:
235: LEWRCSR(LE_CSR0, LE_C0_INEA | LE_C0_STRT | LE_C0_IDON);
236:
237: net_devinit(f, &le_driver, eaddr);
238: return 0;
239: }
240:
241: int
242: le_get(struct iodesc *desc, void *pkt, size_t maxlen, time_t timeout)
243: {
244: int csr, len;
245: volatile int to = 100000 * timeout;
246:
247: retry:
248: if (to-- == 0)
249: return 0;
250:
251: csr = LERDCSR(LE_CSR0);
252: LEWRCSR(LE_CSR0, csr & (LE_C0_BABL|LE_C0_MISS|LE_C0_MERR|LE_C0_RINT));
253:
254: if (kopiera)
255: copyin((int)&rdesc[next_rdesc] - (int)initblock,
256: (void *)&rdesc[next_rdesc], sizeof(struct buffdesc));
257: if (rdesc[next_rdesc].bd_adrflg & BR_OWN)
258: goto retry;
259:
260: if (rdesc[next_rdesc].bd_adrflg & BR_ERR)
261: len = 0;
262: else {
263: if ((len = rdesc[next_rdesc].bd_mcnt - 4) > maxlen)
264: len = maxlen;
265:
266: if (kopiera)
267: copyin((rdesc[next_rdesc].bd_adrflg&0xffffff),
268: pkt, len);
269: else
270: bcopy((char *)(rdesc[next_rdesc].bd_adrflg&0xffffff) +
271: addoff, pkt, len);
272: }
273:
274: rdesc[next_rdesc].bd_mcnt = 0;
275: rdesc[next_rdesc].bd_adrflg |= BR_OWN;
276: if (kopiera)
277: copyout((void *)&rdesc[next_rdesc], (int)&rdesc[next_rdesc] -
278: (int)initblock, sizeof(struct buffdesc));
279: if (++next_rdesc >= NRBUF)
280: next_rdesc = 0;
281:
282:
283: if (len == 0)
284: goto retry;
285: return len;
286: }
287:
288: int
289: le_put(struct iodesc *desc, void *pkt, size_t len)
290: {
291: volatile int to = 100000;
292: int csr;
293:
294: retry:
295: if (--to == 0)
296: return -1;
297:
298: csr = LERDCSR(LE_CSR0);
299: LEWRCSR(LE_CSR0, csr & (LE_C0_MISS|LE_C0_CERR|LE_C0_TINT));
300:
301: if (kopiera)
302: copyin((int)&tdesc[next_tdesc] - (int)initblock,
303: (void *)&tdesc[next_tdesc], sizeof(struct buffdesc));
304: if (tdesc[next_tdesc].bd_adrflg & BT_OWN)
305: goto retry;
306:
307: if (kopiera)
308: copyout(pkt, (tdesc[next_tdesc].bd_adrflg & 0xffffff), len);
309: else
310: bcopy(pkt, (char *)(tdesc[next_tdesc].bd_adrflg & 0xffffff) +
311: addoff, len);
312: tdesc[next_tdesc].bd_bcnt =
313: (len < ETHER_MIN_LEN ? -ETHER_MIN_LEN : -len);
314: tdesc[next_tdesc].bd_mcnt = 0;
315: tdesc[next_tdesc].bd_adrflg |= BT_OWN | BT_STP | BT_ENP;
316: if (kopiera)
317: copyout((void *)&tdesc[next_tdesc], (int)&tdesc[next_tdesc] -
318: (int)initblock, sizeof(struct buffdesc));
319:
320: LEWRCSR(LE_CSR0, LE_C0_TDMD);
321:
322: to = 100000;
323: while (((LERDCSR(LE_CSR0) & LE_C0_TINT) == 0) && --to)
324: ;
325:
326: LEWRCSR(LE_CSR0, LE_C0_TINT);
327: if (++next_tdesc >= NTBUF)
328: next_tdesc = 0;
329:
330: if (to)
331: return len;
332:
333: return -1;
334: }
335:
336: int
337: leclose(struct open_file *f)
338: {
339: LEWRCSR(LE_CSR0, LE_C0_STOP);
340:
341: return 0;
342: }
343:
344: void
345: copyout(void *f, int dest, int len)
346: {
347: short *from = f;
348: short *toaddr;
349:
350: toaddr = (short *)0x20120000 + dest;
351:
352: while (len > 0) {
353: *toaddr = *from++;
354: toaddr += 2;
355: len -= 2;
356: }
357: }
358:
359: void
360: copyin(int src, void *f, int len)
361: {
362: short *to = f;
363: short *fromaddr;
364:
365: fromaddr = (short *)0x20120000 + src;
366:
367: while (len > 0) {
368: *to++ = *fromaddr;
369: fromaddr += 2;
370: len -= 2;
371: }
372: }
CVSweb