Annotation of sys/arch/mvme68k/dev/if_le.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_le.c,v 1.31 2006/01/11 07:21:58 miod Exp $ */
2:
3: /*-
4: * Copyright (c) 1982, 1992, 1993
5: * The Regents of the University of California. 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. Neither the name of the University nor the names of its contributors
16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: *
31: * @(#)if_le.c 8.2 (Berkeley) 10/30/93
32: */
33:
34: #include "bpfilter.h"
35:
36: #include <sys/param.h>
37: #include <sys/systm.h>
38: #include <sys/mbuf.h>
39: #include <sys/syslog.h>
40: #include <sys/socket.h>
41: #include <sys/device.h>
42: #include <sys/malloc.h>
43:
44: #include <net/if.h>
45:
46: #ifdef INET
47: #include <netinet/in.h>
48: #include <netinet/if_ether.h>
49: #endif
50:
51: #include <net/if_media.h>
52:
53: #include <machine/autoconf.h>
54: #include <machine/cpu.h>
55:
56: #include <dev/ic/am7990reg.h>
57: #include <dev/ic/am7990var.h>
58:
59: #include <mvme68k/dev/if_lereg.h>
60: #include <mvme68k/dev/if_levar.h>
61: #include <mvme68k/dev/vme.h>
62:
63: #include "pcc.h"
64: #if NPCC > 0
65: #include <mvme68k/dev/pccreg.h>
66: #endif
67:
68: /* autoconfiguration driver */
69: void leattach(struct device *, struct device *, void *);
70: int lematch(struct device *, void *, void *);
71:
72: struct cfattach le_ca = {
73: sizeof(struct le_softc), lematch, leattach
74: };
75:
76: static int lebustype;
77:
78: void lewrcsr(struct am7990_softc *, u_int16_t, u_int16_t);
79: u_int16_t lerdcsr(struct am7990_softc *, u_int16_t);
80: void vlewrcsr(struct am7990_softc *, u_int16_t, u_int16_t);
81: u_int16_t vlerdcsr(struct am7990_softc *, u_int16_t);
82: void nvram_cmd(struct am7990_softc *, u_char, u_short);
83: u_int16_t nvram_read(struct am7990_softc *, u_char);
84: void vleetheraddr(struct am7990_softc *);
85: void vleinit(struct am7990_softc *);
86: void vlereset(struct am7990_softc *);
87: int vle_intr(void *);
88: void vle_copytobuf_contig(struct am7990_softc *, void *, int, int);
89: void vle_zerobuf_contig(struct am7990_softc *, int, int);
90:
91: /* send command to the nvram controller */
92: void
93: nvram_cmd(sc, cmd, addr)
94: struct am7990_softc *sc;
95: u_char cmd;
96: u_short addr;
97: {
98: int i;
99: struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
100:
101: for (i=0;i<8;i++) {
102: reg1->ler1_ear=((cmd|(addr<<1))>>i);
103: CDELAY;
104: }
105: }
106:
107: /* read nvram one bit at a time */
108: u_int16_t
109: nvram_read(sc, nvram_addr)
110: struct am7990_softc *sc;
111: u_char nvram_addr;
112: {
113: u_short val = 0, mask = 0x04000;
114: u_int16_t wbit;
115: /* these used by macros DO NOT CHANGE!*/
116: struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
117: ((struct le_softc *)sc)->csr = 0x4f;
118: ENABLE_NVRAM;
119: nvram_cmd(sc, NVRAM_RCL, 0);
120: DISABLE_NVRAM;
121: CDELAY;
122: ENABLE_NVRAM;
123: nvram_cmd(sc, NVRAM_READ, nvram_addr);
124: for (wbit=0; wbit<15; wbit++) {
125: (reg1->ler1_ear & 0x01) ? (val = (val | mask)) : (val = (val & (~mask)));
126: mask = mask>>1;
127: CDELAY;
128: }
129: (reg1->ler1_ear & 0x01) ? (val = (val | 0x8000)) : (val = (val & 0x7FFF));
130: CDELAY;
131: DISABLE_NVRAM;
132: return (val);
133: }
134:
135: void
136: vleetheraddr(sc)
137: struct am7990_softc *sc;
138: {
139: u_char * cp = sc->sc_arpcom.ac_enaddr;
140: u_int16_t ival[3];
141: u_char i;
142:
143: for (i=0; i<3; i++) {
144: ival[i] = nvram_read(sc, i);
145: }
146: memcpy(cp, &ival[0], 6);
147: }
148:
149: void
150: lewrcsr(sc, port, val)
151: struct am7990_softc *sc;
152: u_int16_t port, val;
153: {
154: register struct lereg1 *ler1 = (struct lereg1 *)((struct le_softc *)sc)->sc_r1;
155:
156: ler1->ler1_rap = port;
157: ler1->ler1_rdp = val;
158: }
159:
160: void
161: vlewrcsr(sc, port, val)
162: struct am7990_softc *sc;
163: u_int16_t port, val;
164: {
165: register struct vlereg1 *ler1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
166:
167: ler1->ler1_rap = port;
168: ler1->ler1_rdp = val;
169: }
170:
171: u_int16_t
172: lerdcsr(sc, port)
173: struct am7990_softc *sc;
174: u_int16_t port;
175: {
176: register struct lereg1 *ler1 = (struct lereg1 *)((struct le_softc *)sc)->sc_r1;
177: u_int16_t val;
178:
179: ler1->ler1_rap = port;
180: val = ler1->ler1_rdp;
181: return (val);
182: }
183:
184: u_int16_t
185: vlerdcsr(sc, port)
186: struct am7990_softc *sc;
187: u_int16_t port;
188: {
189: register struct vlereg1 *ler1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
190: u_int16_t val;
191:
192: ler1->ler1_rap = port;
193: val = ler1->ler1_rdp;
194: return (val);
195: }
196:
197: /* init MVME376, set ipl and vec */
198: void
199: vleinit(sc)
200: struct am7990_softc *sc;
201: {
202: register struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
203: u_char vec = ((struct le_softc *)sc)->sc_vec;
204: u_char ipl = ((struct le_softc *)sc)->sc_ipl;
205: ((struct le_softc *)sc)->csr = 0x4f;
206: WRITE_CSR_AND( ~ipl );
207: SET_VEC(vec);
208: return;
209: }
210:
211: /* MVME376 hardware reset */
212: void
213: vlereset(sc)
214: struct am7990_softc *sc;
215: {
216: register struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
217: RESET_HW;
218: #ifdef LEDEBUG
219: if (sc->sc_debug) {
220: printf("\nle: hardware reset\n");
221: }
222: #endif
223: SYSFAIL_CL;
224: return;
225: }
226:
227: int
228: vle_intr(sc)
229: void *sc;
230: {
231: register struct vlereg1 *reg1 = (struct vlereg1 *)((struct le_softc *)sc)->sc_r1;
232: int rc;
233: rc = am7990_intr(sc);
234: ENABLE_INTR;
235: return (rc);
236: }
237:
238: void
239: vle_copytobuf_contig(sc, from, boff, len)
240: struct am7990_softc *sc;
241: void *from;
242: int boff, len;
243: {
244: volatile caddr_t buf = sc->sc_mem;
245:
246: /*
247: * Do the cache stuff
248: */
249: dma_cachectl(buf + boff, len);
250: /*
251: * Just call bcopy() to do the work.
252: */
253: bcopy(from, buf + boff, len);
254: }
255:
256: void
257: vle_zerobuf_contig(sc, boff, len)
258: struct am7990_softc *sc;
259: int boff, len;
260: {
261: volatile caddr_t buf = sc->sc_mem;
262: /*
263: * Do the cache stuff
264: */
265: dma_cachectl(buf + boff, len);
266: /*
267: * Just let bzero() do the work
268: */
269: bzero(buf + boff, len);
270: }
271:
272: int
273: lematch(parent, vcf, args)
274: struct device *parent;
275: void *vcf, *args;
276: {
277: struct confargs *ca = args;
278: /* check physical addr for bogus MVME162 addr @0xffffd200. weird XXX - smurph */
279: if (cputyp == CPU_162 && ca->ca_paddr == 0xffffd200)
280: return (0);
281:
282: return (!badvaddr((vaddr_t)ca->ca_vaddr, 2));
283: }
284:
285: /*
286: * Interface exists: make available by filling in network interface
287: * record. System will initialize the interface when it is ready
288: * to accept packets.
289: */
290: void
291: leattach(parent, self, aux)
292: struct device *parent;
293: struct device *self;
294: void *aux;
295: {
296: register struct le_softc *lesc = (struct le_softc *)self;
297: struct am7990_softc *sc = &lesc->sc_am7990;
298: struct confargs *ca = aux;
299: int pri = ca->ca_ipl;
300: extern void *etherbuf;
301: paddr_t addr;
302: int card;
303:
304: /* XXX the following declarations should be elsewhere */
305: extern void myetheraddr(u_char *);
306:
307: lebustype = ca->ca_bustype;
308:
309: switch (lebustype) {
310: case BUS_VMES:
311: /*
312: * get the first available etherbuf. MVME376 uses its own
313: * dual-ported RAM for etherbuf. It is set by dip switches
314: * on board. We support the six Motorola address locations,
315: * however, the board can be set up at any other address.
316: * XXX These physical addresses should be mapped in extio!!!
317: */
318: switch (ca->ca_paddr) {
319: case 0xffff1200:
320: card = 0;
321: break;
322: case 0xffff1400:
323: card = 1;
324: break;
325: case 0xffff1600:
326: card = 2;
327: break;
328: case 0xffff5400:
329: card = 3;
330: break;
331: case 0xffff5600:
332: card = 4;
333: break;
334: case 0xffffa400:
335: card = 5;
336: break;
337: default:
338: printf(": unsupported address\n");
339: return;
340: }
341:
342: addr = VLEMEMBASE - (card * VLEMEMSIZE);
343:
344: sc->sc_mem = (void *)mapiodev(addr, VLEMEMSIZE);
345: if (sc->sc_mem == NULL) {
346: printf("\n%s: no more memory in external I/O map\n",
347: sc->sc_dev.dv_xname);
348: return;
349: }
350: sc->sc_addr = addr & 0x00ffffff;
351:
352: lesc->sc_r1 = (void *)ca->ca_vaddr;
353: lesc->sc_ipl = ca->ca_ipl;
354: lesc->sc_vec = ca->ca_vec;
355: sc->sc_memsize = VLEMEMSIZE;
356: sc->sc_conf3 = LE_C3_BSWP;
357: sc->sc_hwreset = vlereset;
358: sc->sc_rdcsr = vlerdcsr;
359: sc->sc_wrcsr = vlewrcsr;
360: sc->sc_hwinit = vleinit;
361: sc->sc_copytodesc = vle_copytobuf_contig;
362: sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
363: sc->sc_copytobuf = vle_copytobuf_contig;
364: sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
365: sc->sc_zerobuf = am7990_zerobuf_contig;
366: /* get ether address */
367: vleetheraddr(sc);
368: break;
369: case BUS_PCC:
370: sc->sc_mem = etherbuf;
371: lesc->sc_r1 = (void *)ca->ca_vaddr;
372: sc->sc_conf3 = LE_C3_BSWP /*| LE_C3_ACON | LE_C3_BCON*/;
373: sc->sc_addr = kvtop((vaddr_t)sc->sc_mem);
374: sc->sc_memsize = LEMEMSIZE;
375: sc->sc_rdcsr = lerdcsr;
376: sc->sc_wrcsr = lewrcsr;
377: sc->sc_hwreset = NULL;
378: sc->sc_hwinit = NULL;
379: sc->sc_copytodesc = am7990_copytobuf_contig;
380: sc->sc_copyfromdesc = am7990_copyfrombuf_contig;
381: sc->sc_copytobuf = am7990_copytobuf_contig;
382: sc->sc_copyfrombuf = am7990_copyfrombuf_contig;
383: sc->sc_zerobuf = am7990_zerobuf_contig;
384: /* get ether address */
385: myetheraddr(sc->sc_arpcom.ac_enaddr);
386: break;
387: default:
388: printf(": unknown bus type\n");
389: return;
390: }
391:
392: am7990_config(sc);
393:
394: /* connect the interrupt */
395: switch (lebustype) {
396: case BUS_VMES:
397: lesc->sc_ih.ih_fn = vle_intr;
398: lesc->sc_ih.ih_arg = sc;
399: lesc->sc_ih.ih_ipl = pri;
400: vmeintr_establish(ca->ca_vec + 0, &lesc->sc_ih, self->dv_xname);
401: break;
402: #if NPCC > 0
403: case BUS_PCC:
404: lesc->sc_ih.ih_fn = am7990_intr;
405: lesc->sc_ih.ih_arg = sc;
406: lesc->sc_ih.ih_ipl = pri;
407: pccintr_establish(PCCV_LE, &lesc->sc_ih, self->dv_xname);
408: sys_pcc->pcc_leirq = pri | PCC_IRQ_IEN;
409: break;
410: #endif
411: }
412: }
CVSweb