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