xref: /netbsd/sys/arch/mac68k/obio/if_sn_obio.c (revision bf9ec67e)
1 /*	$NetBSD: if_sn_obio.c,v 1.19 1999/09/29 06:14:03 scottr Exp $	*/
2 
3 /*
4  * Copyright (C) 1997 Allen Briggs
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 by Allen Briggs
18  * 4. The name of the author may not be used to endorse or promote products
19  *    derived from this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "opt_inet.h"
34 
35 #include <sys/param.h>
36 #include <sys/device.h>
37 #include <sys/errno.h>
38 #include <sys/ioctl.h>
39 #include <sys/socket.h>
40 #include <sys/syslog.h>
41 #include <sys/systm.h>
42 
43 #include <net/if.h>
44 #include <net/if_ether.h>
45 
46 #if 0 /* XXX this shouldn't be necessary... else reinsert */
47 #ifdef INET
48 #include <netinet/in.h>
49 #include <netinet/if_ether.h>
50 #endif
51 #endif
52 
53 #include <machine/bus.h>
54 #include <machine/cpu.h>
55 #include <machine/viareg.h>
56 
57 #include <mac68k/obio/obiovar.h>
58 #include <mac68k/dev/if_snreg.h>
59 #include <mac68k/dev/if_snvar.h>
60 
61 #define SONIC_REG_BASE	0x50F0A000
62 #define SONIC_PROM_BASE	0x50F08000
63 
64 static int	sn_obio_match __P((struct device *, struct cfdata *, void *));
65 static void	sn_obio_attach __P((struct device *, struct device *, void *));
66 static int	sn_obio_getaddr __P((struct sn_softc *, u_int8_t *));
67 static int	sn_obio_getaddr_kludge __P((struct sn_softc *, u_int8_t *));
68 
69 struct cfattach sn_obio_ca = {
70 	sizeof(struct sn_softc), sn_obio_match, sn_obio_attach
71 };
72 
73 static int
74 sn_obio_match(parent, cf, aux)
75 	struct device *parent;
76 	struct cfdata *cf;
77 	void *aux;
78 {
79 	struct obio_attach_args *oa = (struct obio_attach_args *)aux;
80 	bus_space_handle_t	bsh;
81 	int			found = 0;
82 
83 	if (!mac68k_machine.sonic)
84 		return 0;
85 
86 	if (bus_space_map(oa->oa_tag,
87 	    		  SONIC_REG_BASE, SN_REGSIZE, 0, &bsh))
88 		return 0;
89 
90 	if (mac68k_bus_space_probe(oa->oa_tag, bsh, 0, 4))
91 		found = 1;
92 
93 	bus_space_unmap(oa->oa_tag, bsh, SN_REGSIZE);
94 
95 	return found;
96 }
97 
98 /*
99  * Install interface into kernel networking data structures
100  */
101 static void
102 sn_obio_attach(parent, self, aux)
103 	struct device *parent, *self;
104 	void   *aux;
105 {
106 	struct obio_attach_args *oa = (struct obio_attach_args *)aux;
107 	struct sn_softc	*sc = (void *)self;
108 	u_int8_t myaddr[ETHER_ADDR_LEN];
109 	int i;
110 
111 	sc->snr_dcr = DCR_WAIT0 | DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16;
112 	sc->snr_dcr2 = 0;
113 
114 	sc->slotno = 9;
115 
116 	switch (current_mac_model->machineid) {
117 	case MACH_MACC610:
118 	case MACH_MACC650:
119 	case MACH_MACQ610:
120 	case MACH_MACQ650:
121 	case MACH_MACQ700:
122 	case MACH_MACQ800:
123 	case MACH_MACQ900:
124 	case MACH_MACQ950:
125 		sc->snr_dcr |= DCR_EXBUS;
126 		sc->bitmode = 1;
127 		break;
128 
129 	case MACH_MACLC575:
130 	case MACH_MACP580:
131 	case MACH_MACQ630:
132 		break;
133 
134 	case MACH_MACPB500:
135 		sc->snr_dcr |= DCR_SYNC | DCR_LBR;
136 		sc->bitmode = 0;	/* 16 bit interface */
137 		break;
138 
139 	default:
140 		printf(": unsupported machine type\n");
141 		return;
142 	}
143 
144 	sc->sc_regt = oa->oa_tag;
145 
146 	if (bus_space_map(sc->sc_regt,
147 	    SONIC_REG_BASE, SN_REGSIZE, 0, &sc->sc_regh)) {
148 		printf(": failed to map space for SONIC regs.\n");
149 		return;
150 	}
151 
152 	/* regs are addressed as words, big-endian. */
153 	for (i = 0; i < SN_NREGS; i++) {
154 		sc->sc_reg_map[i] = (bus_size_t)((i * 4) + 2);
155 	}
156 
157 	/*
158 	 * Kind of kludge this.  Comm-slot cards do not really
159 	 * have a visible type, as far as I can tell at this time,
160 	 * so assume that MacOS had it properly configured and use
161 	 * that configuration.
162 	 */
163 	switch (current_mac_model->machineid) {
164 	case MACH_MACLC575:
165 	case MACH_MACP580:
166 	case MACH_MACQ630:
167 		NIC_PUT(sc, SNR_CR, CR_RST);	wbflush();
168 		i = NIC_GET(sc, SNR_DCR);
169 		sc->snr_dcr |= (i & 0xfff0);
170 		sc->bitmode = (i & DCR_DW) ? 1 : 0;
171 		break;
172 	default:
173 		break;
174 	}
175 
176 	if (sn_obio_getaddr(sc, myaddr) &&
177 	    sn_obio_getaddr_kludge(sc, myaddr)) { /* XXX kludge for PB */
178 		printf(": failed to get MAC address.\n");
179 		bus_space_unmap(sc->sc_regt, sc->sc_regh, SN_REGSIZE);
180 		return;
181 	}
182 
183 	printf(": integrated Ethernet adapter\n");
184 
185 	/* snsetup returns 1 if something fails */
186 	if (snsetup(sc, myaddr)) {
187 		bus_space_unmap(sc->sc_regt, sc->sc_regh, SN_REGSIZE);
188 		return;
189 	}
190 
191 	if (mac68k_machine.aux_interrupts) {
192 		intr_establish((int (*)(void *))snintr, (void *)sc, 3);
193 	} else {
194 		add_nubus_intr(sc->slotno, snintr, (void *)sc);
195 	}
196 }
197 
198 static int
199 sn_obio_getaddr(sc, lladdr)
200 	struct sn_softc	*sc;
201 	u_int8_t *lladdr;
202 {
203 	bus_space_handle_t bsh;
204 
205 	if (bus_space_map(sc->sc_regt, SONIC_PROM_BASE, NBPG, 0, &bsh)) {
206 		printf(": failed to map space to read SONIC address.\n%s",
207 		    sc->sc_dev.dv_xname);
208 		return (-1);
209 	}
210 
211 	if (!mac68k_bus_space_probe(sc->sc_regt, bsh, 0, 1)) {
212 		bus_space_unmap(sc->sc_regt, bsh, NBPG);
213 		return (-1);
214 	}
215 
216 	sn_get_enaddr(sc->sc_regt, bsh, 0, lladdr);
217 
218 	bus_space_unmap(sc->sc_regt, bsh, NBPG);
219 
220 	return 0;
221 }
222 
223 /*
224  * Assume that the SONIC was initialized in MacOS.  This should go away
225  * when we can properly get the MAC address on the PBs.
226  */
227 static int
228 sn_obio_getaddr_kludge(sc, lladdr)
229 	struct sn_softc	*sc;
230 	u_int8_t *lladdr;
231 {
232 	int i, ors = 0;
233 
234 	/* Shut down NIC */
235 	NIC_PUT(sc, SNR_CR, CR_RST);
236 	wbflush();
237 
238 	NIC_PUT(sc, SNR_CEP, 15); /* For some reason, Apple fills top first. */
239 	wbflush();
240 	i = NIC_GET(sc, SNR_CAP2);
241 	wbflush();
242 
243 	ors |= i;
244 	lladdr[5] = i >> 8;
245 	lladdr[4] = i;
246 
247 	i = NIC_GET(sc, SNR_CAP1);
248 	wbflush();
249 
250 	ors |= i;
251 	lladdr[3] = i >> 8;
252 	lladdr[2] = i;
253 
254 	i = NIC_GET(sc, SNR_CAP0);
255 	wbflush();
256 
257 	ors |= i;
258 	lladdr[1] = i >> 8;
259 	lladdr[0] = i;
260 
261 	NIC_PUT(sc, SNR_CR, 0);
262 	wbflush();
263 
264 	if (ors == 0)
265 		return -1;
266 
267 	return 0;
268 }
269