xref: /netbsd/sys/arch/i386/stand/lib/netif/wd80x3.c (revision bf9ec67e)
1 /*	$NetBSD: wd80x3.c,v 1.7 2002/02/17 19:47:41 thorpej Exp $	*/
2 
3 /*-
4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
9  * NASA Ames Research Center.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgement:
21  *	This product includes software developed by the NetBSD
22  *	Foundation, Inc. and its contributors.
23  * 4. Neither the name of The NetBSD Foundation nor the names of its
24  *    contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37  * POSSIBILITY OF SUCH DAMAGE.
38  */
39 
40 /*
41  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
42  * adapters.
43  *
44  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
45  *
46  * Copyright (C) 1993, David Greenman.  This software may be used, modified,
47  * copied, distributed, and sold, in both source and binary form provided that
48  * the above copyright and these terms are retained.  Under no circumstances is
49  * the author responsible for the proper functioning of this software, nor does
50  * the author assume any responsibility for damages incurred with its use.
51  */
52 
53 /*
54  * Device driver for the Western Digital/SMC 8003 and 8013 series,
55  * and the SMC Elite Ultra (8216).
56  */
57 
58 #include <sys/types.h>
59 #include <machine/pio.h>
60 
61 #include <lib/libsa/stand.h>
62 #include <libi386.h>
63 
64 #ifdef _STANDALONE
65 #include <lib/libkern/libkern.h>
66 #include <bootinfo.h>
67 #endif
68 
69 #include "etherdrv.h"
70 #include <dev/ic/dp8390reg.h>
71 #include "dp8390.h"
72 #include <dev/ic/wereg.h>
73 
74 #ifndef BASEREG
75 #define BASEREG 0x240
76 #define BASEMEM 0xd0000
77 #endif
78 
79 #define	WD_BASEREG BASEREG
80 #define	WD_BASEMEM BASEMEM
81 
82 #ifndef _STANDALONE
83 extern int mapio __P((void));
84 #endif
85 
86 u_char eth_myaddr[6];
87 
88 static u_int8_t we_type;
89 static int we_is16bit;
90 
91 #ifdef _STANDALONE
92 static struct btinfo_netif bi_netif;
93 #endif
94 
95 const char *
96 we_params()
97 {
98 	const char *typestr;
99 
100 	dp8390_memsize = 8192;
101 
102 	we_type = inb(WD_BASEREG + WE_CARD_ID);
103 	switch (we_type) {
104 #ifdef SUPPORT_WD80X3
105 	case WE_TYPE_WD8003S:
106 		typestr = "WD8003S";
107 		break;
108 	case WE_TYPE_WD8003E:
109 		typestr = "WD8003E";
110 		break;
111 	case WE_TYPE_WD8003EB:
112 		typestr = "WD8003EB";
113 		break;
114 	case WE_TYPE_WD8003W:
115 		typestr = "WD8003W";
116 		break;
117 	case WE_TYPE_WD8013EBT:
118 		typestr = "WD8013EBT";
119 		dp8390_memsize = 16384;
120 		we_is16bit = 1;
121 		break;
122 	case WE_TYPE_WD8013W:
123 		typestr = "WD8013W";
124 		dp8390_memsize = 16384;
125 		we_is16bit = 1;
126 		break;
127 	case WE_TYPE_WD8013EP:		/* also WD8003EP */
128 		if (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) {
129 			we_is16bit = 1;
130 			dp8390_memsize = 16384;
131 			typestr = "WD8013EP";
132 		} else
133 			typestr = "WD8003EP";
134 		break;
135 	case WE_TYPE_WD8013WC:
136 		typestr = "WD8013WC";
137 		dp8390_memsize = 16384;
138 		we_is16bit = 1;
139 		break;
140 	case WE_TYPE_WD8013EBP:
141 		typestr = "WD8013EBP";
142 		dp8390_memsize = 16384;
143 		we_is16bit = 1;
144 		break;
145 	case WE_TYPE_WD8013EPC:
146 		typestr = "WD8013EPC";
147 		dp8390_memsize = 16384;
148 		we_is16bit = 1;
149 		break;
150 #endif
151 #ifdef SUPPORT_SMC_ULTRA
152 	case WE_TYPE_SMC8216C:
153 	case WE_TYPE_SMC8216T:
154 	    {
155 		u_int8_t hwr;
156 
157 		typestr = (we_type == WE_TYPE_SMC8216C) ?
158 		    "SMC8216/SMC8216C" : "SMC8216T";
159 
160 		hwr = inb(WD_BASEREG + WE790_HWR);
161 		outb(WD_BASEREG + WE790_HWR, hwr | WE790_HWR_SWH);
162 		switch (inb(WD_BASEREG + WE790_RAR) & WE790_RAR_SZ64) {
163 		case WE790_RAR_SZ64:
164 			dp8390_memsize = 65536;
165 			break;
166 		case WE790_RAR_SZ32:
167 			dp8390_memsize = 32768;
168 			break;
169 		case WE790_RAR_SZ16:
170 			dp8390_memsize = 16384;
171 			break;
172 		case WE790_RAR_SZ8:
173 			/* 8216 has 16K shared mem -- 8416 has 8K */
174 			typestr = (we_type == WE_TYPE_SMC8216C) ?
175 			    "SMC8416C/SMC8416BT" : "SMC8416T";
176 			dp8390_memsize = 8192;
177 			break;
178 		}
179 		outb(WD_BASEREG + WE790_HWR, hwr);
180 
181 		we_is16bit = 1;
182 #ifdef SUPPORT_WD80X3
183 		dp8390_is790 = 1;
184 #endif
185 		break;
186 	    }
187 #endif
188 	default:
189 		/* Not one we recognize. */
190 		return (NULL);
191 	}
192 
193 	/*
194 	 * Make some adjustments to initial values depending on what is
195 	 * found in the ICR.
196 	 */
197 	if (we_is16bit && (we_type != WE_TYPE_WD8013EBT) &&
198 	    (inb(WD_BASEREG + WE_ICR) & WE_ICR_16BIT) == 0) {
199 		we_is16bit = 0;
200 		dp8390_memsize = 8192;
201 	}
202 
203 #ifdef WE_DEBUG
204 	{
205 		int i;
206 
207 		printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, "
208 		    "memsize = %d\n", we_type, typestr, we_is16bit, dp8390_memsize);
209 		for (i = 0; i < 8; i++)
210 			printf("     %d -> 0x%x\n", i,
211 			    inb(WD_BASEREG + i));
212 	}
213 #endif
214 
215 	return (typestr);
216 }
217 
218 int
219 EtherInit(myadr)
220 	unsigned char *myadr;
221 {
222 	const char *typestr;
223 	u_int8_t x;
224 	int i;
225 	u_int8_t laar_proto;
226 	u_int8_t msr_proto;
227 
228 	dp8390_iobase = WD_BASEREG + WE_NIC_OFFSET;
229 	dp8390_membase = WD_BASEMEM;
230 
231 #ifndef _STANDALONE
232 	if (mapio()) {
233 		printf("no IO access\n");
234 		return(0);
235 	}
236 #endif
237 
238 	for (x = 0, i = 0; i < 8; i++)
239 		x += inb(WD_BASEREG + WE_PROM + i);
240 
241 	if (x != WE_ROM_CHECKSUM_TOTAL)
242 		return(0);
243 
244 	/* reset the ethernet card */
245 	outb(WD_BASEREG + WE_MSR, WE_MSR_RST);
246 	delay(100);
247 	outb(WD_BASEREG + WE_MSR, inb(WD_BASEREG + WE_MSR) & ~WE_MSR_RST);
248 	delay(5000);
249 
250 	typestr = we_params();
251 	if (!typestr)
252 		return(0);
253 
254 	printf("Using %s board, port 0x%x, iomem 0x%x, iosiz %d\n",
255 	       typestr, WD_BASEREG, WD_BASEMEM, dp8390_memsize);
256 
257 	/* get ethernet address */
258 	for(i = 0; i < 6; i++)
259 		eth_myaddr[i] = myadr[i]= inb(WD_BASEREG + WE_PROM + i);
260 
261 	/*
262 	 * Set upper address bits and 8/16 bit access to shared memory.
263 	 */
264 	if (dp8390_is790) {
265 		laar_proto = inb(WD_BASEREG + WE_LAAR) & ~WE_LAAR_M16EN;
266 		outb(WD_BASEREG + WE_LAAR, laar_proto |
267 		     (we_is16bit ? WE_LAAR_M16EN : 0));
268 	} else if ((we_type & WE_SOFTCONFIG) ||
269 		   (we_type == WE_TYPE_WD8013EBT)) {
270 		laar_proto = (WD_BASEMEM >> 19) & WE_LAAR_ADDRHI;
271 		if (we_is16bit)
272 			laar_proto |= WE_LAAR_L16EN;
273 		outb(WD_BASEREG + WE_LAAR, laar_proto |
274 		     (we_is16bit ? WE_LAAR_M16EN : 0));
275 	}
276 
277 	/*
278 	 * Set address and enable interface shared memory.
279 	 */
280 	if (dp8390_is790) {
281 		/* XXX MAGIC CONSTANTS XXX */
282 		x = inb(WD_BASEREG + 0x04);
283 		outb(WD_BASEREG + 0x04, x | 0x80);
284 		outb(WD_BASEREG + 0x0b,
285 		    ((WD_BASEMEM >> 13) & 0x0f) |
286 		    ((WD_BASEMEM >> 11) & 0x40) |
287 		    (inb(WD_BASEREG + 0x0b) & 0xb0));
288 		outb(WD_BASEREG + 0x04, x);
289 		msr_proto = 0x00;
290 		dp8390_cr_proto = 0x00;
291 	} else {
292 		msr_proto = (WD_BASEMEM >> 13) & WE_MSR_ADDR;
293 		dp8390_cr_proto = ED_CR_RD2;
294 	}
295 
296 	outb(WD_BASEREG +  WE_MSR, msr_proto | WE_MSR_MENB);
297 	delay(2);
298 
299 	/*
300 	 * DCR gets:
301 	 *
302 	 *	FIFO threshold to 8, No auto-init Remote DMA,
303 	 *	byte order=80x86.
304 	 *
305 	 * 16-bit cards also get word-wide DMA transfers.
306 	 */
307 	dp8390_dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (we_is16bit ? ED_DCR_WTS : 0);
308 
309 	if (dp8390_config())
310 		return(0);
311 
312 #ifdef _STANDALONE
313 	strncpy(bi_netif.ifname, "we", sizeof(bi_netif.ifname));
314 	bi_netif.bus = BI_BUS_ISA;
315 	bi_netif.addr.iobase = WD_BASEREG;
316 
317 	BI_ADD(&bi_netif, BTINFO_NETIF, sizeof(bi_netif));
318 #endif
319 	return(1);
320 }
321 
322 /*
323  * Stop ethernet board
324  */
325 void
326 EtherStop(void) {
327 	/* stop dp8390, followed by a board reset */
328 	dp8390_stop();
329 	outb(WD_BASEREG + WE_MSR, WE_MSR_RST);
330 	outb(WD_BASEREG + WE_MSR, 0);
331 }
332