xref: /openbsd/sys/arch/hppa/gsc/if_ie_gsc.c (revision 78d5ff0e)
1 /*	$OpenBSD: if_ie_gsc.c,v 1.30 2022/03/13 08:04:38 mpi 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_media.h>
45 
46 #include <netinet/in.h>
47 #include <netinet/if_ether.h>
48 
49 #include <machine/bus.h>
50 #include <machine/intr.h>
51 #include <machine/iomod.h>
52 #include <machine/autoconf.h>
53 
54 #include <hppa/dev/cpudevs.h>
55 #include <hppa/gsc/gscbusvar.h>
56 
57 #include <dev/ic/i82596reg.h>
58 #include <dev/ic/i82596var.h>
59 
60 #define	IEGSC_GECKO	IEMD_FLAG0
61 
62 struct ie_gsc_regs {
63 	u_int32_t	ie_reset;
64 	u_int32_t	ie_port;
65 	u_int32_t	ie_attn;
66 };
67 
68 #define	IE_SIZE	0x8000
69 
70 int	ie_gsc_probe(struct device *, void *, void *);
71 void	ie_gsc_attach(struct device *, struct device *, void *);
72 
73 const struct cfattach ie_gsc_ca = {
74 	sizeof(struct ie_softc), ie_gsc_probe, ie_gsc_attach
75 };
76 
77 static uint64_t ie_gsc_media[] = {
78 	IFM_ETHER | IFM_10_2,
79 };
80 #define	IE_NMEDIA	(sizeof(ie_gsc_media) / sizeof(ie_gsc_media[0]))
81 
82 char *ie_mem;
83 
84 void ie_gsc_reset(struct ie_softc *sc, int what);
85 void ie_gsc_attend(struct ie_softc *sc);
86 void ie_gsc_run(struct ie_softc *sc);
87 void ie_gsc_port(struct ie_softc *sc, u_int);
88 #ifdef USELEDS
89 int ie_gsc_intrhook(struct ie_softc *sc, int what);
90 #endif
91 u_int16_t ie_gsc_read16(struct ie_softc *sc, int offset);
92 void ie_gsc_write16(struct ie_softc *sc, int offset, u_int16_t v);
93 void ie_gsc_write24(struct ie_softc *sc, int offset, int addr);
94 void ie_gsc_memcopyin(struct ie_softc *sc, void *p, int offset, size_t);
95 void ie_gsc_memcopyout(struct ie_softc *sc, const void *p, int, size_t);
96 
97 
98 void
ie_gsc_reset(sc,what)99 ie_gsc_reset(sc, what)
100 	struct ie_softc *sc;
101 	int what;
102 {
103 	volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
104 	int i;
105 
106 	r->ie_reset = 0;
107 	/*
108 	 * per [2] 4.6.2.1
109 	 * delay for 10 system clocks + 5 transmit clocks,
110 	 * NB: works for system clocks over 10MHz
111 	 */
112 	DELAY(1000);
113 
114 	switch (what) {
115 	case IE_CHIP_PROBE:
116 		break;
117 
118 	case IE_CARD_RESET:
119 		/*
120 		 * after the hardware reset:
121 		 * inform i825[89]6 about new SCP address,
122 		 * maddr must be at least 16-byte aligned
123 		 */
124 		ie_gsc_port(sc, IE_PORT_SCP);
125 		ie_gsc_attend(sc);
126 
127 		for (i = 9000; i-- && ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp));
128 		     DELAY(100))
129 			pdcache(0, sc->sc_maddr + sc->iscp, IE_ISCP_SZ);
130 
131 #ifdef I82596_DEBUG
132 		if (i < 0) {
133 			printf("timeout for PORT command (%x)%s\n",
134 			       ie_gsc_read16(sc, IE_ISCP_BUSY(sc->iscp)),
135 			       (sc->sc_flags & IEGSC_GECKO)? " on gecko":"");
136 			return;
137 		}
138 #endif
139 		break;
140 	}
141 }
142 
143 void
ie_gsc_attend(sc)144 ie_gsc_attend(sc)
145 	struct ie_softc *sc;
146 {
147 	volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
148 
149 	fdcache(0, (vaddr_t)ie_mem, IE_SIZE);
150 	DELAY(1);
151 	r->ie_attn = 0;
152 	DELAY(1);
153 }
154 
155 void
ie_gsc_run(sc)156 ie_gsc_run(sc)
157 	struct ie_softc *sc;
158 {
159 }
160 
161 void
ie_gsc_port(sc,cmd)162 ie_gsc_port(sc, cmd)
163 	struct ie_softc *sc;
164 	u_int cmd;
165 {
166 	switch (cmd) {
167 	case IE_PORT_RESET:
168 		cmd = 0;
169 		break;
170 	case IE_PORT_TEST:
171 		cmd = ((u_int)sc->sc_maddr + sc->scp) | 1;
172 		break;
173 	case IE_PORT_SCP:
174 		cmd = ((u_int)sc->sc_maddr + sc->scp) | 2;
175 		break;
176 	case IE_PORT_DUMP:
177 		cmd = 3;
178 		break;
179 	}
180 
181 	if (sc->sc_flags & IEGSC_GECKO) {
182 		volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
183 		r->ie_port = cmd & 0xffff;
184 		DELAY(1000);
185 		r->ie_port = cmd >> 16;
186 		DELAY(1000);
187 	} else {
188 		volatile struct ie_gsc_regs *r = (struct ie_gsc_regs *)sc->ioh;
189 		r->ie_port = cmd >> 16;
190 		DELAY(1000);
191 		r->ie_port = cmd & 0xffff;
192 		DELAY(1000);
193 	}
194 }
195 
196 #ifdef USELEDS
197 int
ie_gsc_intrhook(sc,where)198 ie_gsc_intrhook(sc, where)
199 	struct ie_softc *sc;
200 	int where;
201 {
202 	switch (where) {
203 	case IE_INTR_ENRCV:
204 		ledctl(PALED_NETRCV, 0, 0);
205 		break;
206 	case IE_INTR_ENSND:
207 		ledctl(PALED_NETSND, 0, 0);
208 		break;
209 	case IE_INTR_EXIT:
210 	case IE_INTR_LOOP:
211 		fdcache(0, (vaddr_t)ie_mem, IE_SIZE);
212 		break;
213 	}
214 	return 0;
215 }
216 #endif
217 
218 u_int16_t
ie_gsc_read16(sc,offset)219 ie_gsc_read16(sc, offset)
220 	struct ie_softc *sc;
221 	int offset;
222 {
223 	volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
224 
225 	asm volatile ("fdc	%%r0(%%sr0, %0)" :: "r" (addr));
226 	return *addr;
227 }
228 
229 void
ie_gsc_write16(sc,offset,v)230 ie_gsc_write16(sc, offset, v)
231 	struct ie_softc *sc;
232 	int offset;
233 	u_int16_t v;
234 {
235 	volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
236 
237 	*addr = v;
238 	asm volatile ("fdc	%%r0(%%sr0, %0)" :: "r" (addr));
239 }
240 
241 void
ie_gsc_write24(sc,offset,v)242 ie_gsc_write24(sc, offset, v)
243 	struct ie_softc *sc;
244 	int offset;
245 	int v;
246 {
247 	volatile u_int16_t *addr = (volatile u_int16_t *)(sc->bh + offset);
248 
249 	addr[0] = (v      ) & 0xffff;
250 	addr[1] = (v >> 16) & 0xffff;
251 	asm volatile ("fdc	%%r0(%%sr0, %0)" :: "r" (addr+0));
252 	asm volatile ("fdc	%%r0(%%sr0, %0)" :: "r" (addr+1));
253 }
254 
255 void
ie_gsc_memcopyin(sc,p,offset,size)256 ie_gsc_memcopyin(sc, p, offset, size)
257 	struct ie_softc	*sc;
258 	void *p;
259 	int offset;
260 	size_t size;
261 {
262 	pdcache(0, sc->bh + offset, size);
263 	bcopy ((void *)((u_long)sc->bh + offset), p, size);
264 }
265 
266 void
ie_gsc_memcopyout(sc,p,offset,size)267 ie_gsc_memcopyout(sc, p, offset, size)
268 	struct ie_softc	*sc;
269 	const void *p;
270 	int offset;
271 	size_t size;
272 {
273 	bcopy (p, (void *)((u_long)sc->bh + offset), size);
274 	fdcache(0, sc->bh + offset, size);
275 }
276 
277 int
ie_gsc_probe(parent,match,aux)278 ie_gsc_probe(parent, match, aux)
279 	struct device *parent;
280 	void *match, *aux;
281 {
282 	struct gsc_attach_args *ga = aux;
283 
284 	if (ga->ga_type.iodc_type != HPPA_TYPE_FIO ||
285 	    (ga->ga_type.iodc_sv_model != HPPA_FIO_LAN &&
286 	     ga->ga_type.iodc_sv_model != HPPA_FIO_GLAN))
287 		return 0;
288 
289 	return 1;
290 }
291 
292 void
ie_gsc_attach(parent,self,aux)293 ie_gsc_attach(parent, self, aux)
294 	struct device *parent, *self;
295 	void *aux;
296 {
297 	struct pdc_lan_station_id pdc_mac PDC_ALIGNMENT;
298 	struct ie_softc *sc = (struct ie_softc *)self;
299 	struct gsc_attach_args *ga = aux;
300 	/*bus_dma_segment_t seg;
301 	int rseg;*/
302 	int rv;
303 #ifdef PMAPDEBUG
304 	extern int pmapdebug;
305 	int opmapdebug = pmapdebug;
306 	pmapdebug = 0;
307 #endif
308 
309 	sc->iot = sc->bt = ga->ga_iot;
310 	if (bus_space_map(sc->iot, ga->ga_hpa, IOMOD_HPASIZE, 0, &sc->ioh)) {
311 		printf(": can't map IO space\n");
312 		return;
313 	}
314 
315 	if (ga->ga_type.iodc_sv_model == HPPA_FIO_GLAN)
316 		sc->sc_flags |= IEGSC_GECKO;
317 
318 	sc->sc_msize = IE_SIZE;
319 	/* XXX memory must be under 16M until the mi part is fixed */
320 #if 0
321 	if (bus_dmamem_alloc(ga->ga_dmatag, sc->sc_msize, NBPG, 0,
322 			     &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
323 		printf (": cannot allocate %d bytes of DMA memory\n",
324 			sc->sc_msize);
325 		return;
326 	}
327 	if (bus_dmamem_map(ga->ga_dmatag, &seg, rseg, sc->sc_msize,
328 			   (caddr_t *)&sc->bh, BUS_DMA_NOWAIT)) {
329 		printf (": cannot map DMA memory\n");
330 		bus_dmamem_free(ga->ga_dmatag, &seg, rseg);
331 		return;
332 	}
333 
334 	bzero((void *)sc->bh, sc->sc_msize);
335 	sc->sc_maddr = kvtop((caddr_t)sc->bh);
336 
337 #else
338 	sc->bh = (u_int)ie_mem;
339 	sc->sc_maddr = sc->bh;
340 #endif
341 	sc->sysbus = 0x40 | IE_SYSBUS_82586 | IE_SYSBUS_INTLOW | IE_SYSBUS_TRG | IE_SYSBUS_BE;
342 
343 	sc->do_xmitnopchain = 0;
344 	sc->hwreset = ie_gsc_reset;
345 	sc->chan_attn = ie_gsc_attend;
346 	sc->port = ie_gsc_port;
347 	sc->hwinit = ie_gsc_run;
348 	sc->memcopyout = ie_gsc_memcopyout;
349 	sc->memcopyin = ie_gsc_memcopyin;
350 	sc->ie_bus_read16 = ie_gsc_read16;
351 	sc->ie_bus_write16 = ie_gsc_write16;
352 	sc->ie_bus_write24 = ie_gsc_write24;
353 #ifdef USELEDS
354 	sc->intrhook = ie_gsc_intrhook;
355 #else
356 	sc->intrhook = NULL;
357 #endif
358 
359 #ifdef I82596_DEBUG
360 	printf(" mem %x[%p]/%x", sc->bh, sc->sc_maddr, sc->sc_msize);
361 	sc->sc_debug = IED_ALL;
362 #endif
363 	rv = i82596_probe(sc);
364 	if (!rv) {
365 		/*bus_dmamem_free(ga->ga_dmatag, &seg, sc->sc_msize);*/
366 	}
367 #ifdef PMAPDEBUG
368 	pmapdebug = opmapdebug;
369 #endif
370 	if (!rv) {
371 		printf("\n");
372 		return;
373 	}
374 
375 	if (pdc_call((iodcio_t)pdc, 0, PDC_LAN_STATION_ID,
376 		     PDC_LAN_STATION_ID_READ, &pdc_mac, ga->ga_hpa) < 0)
377 		bcopy((void *)ASP_PROM, sc->sc_arpcom.ac_enaddr,
378 		      ETHER_ADDR_LEN);
379 	else
380 		bcopy(pdc_mac.addr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
381 
382 	printf(":");
383 
384 	sc->iscp = 0;
385 	sc->scp = 32;
386 	sc->scb = 94;
387 	sc->buf_area = 256;
388 	sc->buf_area_sz = sc->sc_msize - sc->buf_area;
389 	sc->sc_type = sc->sc_flags & IEGSC_GECKO? "LASI/i82596CA" : "i82596DX";
390 	sc->sc_vers = ga->ga_type.iodc_model * 10 + ga->ga_type.iodc_sv_rev;
391 	i82596_attach(sc, sc->sc_type, (char *)sc->sc_arpcom.ac_enaddr,
392 		      ie_gsc_media, IE_NMEDIA, ie_gsc_media[0]);
393 
394 	sc->sc_ih = gsc_intr_establish((struct gsc_softc *)parent,
395 	    ga->ga_irq, IPL_NET, i82596_intr, sc, sc->sc_dev.dv_xname);
396 }
397