Annotation of sys/arch/hppa/gsc/if_ie_gsc.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: if_ie_gsc.c,v 1.25 2004/10/28 19:13:30 mickey Exp $ */
2:
3: /*
4: * Copyright (c) 1998-2004 Michael Shalayeff
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: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19: * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22: * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25: * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26: * THE POSSIBILITY OF SUCH DAMAGE.
27: */
28:
29: /*
30: * References:
31: * 1. 82596DX and 82596SX High-Performance 32-bit Local Area Network Coprocessor
32: * Intel Corporation, November 1996, Order Number: 290219-006
33: *
34: * 2. 712 I/O Subsystem ERS Rev 1.0
35: * Hewlett-Packard, June 17 1992, Dwg No. A-A2263-66510-31
36: */
37: #include <sys/param.h>
38: #include <sys/systm.h>
39: #include <sys/device.h>
40: #include <sys/socket.h>
41: #include <sys/sockio.h>
42:
43: #include <net/if.h>
44: #include <net/if_dl.h>
45: #include <net/if_types.h>
46: #include <net/if_media.h>
47:
48: #include <netinet/in.h>
49: #include <netinet/if_ether.h>
50:
51: #include <machine/bus.h>
52: #include <machine/intr.h>
53: #include <machine/iomod.h>
54: #include <machine/autoconf.h>
55:
56: #include <hppa/dev/cpudevs.h>
57: #include <hppa/gsc/gscbusvar.h>
58:
59: #include <dev/ic/i82596reg.h>
60: #include <dev/ic/i82596var.h>
61:
62: #define IEGSC_GECKO IEMD_FLAG0
63:
64: struct ie_gsc_regs {
65: u_int32_t ie_reset;
66: u_int32_t ie_port;
67: u_int32_t ie_attn;
68: };
69:
70: #define IE_SIZE 0x8000
71:
72: int ie_gsc_probe(struct device *, void *, void *);
73: void ie_gsc_attach(struct device *, struct device *, void *);
74:
75: struct cfattach ie_gsc_ca = {
76: sizeof(struct ie_softc), ie_gsc_probe, ie_gsc_attach
77: };
78:
79: static int ie_gsc_media[] = {
80: IFM_ETHER | IFM_10_2,
81: };
82: #define IE_NMEDIA (sizeof(ie_gsc_media) / sizeof(ie_gsc_media[0]))
83:
84: char *ie_mem;
85:
86: void ie_gsc_reset(struct ie_softc *sc, int what);
87: void ie_gsc_attend(struct ie_softc *sc);
88: void ie_gsc_run(struct ie_softc *sc);
89: void ie_gsc_port(struct ie_softc *sc, u_int);
90: #ifdef USELEDS
91: int ie_gsc_intrhook(struct ie_softc *sc, int what);
92: #endif
93: u_int16_t ie_gsc_read16(struct ie_softc *sc, int offset);
94: void ie_gsc_write16(struct ie_softc *sc, int offset, u_int16_t v);
95: void ie_gsc_write24(struct ie_softc *sc, int offset, int addr);
96: void ie_gsc_memcopyin(struct ie_softc *sc, void *p, int offset, size_t);
97: void ie_gsc_memcopyout(struct ie_softc *sc, const void *p, int, size_t);
98:
99:
100: void
101: ie_gsc_reset(sc, what)
102: struct ie_softc *sc;
103: int what;
104: {
105: volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
106: int i;
107:
108: r->ie_reset = 0;
109: /*
110: * per [2] 4.6.2.1
111: * delay for 10 system clocks + 5 transmit clocks,
112: * NB: works for system clocks over 10MHz
113: */
114: DELAY(1000);
115:
116: switch (what) {
117: case IE_CHIP_PROBE:
118: break;
119:
120: case IE_CARD_RESET:
121: /*
122: * after the hardware reset:
123: * inform i825[89]6 about new SCP address,
124: * maddr must be at least 16-byte aligned
125: */
126: ie_gsc_port(sc, IE_PORT_SCP);
127: ie_gsc_attend(sc);
128:
129: for (i = 9000; i-- && ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp));
130: DELAY(100))
131: pdcache(0, sc->sc_maddr + sc->iscp, IE_ISCP_SZ);
132:
133: #ifdef I82596_DEBUG
134: if (i < 0) {
135: printf("timeout for PORT command (%x)%s\n",
136: ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp)),
137: (sc->sc_flags & IEGSC_GECKO)? " on gecko":"");
138: return;
139: }
140: #endif
141: break;
142: }
143: }
144:
145: void
146: ie_gsc_attend(sc)
147: struct ie_softc *sc;
148: {
149: volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
150:
151: fdcache(0, (vaddr_t)ie_mem, IE_SIZE);
152: DELAY(1);
153: r->ie_attn = 0;
154: DELAY(1);
155: }
156:
157: void
158: ie_gsc_run(sc)
159: struct ie_softc *sc;
160: {
161: }
162:
163: void
164: ie_gsc_port(sc, cmd)
165: struct ie_softc *sc;
166: u_int cmd;
167: {
168: switch (cmd) {
169: case IE_PORT_RESET:
170: cmd = 0;
171: break;
172: case IE_PORT_TEST:
173: cmd = ((u_int)sc->sc_maddr + sc->scp) | 1;
174: break;
175: case IE_PORT_SCP:
176: cmd = ((u_int)sc->sc_maddr + sc->scp) | 2;
177: break;
178: case IE_PORT_DUMP:
179: cmd = 3;
180: break;
181: }
182:
183: if (sc->sc_flags & IEGSC_GECKO) {
184: volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
185: r->ie_port = cmd & 0xffff;
186: DELAY(1000);
187: r->ie_port = cmd >> 16;
188: DELAY(1000);
189: } else {
190: volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
191: r->ie_port = cmd >> 16;
192: DELAY(1000);
193: r->ie_port = cmd & 0xffff;
194: DELAY(1000);
195: }
196: }
197:
198: #ifdef USELEDS
199: int
200: ie_gsc_intrhook(sc, where)
201: struct ie_softc *sc;
202: int where;
203: {
204: switch (where) {
205: case IE_INTR_ENRCV:
206: ledctl(PALED_NETRCV, 0, 0);
207: break;
208: case IE_INTR_ENSND:
209: ledctl(PALED_NETSND, 0, 0);
210: break;
211: case IE_INTR_EXIT:
212: case IE_INTR_LOOP:
213: fdcache(0, (vaddr_t)ie_mem, IE_SIZE);
214: break;
215: }
216: return 0;
217: }
218: #endif
219:
220: u_int16_t
221: ie_gsc_read16(sc, offset)
222: struct ie_softc *sc;
223: int offset;
224: {
225: volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
226:
227: asm __volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr));
228: return *addr;
229: }
230:
231: void
232: ie_gsc_write16(sc, offset, v)
233: struct ie_softc *sc;
234: int offset;
235: u_int16_t v;
236: {
237: volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
238:
239: *addr = v;
240: asm __volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr));
241: }
242:
243: void
244: ie_gsc_write24(sc, offset, v)
245: struct ie_softc *sc;
246: int offset;
247: int v;
248: {
249: volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
250:
251: addr[0] = (v ) & 0xffff;
252: addr[1] = (v >> 16) & 0xffff;
253: asm __volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr+0));
254: asm __volatile ("fdc %%r0(%%sr0, %0)" :: "r" (addr+1));
255: }
256:
257: void
258: ie_gsc_memcopyin(sc, p, offset, size)
259: struct ie_softc *sc;
260: void *p;
261: int offset;
262: size_t size;
263: {
264: pdcache(0, sc->bh + offset, size);
265: bcopy ((void *)((u_long)sc->bh + offset), p, size);
266: }
267:
268: void
269: ie_gsc_memcopyout(sc, p, offset, size)
270: struct ie_softc *sc;
271: const void *p;
272: int offset;
273: size_t size;
274: {
275: bcopy (p, (void *)((u_long)sc->bh + offset), size);
276: fdcache(0, sc->bh + offset, size);
277: }
278:
279: int
280: ie_gsc_probe(parent, match, aux)
281: struct device *parent;
282: void *match, *aux;
283: {
284: struct gsc_attach_args *ga = aux;
285:
286: if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
287: (ga->ga_type.iodc_sv_model != HPPA_FIO_LAN &&
288: ga->ga_type.iodc_sv_model != HPPA_FIO_GLAN))
289: return 0;
290:
291: return 1;
292: }
293:
294: void
295: ie_gsc_attach(parent, self, aux)
296: struct device *parent, *self;
297: void *aux;
298: {
299: struct pdc_lan_station_id pdc_mac PDC_ALIGNMENT;
300: struct ie_softc *sc = (struct ie_softc *)self;
301: struct gsc_attach_args *ga = aux;
302: /*bus_dma_segment_t seg;
303: int rseg;*/
304: int rv;
305: #ifdef PMAPDEBUG
306: extern int pmapdebug;
307: int opmapdebug = pmapdebug;
308: pmapdebug = 0;
309: #endif
310:
311: sc->iot = sc->bt = ga->ga_iot;
312: if (bus_space_map(sc->iot, ga->ga_hpa, IOMOD_HPASIZE, 0, &sc->ioh)) {
313: printf(": can't map IO space\n");
314: return;
315: }
316:
317: if (ga->ga_type.iodc_sv_model == HPPA_FIO_GLAN)
318: sc->sc_flags |= IEGSC_GECKO;
319:
320: sc->sc_msize = IE_SIZE;
321: /* XXX memory must be under 16M until the mi part is fixed */
322: #if 0
323: if (bus_dmamem_alloc(ga->ga_dmatag, sc->sc_msize, NBPG, 0,
324: &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
325: printf (": cannot allocate %d bytes of DMA memory\n",
326: sc->sc_msize);
327: return;
328: }
329: if (bus_dmamem_map(ga->ga_dmatag, &seg, rseg, sc->sc_msize,
330: (caddr_t *)&sc->bh, BUS_DMA_NOWAIT)) {
331: printf (": cannot map DMA memory\n");
332: bus_dmamem_free(ga->ga_dmatag, &seg, rseg);
333: return;
334: }
335:
336: bzero((void *)sc->bh, sc->sc_msize);
337: sc->sc_maddr = kvtop((caddr_t)sc->bh);
338:
339: #else
340: sc->bh = (u_int)ie_mem;
341: sc->sc_maddr = sc->bh;
342: #endif
343: sc->sysbus = 0x40 | IE_SYSBUS_82586 | IE_SYSBUS_INTLOW | IE_SYSBUS_TRG | IE_SYSBUS_BE;
344:
345: sc->do_xmitnopchain = 0;
346: sc->hwreset = ie_gsc_reset;
347: sc->chan_attn = ie_gsc_attend;
348: sc->port = ie_gsc_port;
349: sc->hwinit = ie_gsc_run;
350: sc->memcopyout = ie_gsc_memcopyout;
351: sc->memcopyin = ie_gsc_memcopyin;
352: sc->ie_bus_read16 = ie_gsc_read16;
353: sc->ie_bus_write16 = ie_gsc_write16;
354: sc->ie_bus_write24 = ie_gsc_write24;
355: #ifdef USELEDS
356: sc->intrhook = ie_gsc_intrhook;
357: #else
358: sc->intrhook = NULL;
359: #endif
360:
361: #ifdef I82596_DEBUG
362: printf(" mem %x[%p]/%x", sc->bh, sc->sc_maddr, sc->sc_msize);
363: sc->sc_debug = IED_ALL;
364: #endif
365: rv = i82596_probe(sc);
366: if (!rv) {
367: /*bus_dmamem_free(ga->ga_dmatag, &seg, sc->sc_msize);*/
368: }
369: #ifdef PMAPDEBUG
370: pmapdebug = opmapdebug;
371: #endif
372: if (!rv) {
373: printf("\n");
374: return;
375: }
376:
377: if (pdc_call((iodcio_t)pdc, 0, PDC_LAN_STATION_ID,
378: PDC_LAN_STATION_ID_READ, &pdc_mac, ga->ga_hpa) < 0)
379: bcopy((void *)ASP_PROM, sc->sc_arpcom.ac_enaddr,
380: ETHER_ADDR_LEN);
381: else
382: bcopy(pdc_mac.addr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
383:
384: printf(":");
385:
386: sc->iscp = 0;
387: sc->scp = 32;
388: sc->scb = 94;
389: sc->buf_area = 256;
390: sc->buf_area_sz = sc->sc_msize - sc->buf_area;
391: sc->sc_type = sc->sc_flags & IEGSC_GECKO? "LASI/i82596CA" : "i82596DX";
392: sc->sc_vers = ga->ga_type.iodc_model * 10 + ga->ga_type.iodc_sv_rev;
393: i82596_attach(sc, sc->sc_type, (char *)sc->sc_arpcom.ac_enaddr,
394: ie_gsc_media, IE_NMEDIA, ie_gsc_media[0]);
395:
396: sc->sc_ih = gsc_intr_establish((struct gsc_softc *)parent,
397: ga->ga_irq, IPL_NET, i82596_intr, sc, sc->sc_dev.dv_xname);
398: }
CVSweb