1/*	$NetBSD: wd80x3.c,v 1.9 2008/04/28 20:23:25 martin 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
76extern int mapio(void);
77#endif
78
79u_char eth_myaddr[6];
80
81static uint8_t we_type;
82static int we_is16bit;
83
84#ifdef _STANDALONE
85static struct btinfo_netif bi_netif;
86#endif
87
88const char *
89we_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
211int
212EtherInit(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 */
317void
318EtherStop(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