xref: /openbsd/sys/arch/hppa/gsc/if_ie_gsc.c (revision 17df1aa7)
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 }
399