xref: /netbsd/sys/arch/mac68k/nubus/if_sn_nubus.c (revision bf9ec67e)
1 /*	$NetBSD: if_sn_nubus.c,v 1.20 1999/09/29 06:04:51 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_inarp.h>
50 #endif
51 #endif
52 
53 #include <machine/bus.h>
54 #include <machine/viareg.h>
55 
56 #include <mac68k/nubus/nubus.h>
57 #include <mac68k/dev/if_snreg.h>
58 #include <mac68k/dev/if_snvar.h>
59 
60 static int	sn_nubus_match __P((struct device *, struct cfdata *, void *));
61 static void	sn_nubus_attach __P((struct device *, struct device *, void *));
62 static int	sn_nb_card_vendor __P((bus_space_tag_t, bus_space_handle_t,
63 		    struct nubus_attach_args *));
64 
65 struct cfattach sn_nubus_ca = {
66 	sizeof(struct sn_softc), sn_nubus_match, sn_nubus_attach
67 };
68 
69 
70 static int
71 sn_nubus_match(parent, cf, aux)
72 	struct device *parent;
73 	struct cfdata *cf;
74 	void *aux;
75 {
76 	struct nubus_attach_args *na = (struct nubus_attach_args *) aux;
77 	bus_space_handle_t bsh;
78 	int rv;
79 
80 	if (bus_space_map(na->na_tag,
81 	    NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 0, &bsh))
82 		return (0);
83 
84 	rv = 0;
85 
86 	if (na->category == NUBUS_CATEGORY_NETWORK &&
87 	    na->type == NUBUS_TYPE_ETHERNET) {
88 		switch (sn_nb_card_vendor(na->na_tag, bsh, na)) {
89 		default:
90 			break;
91 
92 		case SN_VENDOR_APPLE:
93 		case SN_VENDOR_APPLE16:
94 		case SN_VENDOR_ASANTELC:
95 		case SN_VENDOR_DAYNA:
96 			rv = 1;
97 			break;
98 		}
99 	}
100 
101 	bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
102 
103 	return rv;
104 }
105 
106 /*
107  * Install interface into kernel networking data structures
108  */
109 static void
110 sn_nubus_attach(parent, self, aux)
111 	struct device *parent, *self;
112 	void   *aux;
113 {
114 	struct sn_softc *sc = (void *)self;
115 	struct nubus_attach_args *na = (struct nubus_attach_args *)aux;
116 	int i, success, offset;
117 	bus_space_tag_t	bst;
118 	bus_space_handle_t bsh, tmp_bsh;
119 	u_int8_t myaddr[ETHER_ADDR_LEN];
120 	char *cardtype;
121 
122 	(void)(&offset);	/* Work around lame gcc initialization bug */
123 
124 	bst = na->na_tag;
125 	if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 0, &bsh)) {
126 		printf(": failed to map memory space.\n");
127 		return;
128 	}
129 
130 	sc->sc_regt = bst;
131 
132 	cardtype = nubus_get_card_name(bst, bsh, na->fmt);
133 
134 	success = 0;
135 
136 	sc->slotno = na->slot;
137 
138 	switch (sn_nb_card_vendor(bst, bsh, na)) {
139 	case SN_VENDOR_DAYNA:
140 		sc->snr_dcr = DCR_ASYNC | DCR_WAIT0 |
141 		    DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16;
142 		sc->snr_dcr2 = 0;
143 		sc->bitmode = 1;	/* 32 bit card */
144 
145 		if (bus_space_subregion(bst, bsh,
146 		    0x00180000, SN_REGSIZE, &sc->sc_regh)) {
147 			printf(": failed to map register space.\n");
148 			break;
149 		}
150 
151 		if (bus_space_subregion(bst, bsh,
152 		    0x00ffe004, ETHER_ADDR_LEN, &tmp_bsh)) {
153 			printf(": failed to map ROM space.\n");
154 			break;
155 		}
156 
157 		sn_get_enaddr(bst, tmp_bsh, 0, myaddr);
158 
159 		offset = 2;
160 		success = 1;
161 		break;
162 
163 	case SN_VENDOR_APPLE:
164 		sc->snr_dcr = DCR_ASYNC | DCR_WAIT0 |
165 		    DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16;
166 		sc->snr_dcr2 = 0;
167 		sc->bitmode = 1; /* 32 bit card */
168 
169 		if (bus_space_subregion(bst, bsh,
170 		    0x0, SN_REGSIZE, &sc->sc_regh)) {
171 			printf(": failed to map register space.\n");
172 			break;
173 		}
174 
175 		if (bus_space_subregion(bst, bsh,
176 		    0x40000, ETHER_ADDR_LEN, &tmp_bsh)) {
177 			printf(": failed to map ROM space.\n");
178 			break;
179 		}
180 
181 		sn_get_enaddr(bst, tmp_bsh, 0, myaddr);
182 
183 		offset = 0;
184 		success = 1;
185 		break;
186 
187 	case SN_VENDOR_APPLE16:
188 		sc->snr_dcr = DCR_ASYNC | DCR_WAIT0 | DCR_EXBUS |
189 		    DCR_DMABLOCK | DCR_PO1 | DCR_RFT16 | DCR_TFT16;
190 		sc->snr_dcr2 = 0;
191 		sc->bitmode = 0; /* 16 bit card */
192 
193 		if (bus_space_subregion(bst, bsh,
194 		    0x0, SN_REGSIZE, &sc->sc_regh)) {
195 			printf(": failed to map register space.\n");
196 			break;
197 		}
198 
199 		if (bus_space_subregion(bst, bsh,
200 		    0x40000, ETHER_ADDR_LEN, &tmp_bsh)) {
201 			printf(": failed to map ROM space.\n");
202 			break;
203 		}
204 
205 		sn_get_enaddr(bst, tmp_bsh, 0, myaddr);
206 
207 		offset = 0;
208 		success = 1;
209 		break;
210 
211 	case SN_VENDOR_ASANTELC: /* Macintosh LC Ethernet Adapter */
212 		sc->snr_dcr = DCR_ASYNC | DCR_WAIT0 |
213 		    DCR_DMABLOCK | DCR_PO1 | DCR_RFT16 | DCR_TFT16;
214 		sc->snr_dcr2 = 0;
215 		sc->bitmode = 0; /* 16 bit card */
216 
217 		if (bus_space_subregion(bst, bsh,
218 		    0x0, SN_REGSIZE, &sc->sc_regh)) {
219 			printf(": failed to map register space.\n");
220 			break;
221 		}
222 
223 		if (bus_space_subregion(bst, bsh,
224 		    0x400000, ETHER_ADDR_LEN, &tmp_bsh)) {
225 			printf(": failed to map ROM space.\n");
226 			break;
227 		}
228 
229 		sn_get_enaddr(bst, tmp_bsh, 0, myaddr);
230 
231 		offset = 0;
232 		success = 1;
233 		break;
234 
235 	default:
236 		/*
237 		 * You can't actually get this default, the snmatch
238 		 * will fail for unknown hardware. If you're adding support
239 		 * for a new card, the following defaults are a
240 		 * good starting point.
241 		 */
242 		sc->snr_dcr = DCR_SYNC | DCR_WAIT0 | DCR_DW32 |
243 		    DCR_DMABLOCK | DCR_RFT16 | DCR_TFT16;
244 		sc->snr_dcr2 = 0;
245 		success = 0;
246 		printf(": unknown card: attachment incomplete.\n");
247 	}
248 
249 	if (!success) {
250 		bus_space_unmap(bst, bsh, NBMEMSIZE);
251 		return;
252 	}
253 
254 	/* Regs are addressed as words, big endian. */
255 	for (i = 0; i < SN_NREGS; i++) {
256 		sc->sc_reg_map[i] = (bus_size_t)((i * 4) + offset);
257 	}
258 
259 	printf(": %s\n", cardtype);
260 
261 	/* snsetup returns 1 if something fails */
262 	if (snsetup(sc, myaddr)) {
263 		bus_space_unmap(bst, bsh, NBMEMSIZE);
264 		return;
265 	}
266 
267 	add_nubus_intr(sc->slotno, snintr, (void *)sc);
268 
269 	return;
270 }
271 
272 static int
273 sn_nb_card_vendor(bst, bsh, na)
274 	bus_space_tag_t bst;
275 	bus_space_handle_t bsh;
276 	struct nubus_attach_args *na;
277 {
278 	int vendor = SN_VENDOR_UNKNOWN;
279 
280 	switch (na->drsw) {
281 	case NUBUS_DRSW_3COM:
282 		if (na->drhw == NUBUS_DRHW_APPLE_SNT)
283 			vendor = SN_VENDOR_APPLE;
284 		else if (na->drhw == NUBUS_DRHW_APPLE_SN)
285 			vendor = SN_VENDOR_APPLE16;
286 		break;
287 	case NUBUS_DRSW_APPLE:
288 		if (na->drhw == NUBUS_DRHW_ASANTE_LC)
289 			vendor = SN_VENDOR_ASANTELC;
290 		else
291 			vendor = SN_VENDOR_APPLE;
292 		break;
293 	case NUBUS_DRSW_TECHWORKS:
294 		vendor = SN_VENDOR_APPLE;
295 		break;
296 	case NUBUS_DRSW_GATOR:
297 		if (na->drhw == NUBUS_DRHW_KINETICS &&
298 		    strncmp(nubus_get_card_name(bst, bsh, na->fmt),
299 		    "EtherPort", 9) != 0)
300 			vendor = SN_VENDOR_DAYNA;
301 		break;
302 	case NUBUS_DRSW_DAYNA:
303 		vendor = SN_VENDOR_DAYNA;
304 		break;
305 	}
306 
307 	return vendor;
308 }
309