1/*	$NetBSD: if_sn_nubus.c,v 1.28 2007/10/17 19:55:15 garbled 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 <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: if_sn_nubus.c,v 1.28 2007/10/17 19:55:15 garbled Exp $");
35
36#include <sys/param.h>
37#include <sys/systm.h>
38#include <sys/device.h>
39#include <sys/ioctl.h>
40
41#include <net/if.h>
42#include <net/if_ether.h>
43
44#include <machine/bus.h>
45#include <machine/viareg.h>
46
47#include <dev/ic/dp83932reg.h>
48#include <dev/ic/dp83932var.h>
49
50#include <mac68k/nubus/nubus.h>
51#include <mac68k/dev/if_snvar.h>
52
53static int	sn_nubus_match(device_t, cfdata_t, void *);
54static void	sn_nubus_attach(device_t, device_t, void *);
55static int	sn_nb_card_vendor(bus_space_tag_t, bus_space_handle_t,
56		    struct nubus_attach_args *);
57
58CFATTACH_DECL_NEW(sn_nubus, sizeof(struct sonic_softc),
59    sn_nubus_match, sn_nubus_attach, NULL, NULL);
60
61
62static int
63sn_nubus_match(device_t parent, cfdata_t cf, void *aux)
64{
65	struct nubus_attach_args *na = aux;
66	bus_space_handle_t bsh;
67	int rv;
68
69	if (bus_space_map(na->na_tag,
70	    NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 0, &bsh))
71		return 0;
72
73	rv = 0;
74
75	if (na->category == NUBUS_CATEGORY_NETWORK &&
76	    na->type == NUBUS_TYPE_ETHERNET) {
77		switch (sn_nb_card_vendor(na->na_tag, bsh, na)) {
78		default:
79			break;
80
81		case SN_VENDOR_APPLE:
82		case SN_VENDOR_APPLE16:
83		case SN_VENDOR_ASANTELC:
84		case SN_VENDOR_DAYNA:
85			rv = 1;
86			break;
87		}
88	}
89
90	bus_space_unmap(na->na_tag, bsh, NBMEMSIZE);
91
92	return rv;
93}
94
95/*
96 * Install interface into kernel networking data structures
97 */
98static void
99sn_nubus_attach(device_t parent, device_t self, void *aux)
100{
101	struct sonic_softc *sc = device_private(self);
102	struct nubus_attach_args *na = aux;
103	int i, success, offset;
104	bus_space_tag_t	bst;
105	bus_space_handle_t bsh, tmp_bsh;
106	uint8_t myaddr[ETHER_ADDR_LEN];
107	const char *cardtype;
108
109	bst = na->na_tag;
110	if (bus_space_map(bst, NUBUS_SLOT2PA(na->slot), NBMEMSIZE, 0, &bsh)) {
111		aprint_error(": failed to map memory space.\n");
112		return;
113	}
114
115	sc->sc_dev = self;
116	sc->sc_st = bst;
117	sc->sc_dmat = na->na_dmat;
118
119	cardtype = nubus_get_card_name(bst, bsh, na->fmt);
120
121	success = 0;
122	offset = 0;
123
124	switch (sn_nb_card_vendor(bst, bsh, na)) {
125	case SN_VENDOR_DAYNA:
126		sc->sc_dcr = DCR_BMS | DCR_RFT1 | DCR_TFT0;
127		sc->sc_dcr2 = 0;
128		sc->sc_32bit = 1;	/* 32 bit card */
129
130		if (bus_space_subregion(bst, bsh,
131		    0x00180000, SONIC_NREGS * 4, &sc->sc_sh)) {
132			aprint_error(": failed to map register space.\n");
133			break;
134		}
135
136		if (bus_space_subregion(bst, bsh,
137		    0x00ffe004, ETHER_ADDR_LEN, &tmp_bsh)) {
138			aprint_error(": failed to map ROM space.\n");
139			break;
140		}
141
142		sn_get_enaddr(bst, tmp_bsh, 0, myaddr);
143
144		offset = 2;
145		success = 1;
146		break;
147
148	case SN_VENDOR_APPLE:
149		sc->sc_dcr = DCR_BMS | DCR_RFT1 | DCR_TFT0;
150		sc->sc_dcr2 = 0;
151		sc->sc_32bit = 1; /* 32 bit card */
152
153		if (bus_space_subregion(bst, bsh,
154		    0x0, SONIC_NREGS * 4, &sc->sc_sh)) {
155			aprint_error(": failed to map register space.\n");
156			break;
157		}
158
159		if (bus_space_subregion(bst, bsh,
160		    0x40000, ETHER_ADDR_LEN, &tmp_bsh)) {
161			aprint_error(": failed to map ROM space.\n");
162			break;
163		}
164
165		sn_get_enaddr(bst, tmp_bsh, 0, myaddr);
166
167		offset = 0;
168		success = 1;
169		break;
170
171	case SN_VENDOR_APPLE16:
172		sc->sc_dcr = DCR_EXBUS | DCR_BMS | DCR_PO1 |
173		    DCR_RFT1 | DCR_TFT0;
174		sc->sc_dcr2 = 0;
175		sc->sc_32bit = 0; /* 16 bit card */
176
177		if (bus_space_subregion(bst, bsh,
178		    0x0, SONIC_NREGS * 4, &sc->sc_sh)) {
179			aprint_error(": failed to map register space.\n");
180			break;
181		}
182
183		if (bus_space_subregion(bst, bsh,
184		    0x40000, ETHER_ADDR_LEN, &tmp_bsh)) {
185			aprint_error(": failed to map ROM space.\n");
186			break;
187		}
188
189		sn_get_enaddr(bst, tmp_bsh, 0, myaddr);
190
191		offset = 0;
192		success = 1;
193		break;
194
195	case SN_VENDOR_ASANTELC: /* Macintosh LC Ethernet Adapter */
196		sc->sc_dcr = DCR_BMS | DCR_PO1 | DCR_RFT1 | DCR_TFT0;
197		sc->sc_dcr2 = 0;
198		sc->sc_32bit = 0; /* 16 bit card */
199
200		if (bus_space_subregion(bst, bsh,
201		    0x0, SONIC_NREGS * 4, &sc->sc_sh)) {
202			aprint_error(": failed to map register space.\n");
203			break;
204		}
205
206		if (bus_space_subregion(bst, bsh,
207		    0x400000, ETHER_ADDR_LEN, &tmp_bsh)) {
208			aprint_error(": failed to map ROM space.\n");
209			break;
210		}
211
212		sn_get_enaddr(bst, tmp_bsh, 0, myaddr);
213
214		offset = 0;
215		success = 1;
216		break;
217
218	default:
219		/*
220		 * You can't actually get this default, the snmatch
221		 * will fail for unknown hardware. If you're adding support
222		 * for a new card, the following defaults are a
223		 * good starting point.
224		 */
225		sc->sc_dcr = DCR_SBUS | DCR_BMS | DCR_RFT1 | DCR_TFT0;
226		sc->sc_dcr2 = 0;
227		sc->sc_32bit = 1;
228		success = 0;
229		aprint_error(": unknown card: attachment incomplete.\n");
230	}
231
232	if (!success) {
233		bus_space_unmap(bst, bsh, NBMEMSIZE);
234		return;
235	}
236
237	/* Regs are addressed as words, big endian. */
238	for (i = 0; i < SONIC_NREGS; i++) {
239		sc->sc_regmap[i] = (bus_size_t)((i * 4) + offset);
240	}
241
242	sc->sc_bigendian = 1;
243
244	aprint_error(": %s\n", cardtype);
245
246	add_nubus_intr(na->slot, (void (*)(void *))sonic_intr, (void *)sc);
247
248	sonic_attach(sc, myaddr);
249
250	return;
251}
252
253static int
254sn_nb_card_vendor(bus_space_tag_t bst, bus_space_handle_t bsh,
255    struct nubus_attach_args *na)
256{
257	int vendor = SN_VENDOR_UNKNOWN;
258
259	switch (na->drsw) {
260	case NUBUS_DRSW_3COM:
261		if (na->drhw == NUBUS_DRHW_APPLE_SNT)
262			vendor = SN_VENDOR_APPLE;
263		else if (na->drhw == NUBUS_DRHW_APPLE_SN)
264			vendor = SN_VENDOR_APPLE16;
265		break;
266	case NUBUS_DRSW_APPLE:
267		if (na->drhw == NUBUS_DRHW_ASANTE_LC)
268			vendor = SN_VENDOR_ASANTELC;
269		else
270			vendor = SN_VENDOR_APPLE;
271		break;
272	case NUBUS_DRSW_TECHWORKS:
273		vendor = SN_VENDOR_APPLE;
274		break;
275	case NUBUS_DRSW_GATOR:
276		if (na->drhw == NUBUS_DRHW_KINETICS &&
277		    strncmp(nubus_get_card_name(bst, bsh, na->fmt),
278		    "EtherPort", 9) != 0)
279			vendor = SN_VENDOR_DAYNA;
280		break;
281	case NUBUS_DRSW_DAYNA:
282		vendor = SN_VENDOR_DAYNA;
283		break;
284	}
285
286	return vendor;
287}
288