if_ed_cbus.c revision 108533
1142425Snectar/*
2142425Snectar * Copyright (c) 1995, David Greenman
3142425Snectar * All rights reserved.
4142425Snectar *
5142425Snectar * Redistribution and use in source and binary forms, with or without
6142425Snectar * modification, are permitted provided that the following conditions
7142425Snectar * are met:
8142425Snectar * 1. Redistributions of source code must retain the above copyright
9142425Snectar *    notice unmodified, this list of conditions, and the following
10142425Snectar *    disclaimer.
11142425Snectar * 2. Redistributions in binary form must reproduce the above copyright
12142425Snectar *    notice, this list of conditions and the following disclaimer in the
13142425Snectar *    documentation and/or other materials provided with the distribution.
14142425Snectar *
15142425Snectar * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16142425Snectar * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17142425Snectar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18142425Snectar * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19142425Snectar * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20142425Snectar * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21142425Snectar * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22142425Snectar * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23142425Snectar * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24142425Snectar * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25142425Snectar * SUCH DAMAGE.
26142425Snectar *
27142425Snectar * $FreeBSD: head/sys/dev/ed/if_ed_cbus.c 108533 2003-01-01 18:49:04Z schweikh $
28142425Snectar */
29142425Snectar
30142425Snectar#include <sys/param.h>
31142425Snectar#include <sys/systm.h>
32142425Snectar#include <sys/socket.h>
33142425Snectar#include <sys/kernel.h>
34238405Sjkim
35142425Snectar#include <sys/module.h>
36142425Snectar#include <sys/bus.h>
37142425Snectar#include <machine/bus.h>
38142425Snectar#ifdef PC98
39160814Ssimon#include <sys/rman.h>
40238405Sjkim#include <machine/resource.h>
41194206Ssimon#include <machine/clock.h>
42238405Sjkim#include <machine/md_var.h>
43142425Snectar#endif
44142425Snectar
45142425Snectar#include <net/ethernet.h>
46142425Snectar#include <net/if.h>
47142425Snectar#include <net/if_arp.h>
48142425Snectar#include <net/if_mib.h>
49142425Snectar
50142425Snectar#include <isa/isavar.h>
51142425Snectar
52142425Snectar#include <dev/ed/if_edvar.h>
53142425Snectar#ifdef PC98
54142425Snectar#include <dev/ed/if_edreg.h>
55160814Ssimon#include <dev/ed/if_ed98.h>
56238405Sjkim
57142425Snectarstatic int ed98_alloc_port	(device_t, int);
58238405Sjkimstatic int ed98_alloc_memory	(device_t, int);
59238405Sjkimstatic int ed_pio_testmem	(struct ed_softc *, int, int, int);
60142425Snectarstatic int ed_probe_SIC98	(device_t, int, int);
61142425Snectarstatic int ed_probe_CNET98	(device_t, int, int);
62142425Snectarstatic int ed_probe_CNET98EL	(device_t, int, int);
63160814Ssimonstatic int ed_probe_NEC77	(device_t, int, int);
64238405Sjkimstatic int ed_probe_NW98X	(device_t, int, int);
65142425Snectarstatic int ed_probe_SB98	(device_t, int, int);
66238405Sjkimstatic int ed_probe_EZ98	(device_t, int, int);
67238405Sjkimstatic int ed98_probe_Novell	(device_t, int, int);
68142425Snectarstatic int ed98_probe_generic8390	(struct ed_softc *);
69142425Snectarstatic void ed_reset_CNET98	(struct ed_softc *, int);
70142425Snectarstatic void ed_winsel_CNET98	(struct ed_softc *, u_short);
71142425Snectarstatic void ed_get_SB98		(struct ed_softc *);
72142425Snectar#endif
73142425Snectar
74142425Snectarstatic int ed_isa_probe		(device_t);
75142425Snectarstatic int ed_isa_attach	(device_t);
76142425Snectar
77142425Snectarstatic struct isa_pnp_id ed_ids[] = {
78142425Snectar#ifdef PC98
79142425Snectar/* TODO - list up PnP boards for PC-98 */
80142425Snectar	{ 0,		NULL }
81142425Snectar#endif
82142425Snectar};
83142425Snectar
84142425Snectarstatic int
85142425Snectared_isa_probe(dev)
86160814Ssimon	device_t dev;
87160814Ssimon{
88160814Ssimon	struct ed_softc *sc = device_get_softc(dev);
89160814Ssimon	int flags = device_get_flags(dev);
90160814Ssimon	int error = 0;
91160814Ssimon
92160814Ssimon	bzero(sc, sizeof(struct ed_softc));
93142425Snectar#ifdef PC98
94142425Snectar	sc->type = ED_TYPE98(flags);
95142425Snectar#ifdef ED_DEBUG
96142425Snectar	device_printf(dev, "ed_isa_probe: sc->type=%x\n", sc->type);
97142425Snectar#endif
98142425Snectar#endif
99142425Snectar
100142425Snectar	/* Check isapnp ids */
101160814Ssimon	error = ISA_PNP_PROBE(device_get_parent(dev), dev, ed_ids);
102160814Ssimon#ifdef ED_DEBUG
103142425Snectar	device_printf(dev, "ed_isa_probe: ISA_PNP_PROBE returns %d\n", error);
104142425Snectar#endif
105142425Snectar
106142425Snectar	/* If the card had a PnP ID that didn't match any we know about */
107142425Snectar	if (error == ENXIO) {
108142425Snectar		goto end;
109160814Ssimon	}
110142425Snectar
111142425Snectar	/* If we had some other problem. */
112142425Snectar	if (!(error == 0 || error == ENOENT)) {
113142425Snectar		goto end;
114142425Snectar	}
115142425Snectar
116142425Snectar	/* Heuristic probes */
117142425Snectar#ifdef ED_DEBUG
118142425Snectar	device_printf(dev, "ed_isa_probe: Heuristic probes start\n");
119142425Snectar#endif
120142425Snectar#ifdef PC98
121142425Snectar	switch (sc->type) {
122142425Snectar	case ED_TYPE98_GENERIC:
123142425Snectar		/*
124142425Snectar		 * CAUTION!
125142425Snectar		 * sc->type of these boards are overwritten by PC/AT's value.
126142425Snectar		 */
127142425Snectar
128142425Snectar		/*
129142425Snectar		 * SMC EtherEZ98
130142425Snectar		 */
131160814Ssimon		error = ed_probe_EZ98(dev, 0, flags);
132160814Ssimon		if (error == 0) {
133160814Ssimon			goto end;
134160814Ssimon		}
135160814Ssimon
136142425Snectar		ed_release_resources(dev);
137142425Snectar
138142425Snectar		/*
139142425Snectar		 * Allied Telesis CenterCom LA-98-T
140238405Sjkim		 */
141142425Snectar		error = ed_probe_Novell(dev, 0, flags);
142142425Snectar		if (error == 0) {
143238405Sjkim			goto end;
144142425Snectar		}
145142425Snectar
146142425Snectar		break;
147142425Snectar
148142425Snectar	/*
149142425Snectar	 * NE2000-like boards probe routine
150142425Snectar	 */
151142425Snectar	case ED_TYPE98_BDN:
152142425Snectar		/*
153142425Snectar		 * ELECOM LANEED LD-BDN
154160814Ssimon		 * PLANET SMART COM 98 EN-2298
155160814Ssimon		 */
156194206Ssimon	case ED_TYPE98_LGY:
157238405Sjkim		/*
158160814Ssimon		 * MELCO LGY-98, IND-SP, IND-SS
159194206Ssimon		 * MACNICA NE2098
160160814Ssimon		 */
161238405Sjkim	case ED_TYPE98_ICM:
162160814Ssimon		/*
163160814Ssimon		 * ICM DT-ET-25, DT-ET-T5, IF-2766ET, IF-2771ET
164238405Sjkim		 * D-Link DE-298P, DE-298
165142425Snectar		 */
166142425Snectar	case ED_TYPE98_EGY:
167142425Snectar		/*
168142425Snectar		 * MELCO EGY-98
169142425Snectar		 * Contec C-NET(98)E-A, C-NET(98)L-A
170142425Snectar		 */
171142425Snectar	case ED_TYPE98_108:
172160814Ssimon		/*
173160814Ssimon		 * NEC PC-9801-107,108
174160814Ssimon		 */
175238405Sjkim	case ED_TYPE98_NC5098:
176238405Sjkim		/*
177238405Sjkim		 * NextCom NC5098
178237657Sjkim		 */
179237657Sjkim
180237657Sjkim		error = ed98_probe_Novell(dev, 0, flags);
181237657Sjkim
182237657Sjkim		break;
183237657Sjkim
184237657Sjkim	/*
185237657Sjkim	 * other boards with special probe routine
186237657Sjkim	 */
187160814Ssimon	case ED_TYPE98_SIC:
188142425Snectar		/*
189160814Ssimon		 * Allied Telesis SIC-98
190160814Ssimon		 */
191238405Sjkim		error = ed_probe_SIC98(dev, 0, flags);
192238405Sjkim
193238405Sjkim		break;
194237657Sjkim
195237657Sjkim	case ED_TYPE98_CNET98EL:
196237657Sjkim		/*
197237657Sjkim		 * Contec C-NET(98)E/L
198237657Sjkim		 */
199237657Sjkim		error = ed_probe_CNET98EL(dev, 0, flags);
200237657Sjkim
201237657Sjkim		break;
202237657Sjkim
203237657Sjkim	case ED_TYPE98_CNET98:
204160814Ssimon		/*
205160814Ssimon		 * Contec C-NET(98)
206160814Ssimon		 */
207238405Sjkim		error = ed_probe_CNET98(dev, 0, flags);
208238405Sjkim
209238405Sjkim		break;
210237657Sjkim
211237657Sjkim	case ED_TYPE98_LA98:
212237657Sjkim		/*
213237657Sjkim		 * IO-DATA LA/T-98
214237657Sjkim		 * NEC PC-9801-77,78
215237657Sjkim		 */
216237657Sjkim		error = ed_probe_NEC77(dev, 0, flags);
217237657Sjkim
218237657Sjkim		break;
219237657Sjkim
220160814Ssimon	case ED_TYPE98_NW98X:
221142425Snectar		/*
222160814Ssimon		 * Networld EC/EP-98X
223160814Ssimon		 */
224238405Sjkim		error = ed_probe_NW98X(dev, 0, flags);
225238405Sjkim
226238405Sjkim		break;
227237657Sjkim
228237657Sjkim	case ED_TYPE98_SB98:
229237657Sjkim		/*
230237657Sjkim		 * Soliton SB-9801
231237657Sjkim		 * Fujikura FN-9801
232237657Sjkim		 */
233237657Sjkim
234237657Sjkim		error = ed_probe_SB98(dev, 0, flags);
235237657Sjkim
236160814Ssimon		break;
237238405Sjkim	}
238238405Sjkim#endif
239238405Sjkim
240238405Sjkimend:
241237657Sjkim#ifdef ED_DEBUG
242237657Sjkim	device_printf(dev, "ed_isa_probe: end, error=%d\n", error);
243238405Sjkim#endif
244238405Sjkim	if (error == 0)
245238405Sjkim		error = ed_alloc_irq(dev, 0, 0);
246238405Sjkim
247238405Sjkim	ed_release_resources(dev);
248238405Sjkim	return (error);
249237657Sjkim}
250238405Sjkim
251238405Sjkimstatic int
252238405Sjkimed_isa_attach(dev)
253238405Sjkim	device_t dev;
254238405Sjkim{
255238405Sjkim	struct ed_softc *sc = device_get_softc(dev);
256238405Sjkim	int flags = device_get_flags(dev);
257194206Ssimon	int error;
258238405Sjkim
259238405Sjkim	if (sc->port_used > 0) {
260238405Sjkim#ifdef PC98
261238405Sjkim		if (ED_TYPE98(flags) == ED_TYPE98_GENERIC) {
262238405Sjkim			ed_alloc_port(dev, sc->port_rid, sc->port_used);
263238405Sjkim		} else {
264237657Sjkim			ed98_alloc_port(dev, sc->port_rid);
265237657Sjkim		}
266237657Sjkim#endif
267238405Sjkim	}
268237657Sjkim	if (sc->mem_used)
269237657Sjkim		ed_alloc_memory(dev, sc->mem_rid, sc->mem_used);
270237657Sjkim
271237657Sjkim	ed_alloc_irq(dev, sc->irq_rid, 0);
272237657Sjkim
273160814Ssimon	error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET,
274160814Ssimon			       edintr, sc, &sc->irq_handle);
275160814Ssimon	if (error) {
276238405Sjkim		ed_release_resources(dev);
277238405Sjkim		return (error);
278238405Sjkim	}
279237657Sjkim
280237657Sjkim	return ed_attach(sc, device_get_unit(dev), flags);
281237657Sjkim}
282237657Sjkim
283237657Sjkim#ifdef PC98
284237657Sjkim/*
285237657Sjkim * Interrupt conversion table for EtherEZ98
286237657Sjkim */
287237657Sjkimstatic unsigned short ed_EZ98_intr_val[] = {
288160814Ssimon	0,
289160814Ssimon	3,
290160814Ssimon	5,
291238405Sjkim	6,
292238405Sjkim	0,
293238405Sjkim	9,
294237657Sjkim	12,
295237657Sjkim	13
296237657Sjkim};
297237657Sjkim
298237657Sjkimstatic int
299237657Sjkimed_probe_EZ98(dev, port_rid, flags)
300237657Sjkim	device_t dev;
301237657Sjkim	int port_rid;
302237657Sjkim	int flags;
303237657Sjkim{
304160814Ssimon	struct ed_softc *sc = device_get_softc(dev);
305160814Ssimon	int error;
306160814Ssimon	static unsigned short *intr_vals[] = {NULL, ed_EZ98_intr_val};
307238405Sjkim
308238405Sjkim	error = ed_alloc_port(dev, port_rid, ED_EZ98_IO_PORTS);
309238405Sjkim	if (error) {
310237657Sjkim		return (error);
311237657Sjkim	}
312237657Sjkim
313237657Sjkim	sc->asic_offset = ED_EZ98_ASIC_OFFSET;
314237657Sjkim	sc->nic_offset  = ED_EZ98_NIC_OFFSET;
315237657Sjkim
316237657Sjkim	return ed_probe_WD80x3_generic(dev, flags, intr_vals);
317237657Sjkim}
318237657Sjkim
319237657Sjkim/*
320160814Ssimon * I/O conversion tables
321142425Snectar */
322160814Ssimon
323160814Ssimon/* LGY-98, ICM, C-NET(98)E/L */
324238405Sjkimstatic	bus_addr_t ed98_ioaddr_generic[] = {
325238405Sjkim	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
326238405Sjkim};
327237657Sjkim
328237657Sjkim/*
329237657Sjkim *		Definitions for Contec C-NET(98)E/L
330237657Sjkim */
331237657Sjkim#define	ED_CNET98EL_ICR         2	/* Interrupt Configuration Register */
332237657Sjkim
333237657Sjkim#define	ED_CNET98EL_ICR_IRQ3	0x01
334237657Sjkim#define	ED_CNET98EL_ICR_IRQ5	0x02
335237657Sjkim#define	ED_CNET98EL_ICR_IRQ6	0x04
336160814Ssimon#define	ED_CNET98EL_ICR_IRQ12	0x20
337142425Snectar
338160814Ssimon#define	ED_CNET98EL_IMR         4	/* Interrupt Mask Register	*/
339142425Snectar#define	ED_CNET98EL_ISR         5	/* Interrupt Status Register	*/
340238405Sjkim
341238405Sjkim/* EGY-98 */
342238405Sjkimstatic	bus_addr_t ed98_ioaddr_egy98[] = {
343237657Sjkim	0,     0x02,  0x04,  0x06,  0x08,  0x0a,  0x0c,  0x0e,
344237657Sjkim	0x100, 0x102, 0x104, 0x106, 0x108, 0x10a, 0x10c, 0x10e
345237657Sjkim};
346237657Sjkim
347237657Sjkim/* SIC-98 */
348237657Sjkimstatic	bus_addr_t ed98_ioaddr_sic98[] = {
349237657Sjkim	0x0000, 0x0200, 0x0400, 0x0600, 0x0800, 0x0a00, 0x0c00, 0x0e00,
350237657Sjkim	0x1000, 0x1200, 0x1400, 0x1600, 0x1800, 0x1a00, 0x1c00, 0x1e00
351237657Sjkim};
352160814Ssimon
353142425Snectar/* LA/T-98, LD-BDN, PC-9801-77, SB-9801 */
354160814Ssimonstatic	bus_addr_t ed98_ioaddr_la98[] = {
355160814Ssimon	0x0000, 0x1000, 0x2000, 0x3000, 0x4000, 0x5000, 0x6000, 0x7000,
356160814Ssimon	0x8000, 0x9000, 0xa000, 0xb000, 0xc000, 0xd000, 0xe000, 0xf000,
357238405Sjkim	0x0100	/* for NEC 77(see below) */
358238405Sjkim};
359238405Sjkim
360237657Sjkim/*
361237657Sjkim *		Definitions for NEC PC-9801-77
362237657Sjkim */
363237657Sjkim#define	ED_NEC77_IRQ		16	/* Interrupt Configuration Register */
364237657Sjkim
365237657Sjkim#define	ED_NEC77_IRQ3		0x04
366237657Sjkim#define	ED_NEC77_IRQ5		0x06
367238405Sjkim#define	ED_NEC77_IRQ6		0x08
368238405Sjkim#define	ED_NEC77_IRQ12		0x0a
369238405Sjkim#define	ED_NEC77_IRQ13		0x02
370238405Sjkim
371160814Ssimon/*
372160814Ssimon *		Definitions for Soliton SB-9801
373160814Ssimon */
374238405Sjkim#define	ED_SB98_CFG		1	/* Board configuration		*/
375238405Sjkim
376238405Sjkim#define	ED_SB98_CFG_IRQ3	0x00
377237657Sjkim#define	ED_SB98_CFG_IRQ5	0x04
378237657Sjkim#define	ED_SB98_CFG_IRQ6	0x08
379237657Sjkim#define	ED_SB98_CFG_IRQ12	0x0c
380237657Sjkim#define	ED_SB98_CFG_ALTPORT	0x40		/* use EXTERNAL media	*/
381237657Sjkim#define	ED_SB98_CFG_ENABLE	0xa0		/* enable configuration	*/
382237657Sjkim
383237657Sjkim#define	ED_SB98_EEPENA		2	/* EEPROM access enable		*/
384237657Sjkim
385237657Sjkim#define	ED_SB98_EEPENA_DISABLE	0x00
386160814Ssimon#define	ED_SB98_EEPENA_ENABLE	0x01
387160814Ssimon
388160814Ssimon#define	ED_SB98_EEP		3	/* EEPROM access		*/
389160814Ssimon
390238405Sjkim#define	ED_SB98_EEP_SDA		0x01		/* Serial Data	*/
391238405Sjkim#define	ED_SB98_EEP_SCL		0x02		/* Serial Clock	*/
392238405Sjkim#define	ED_SB98_EEP_READ	0x01		/* Read Command	*/
393237657Sjkim
394237657Sjkim#define	ED_SB98_EEP_DELAY	300
395237657Sjkim
396237657Sjkim#define	ED_SB98_ADDRESS		0x01		/* Station Address(1-6)	*/
397237657Sjkim
398237657Sjkim#define	ED_SB98_POLARITY	4	/* Polarity			*/
399237657Sjkim
400237657Sjkim/* PC-9801-108 */
401237657Sjkimstatic	bus_addr_t ed98_ioaddr_nec108[] = {
402160814Ssimon	0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
403238405Sjkim	0x1000, 0x1002, 0x1004, 0x1006, 0x1008, 0x100a, 0x100c, 0x100e
404238405Sjkim};
405238405Sjkim
406238405Sjkim/* C-NET(98) */
407237657Sjkimstatic	bus_addr_t ed98_ioaddr_cnet98[] = {
408238405Sjkim	0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
409238405Sjkim	0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e
410238405Sjkim};
411238405Sjkim
412238405Sjkim/*
413238405Sjkim *		Definitions for Contec C-NET(98)
414238405Sjkim */
415238405Sjkim#define	ED_CNET98_MAP_REG0L	0	/* MAPPING register0 Low	*/
416238405Sjkim#define	ED_CNET98_MAP_REG1L	1	/* MAPPING register1 Low	*/
417238405Sjkim#define	ED_CNET98_MAP_REG2L	2	/* MAPPING register2 Low	*/
418160814Ssimon#define	ED_CNET98_MAP_REG3L	3	/* MAPPING register3 Low	*/
419238405Sjkim#define	ED_CNET98_MAP_REG0H	4	/* MAPPING register0 Hi		*/
420238405Sjkim#define	ED_CNET98_MAP_REG1H	5	/* MAPPING register1 Hi		*/
421238405Sjkim#define	ED_CNET98_MAP_REG2H	6	/* MAPPING register2 Hi		*/
422238405Sjkim#define	ED_CNET98_MAP_REG3H	7	/* MAPPING register3 Hi		*/
423237657Sjkim#define	ED_CNET98_WIN_REG	8	/* Window register		*/
424237657Sjkim#define	ED_CNET98_INT_LEV	9	/* Init level register		*/
425238405Sjkim
426238405Sjkim#define	ED_CNET98_INT_IRQ3	0x01		/* INT 0 */
427238405Sjkim#define	ED_CNET98_INT_IRQ5	0x02		/* INT 1 */
428238405Sjkim#define	ED_CNET98_INT_IRQ6	0x04		/* INT 2 */
429238405Sjkim#define	ED_CNET98_INT_IRQ9	0x08		/* INT 3 */
430238405Sjkim#define	ED_CNET98_INT_IRQ12	0x20		/* INT 5 */
431237657Sjkim#define	ED_CNET98_INT_IRQ13	0x40		/* INT 6 */
432238405Sjkim
433238405Sjkim#define	ED_CNET98_INT_REQ	10	/* Init request register	*/
434238405Sjkim#define	ED_CNET98_INT_MASK	11	/* Init mask register		*/
435238405Sjkim#define	ED_CNET98_INT_STAT	12	/* Init status register		*/
436238405Sjkim#define	ED_CNET98_INT_CLR	12	/* Init clear register		*/
437238405Sjkim#define	ED_CNET98_RESERVE1	13
438238405Sjkim#define	ED_CNET98_RESERVE2	14
439160814Ssimon#define	ED_CNET98_RESERVE3	15
440238405Sjkim
441238405Sjkim/* EC/EP-98X, NC5098 */
442238405Sjkimstatic	bus_addr_t ed98_ioaddr_nw98x[] = {
443238405Sjkim	0x0000, 0x0100, 0x0200, 0x0300, 0x0400, 0x0500, 0x0600, 0x0700,
444237657Sjkim	0x0800, 0x0900, 0x0a00, 0x0b00, 0x0c00, 0x0d00, 0x0e00, 0x0f00,
445237657Sjkim	0x1000	/* for EC/EP-98X(see below) */
446238405Sjkim};
447238405Sjkim
448238405Sjkim/*
449238405Sjkim *		Definitions for Networld EC/EP-98X
450238405Sjkim */
451238405Sjkim#define	ED_NW98X_IRQ            16	/* Interrupt Configuration Register */
452237657Sjkim
453238405Sjkim#define	ED_NW98X_IRQ3           0x04
454238405Sjkim#define	ED_NW98X_IRQ5           0x06
455238405Sjkim#define	ED_NW98X_IRQ6           0x08
456238405Sjkim#define	ED_NW98X_IRQ12          0x0a
457238405Sjkim#define	ED_NW98X_IRQ13          0x02
458238405Sjkim
459238405Sjkim/* NC5098 ASIC */
460160814Ssimonstatic bus_addr_t ed98_asic_nc5098[] = {
461142425Snectar/*	DATA    ENADDR						RESET	*/
462160814Ssimon	0x0000, 0x2000, 0x2100, 0x2200, 0x2300, 0x2400, 0x2500, 0x4000,
463160814Ssimon	     0,      0,      0,      0,      0,      0,      0,      0
464160814Ssimon};
465238405Sjkim
466238405Sjkim/*
467238405Sjkim *		Definitions for NextCom NC5098
468237657Sjkim */
469237657Sjkim#define	ED_NC5098_ENADDR	1	/* Station Address(1-6)		*/
470237657Sjkim
471237657Sjkim/*
472237657Sjkim * Allocate a port resource with the given resource id.
473237657Sjkim */
474237657Sjkimstatic int
475238405Sjkimed98_alloc_port(dev, rid)
476238405Sjkim	device_t dev;
477238405Sjkim	int rid;
478238405Sjkim{
479160814Ssimon	struct ed_softc *sc = device_get_softc(dev);
480142425Snectar	struct resource *res;
481160814Ssimon	int error;
482142425Snectar	bus_addr_t *io_nic, *io_asic, adj;
483238405Sjkim	static bus_addr_t io_res[ED_NOVELL_IO_PORTS + 1];
484238405Sjkim	int i, n;
485238405Sjkim	int offset, reset, data;
486237657Sjkim
487237657Sjkim	/* Set i/o table for resource manager */
488237657Sjkim	io_nic = io_asic = ed98_ioaddr_generic;
489237657Sjkim	offset = ED_NOVELL_ASIC_OFFSET;
490237657Sjkim	reset = ED_NOVELL_RESET;
491237657Sjkim	data  = ED_NOVELL_DATA;
492237657Sjkim	n = ED_NOVELL_IO_PORTS;
493237657Sjkim
494237657Sjkim	switch (sc->type) {
495237657Sjkim	case ED_TYPE98_LGY:
496238405Sjkim		io_asic = ed98_ioaddr_egy98; /* XXX - Yes, we use egy98 */
497238405Sjkim		offset = 0x0200;
498238405Sjkim		reset = 8;
499238405Sjkim		break;
500238405Sjkim
501238405Sjkim	case ED_TYPE98_EGY:
502238405Sjkim		io_nic = io_asic = ed98_ioaddr_egy98;
503238405Sjkim		offset = 0x0200;
504238405Sjkim		reset = 8;
505238405Sjkim		break;
506238405Sjkim
507238405Sjkim	case ED_TYPE98_ICM:
508238405Sjkim		offset = 0x0100;
509238405Sjkim		break;
510238405Sjkim
511238405Sjkim	case ED_TYPE98_BDN:
512160814Ssimon		io_nic = io_asic = ed98_ioaddr_la98;
513142425Snectar		offset = 0x0100;
514160814Ssimon		reset = 0x0c;
515160814Ssimon		break;
516160814Ssimon
517238405Sjkim	case ED_TYPE98_SIC:
518238405Sjkim		io_nic = io_asic = ed98_ioaddr_sic98;
519238405Sjkim		offset = 0x2000;
520237657Sjkim		n = 16+1;
521237657Sjkim		break;
522237657Sjkim
523237657Sjkim	case ED_TYPE98_108:
524237657Sjkim		io_nic = io_asic = ed98_ioaddr_nec108;
525237657Sjkim		offset = 0x0888;	/* XXX - overwritten after */
526237657Sjkim		reset = 1;
527238405Sjkim		n = 16;	/* XXX - does not set ASIC i/o here */
528238405Sjkim		break;
529238405Sjkim
530238405Sjkim	case ED_TYPE98_LA98:
531160814Ssimon		io_nic = io_asic = ed98_ioaddr_la98;
532160814Ssimon		offset = 0x0100;
533160814Ssimon		break;
534238405Sjkim
535238405Sjkim	case ED_TYPE98_CNET98EL:
536238405Sjkim		offset = 0x0400;
537237657Sjkim		data = 0x0e;
538237657Sjkim		break;
539237657Sjkim
540237657Sjkim	case ED_TYPE98_CNET98:
541237657Sjkim		/* XXX - Yes, we use generic i/o here */
542237657Sjkim		offset = 0x0400;
543237657Sjkim		break;
544237657Sjkim
545237657Sjkim	case ED_TYPE98_NW98X:
546160814Ssimon		io_nic = io_asic = ed98_ioaddr_nw98x;
547142425Snectar		offset = 0x1000;
548160814Ssimon		break;
549160814Ssimon
550160814Ssimon	case ED_TYPE98_SB98:
551238405Sjkim		io_nic = io_asic = ed98_ioaddr_la98;
552238405Sjkim		offset = 0x0400;
553238405Sjkim		reset = 7;
554237657Sjkim		break;
555237657Sjkim
556237657Sjkim	case ED_TYPE98_NC5098:
557237657Sjkim		io_nic  = ed98_ioaddr_nw98x;
558237657Sjkim		io_asic = ed98_asic_nc5098;
559238405Sjkim		offset = 0x2000;
560238405Sjkim		reset = 7;
561238405Sjkim		n = 16+8;	/* XXX */
562237657Sjkim		break;
563237657Sjkim	}
564237657Sjkim
565237657Sjkim	bcopy(io_nic, io_res, sizeof(io_nic[0]) * ED_NOVELL_ASIC_OFFSET);
566237657Sjkim	for (i = ED_NOVELL_ASIC_OFFSET; i < ED_NOVELL_IO_PORTS; i++) {
567160814Ssimon		io_res[i] = io_asic[i - ED_NOVELL_ASIC_OFFSET] + offset;
568238405Sjkim	}
569238405Sjkim
570238405Sjkim	res = isa_alloc_resourcev(dev, SYS_RES_IOPORT, &rid,
571238405Sjkim				  io_res, n, RF_ACTIVE);
572237657Sjkim	if (!res) {
573237657Sjkim		return (ENOENT);
574238405Sjkim	}
575238405Sjkim
576238405Sjkim	sc->port_rid = rid;
577238405Sjkim	sc->port_res = res;
578238405Sjkim	sc->port_used = n;
579238405Sjkim
580279264Sdelphij	/* Re-map i/o table if needed */
581279264Sdelphij	switch (sc->type) {
582279264Sdelphij	case ED_TYPE98_LA98:
583279264Sdelphij	case ED_TYPE98_NW98X:
584279264Sdelphij		io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset;
585279264Sdelphij		n++;
586279264Sdelphij		break;
587279264Sdelphij
588279264Sdelphij	case ED_TYPE98_108:
589160814Ssimon		adj = (rman_get_start(res) & 0xf000) / 2;
590160814Ssimon		offset = (offset | adj) - rman_get_start(res);
591142425Snectar
592160814Ssimon		for (n = ED_NOVELL_ASIC_OFFSET; n < ED_NOVELL_IO_PORTS; n++) {
593238405Sjkim			io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset;
594238405Sjkim		}
595238405Sjkim		break;
596237657Sjkim
597237657Sjkim	case ED_TYPE98_CNET98:
598237657Sjkim		io_nic = io_asic = ed98_ioaddr_cnet98;
599237657Sjkim		offset = 1;
600237657Sjkim
601237657Sjkim		bcopy(io_nic, io_res, sizeof(io_nic[0]) * ED_NOVELL_ASIC_OFFSET);
602237657Sjkim		for (n = ED_NOVELL_ASIC_OFFSET; n < ED_NOVELL_IO_PORTS; n++) {
603237657Sjkim			io_res[n] = io_asic[n - ED_NOVELL_ASIC_OFFSET] + offset;
604237657Sjkim		}
605237657Sjkim		break;
606237657Sjkim
607160814Ssimon	case ED_TYPE98_NC5098:
608160814Ssimon		n = ED_NOVELL_IO_PORTS;
609160814Ssimon		break;
610238405Sjkim	}
611238405Sjkim
612238405Sjkim	if (reset != ED_NOVELL_RESET) {
613237657Sjkim		io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_RESET] =
614237657Sjkim			io_res[ED_NOVELL_ASIC_OFFSET + reset];
615237657Sjkim	}
616237657Sjkim	if (data  != ED_NOVELL_DATA) {
617237657Sjkim		io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_DATA] =
618237657Sjkim			io_res[ED_NOVELL_ASIC_OFFSET + data];
619237657Sjkim#if 0
620237657Sjkim		io_res[ED_NOVELL_ASIC_OFFSET + ED_NOVELL_DATA + 1] =
621237657Sjkim			io_res[ED_NOVELL_ASIC_OFFSET + data + 1];
622237657Sjkim#endif
623160814Ssimon	}
624160814Ssimon
625160814Ssimon	error = isa_load_resourcev(res, io_res, n);
626238405Sjkim	if (error != 0) {
627238405Sjkim		return (ENOENT);
628238405Sjkim	}
629237657Sjkim#ifdef ED_DEBUG
630237657Sjkim	device_printf(dev, "ed98_alloc_port: i/o ports = %d\n", n);
631237657Sjkim	for (i = 0; i < n; i++) {
632237657Sjkim		printf("%x,", io_res[i]);
633237657Sjkim	}
634237657Sjkim	printf("\n");
635237657Sjkim#endif
636237657Sjkim	return (0);
637237657Sjkim}
638237657Sjkim
639160814Ssimonstatic int
640160814Ssimoned98_alloc_memory(dev, rid)
641160814Ssimon	device_t dev;
642238405Sjkim	int rid;
643238405Sjkim{
644238405Sjkim	struct ed_softc *sc = device_get_softc(dev);
645237657Sjkim	int error;
646237657Sjkim	u_long conf_maddr, conf_msize;
647237657Sjkim
648237657Sjkim	error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
649237657Sjkim				 &conf_maddr, &conf_msize);
650237657Sjkim	if (error) {
651237657Sjkim		return (error);
652237657Sjkim	}
653237657Sjkim
654237657Sjkim	if ((conf_maddr == 0) || (conf_msize == 0)) {
655238405Sjkim		return (ENXIO);
656238405Sjkim	}
657238405Sjkim
658238405Sjkim	error = ed_alloc_memory(dev, rid, (int) conf_msize);
659238405Sjkim	if (error) {
660238405Sjkim		return (error);
661238405Sjkim	}
662238405Sjkim
663238405Sjkim	sc->mem_start = (caddr_t) rman_get_virtual(sc->mem_res);
664238405Sjkim	sc->mem_size  = conf_msize;
665238405Sjkim
666238405Sjkim	return (0);
667238405Sjkim}
668238405Sjkim
669238405Sjkim/*
670238405Sjkim * Generic probe routine for testing for the existance of a DS8390.
671238405Sjkim *	Must be called after the NIC has just been reset. This routine
672238405Sjkim *	works by looking at certain register values that are guaranteed
673238405Sjkim *	to be initialized a certain way after power-up or reset. Seems
674238405Sjkim *	not to currently work on the 83C690.
675238405Sjkim *
676238405Sjkim * Specifically:
677238405Sjkim *
678238405Sjkim *	Register			reset bits	set bits
679238405Sjkim *	Command Register (CR)		TXP, STA	RD2, STP
680238405Sjkim *	Interrupt Status (ISR)				RST
681238405Sjkim *	Interrupt Mask (IMR)		All bits
682238405Sjkim *	Data Control (DCR)				LAS
683238405Sjkim *	Transmit Config. (TCR)		LB1, LB0
684238405Sjkim *
685238405Sjkim * XXX - We only check the CR register.
686238405Sjkim *
687238405Sjkim * Return 1 if 8390 was found, 0 if not.
688238405Sjkim */
689238405Sjkim
690238405Sjkimstatic int
691238405Sjkimed98_probe_generic8390(sc)
692238405Sjkim	struct ed_softc *sc;
693238405Sjkim{
694238405Sjkim	u_char tmp = ed_nic_inb(sc, ED_P0_CR);
695238405Sjkim#ifdef DIAGNOSTIC
696238405Sjkim	printf("ed?: inb(ED_P0_CR)=%x\n", tmp);
697238405Sjkim#endif
698238405Sjkim	if ((tmp & (ED_CR_RD2 | ED_CR_TXP | ED_CR_STA | ED_CR_STP)) !=
699238405Sjkim	    (ED_CR_RD2 | ED_CR_STP)) {
700238405Sjkim		return (0);
701238405Sjkim	}
702160814Ssimon
703142425Snectar	(void) ed_nic_inb(sc, ED_P0_ISR);
704160814Ssimon
705160814Ssimon	return (1);
706238405Sjkim}
707238405Sjkim
708237657Sjkimstatic int
709237657Sjkimed98_probe_Novell(dev, port_rid, flags)
710237657Sjkim	device_t dev;
711237657Sjkim	int port_rid;
712237657Sjkim	int flags;
713237657Sjkim{
714237657Sjkim	struct ed_softc *sc = device_get_softc(dev);
715237657Sjkim	int error;
716237657Sjkim	int n;
717160814Ssimon	u_char romdata[ETHER_ADDR_LEN * 2], tmp;
718160814Ssimon
719160814Ssimon#ifdef ED_DEBUG
720238405Sjkim	device_printf(dev, "ed98_probe_Novell: start\n");
721238405Sjkim#endif
722238405Sjkim	error = ed98_alloc_port(dev, port_rid);
723237657Sjkim	if (error) {
724237657Sjkim		return (error);
725237657Sjkim	}
726237657Sjkim
727237657Sjkim	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
728237657Sjkim	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
729237657Sjkim
730237657Sjkim	/* Reset the board */
731237657Sjkim#ifdef ED_DEBUG
732160814Ssimon	device_printf(dev, "ed98_probe_Novell: reset\n");
733160814Ssimon#endif
734142425Snectar	switch (sc->type) {
735142425Snectar#if 1	/* XXX - I'm not sure this is really necessary... */
736160814Ssimon	case ED_TYPE98_BDN:
737238405Sjkim		tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
738238405Sjkim		ed_asic_outb(sc, ED_NOVELL_RESET, (tmp & 0xf0) | 0x08);
739238405Sjkim		ed_nic_outb(sc, 0x04, tmp);
740237657Sjkim		(void) ed_asic_inb(sc, 0x08);
741237657Sjkim		ed_asic_outb(sc, 0x08, tmp);
742237657Sjkim		ed_asic_outb(sc, 0x08, tmp & 0x7f);
743237657Sjkim		break;
744237657Sjkim#endif
745237657Sjkim	case ED_TYPE98_NC5098:
746237657Sjkim		ed_asic_outb(sc, ED_NOVELL_RESET, 0x00);
747238405Sjkim		DELAY(5000);
748238405Sjkim		ed_asic_outb(sc, ED_NOVELL_RESET, 0x01);
749238405Sjkim		break;
750160814Ssimon
751142425Snectar	default:
752160814Ssimon		tmp = ed_asic_inb(sc, ED_NOVELL_RESET);
753160814Ssimon
754238405Sjkim	/*
755238405Sjkim	 * I don't know if this is necessary; probably cruft leftover from
756238405Sjkim	 * Clarkson packet driver code. Doesn't do a thing on the boards I've
757237657Sjkim	 * tested. -DG [note that an outb(0x84, 0) seems to work here, and is
758237657Sjkim	 * non-invasive...but some boards don't seem to reset and I don't have
759237657Sjkim	 * complete documentation on what the 'right' thing to do is...so we
760237657Sjkim	 * do the invasive thing for now. Yuck.]
761237657Sjkim	 */
762237657Sjkim		ed_asic_outb(sc, ED_NOVELL_RESET, tmp);
763237657Sjkim		break;
764237657Sjkim	}
765237657Sjkim	DELAY(5000);
766160814Ssimon
767160814Ssimon	/*
768160814Ssimon	 * This is needed because some NE clones apparently don't reset the
769238405Sjkim	 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
770238405Sjkim	 * - this makes the probe invasive! ...Done against my better
771238405Sjkim	 * judgement. -DLG
772237657Sjkim	 */
773237657Sjkim	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
774237657Sjkim	DELAY(5000);
775237657Sjkim
776237657Sjkim	/* Make sure that we really have an 8390 based board */
777237657Sjkim	if (!ed98_probe_generic8390(sc)) {
778237657Sjkim		return (ENXIO);
779237657Sjkim	}
780237657Sjkim
781237657Sjkim	/* Test memory via PIO */
782160814Ssimon#ifdef ED_DEBUG
783238405Sjkim	device_printf(dev, "ed98_probe_Novell: test memory\n");
784238405Sjkim#endif
785238405Sjkim	sc->cr_proto = ED_CR_RD2;
786238405Sjkim	if (!ed_pio_testmem(sc,  8192, 0, flags)
787237657Sjkim	&&  !ed_pio_testmem(sc, 16384, 1, flags)) {
788237657Sjkim		return (ENXIO);
789238405Sjkim	}
790238405Sjkim
791238405Sjkim	/* Setup the board type */
792238405Sjkim#ifdef ED_DEBUG
793238405Sjkim	device_printf(dev, "ed98_probe_Novell: board type\n");
794238405Sjkim#endif
795237657Sjkim	switch (sc->type) {
796237657Sjkim	case ED_TYPE98_BDN:
797238405Sjkim		sc->type_str = "LD-BDN";
798238405Sjkim		break;
799238405Sjkim	case ED_TYPE98_EGY:
800238405Sjkim		sc->type_str = "EGY-98";
801238405Sjkim		break;
802238405Sjkim	case ED_TYPE98_LGY:
803238405Sjkim		sc->type_str = "LGY-98";
804160814Ssimon		break;
805142425Snectar	case ED_TYPE98_ICM:
806160814Ssimon		sc->type_str = "ICM";
807160814Ssimon		break;
808160814Ssimon	case ED_TYPE98_108:
809238405Sjkim		sc->type_str = "PC-9801-108";
810238405Sjkim		break;
811238405Sjkim	case ED_TYPE98_LA98:
812237657Sjkim		sc->type_str = "LA-98";
813237657Sjkim		break;
814237657Sjkim	case ED_TYPE98_NW98X:
815237657Sjkim		sc->type_str = "NW98X";
816237657Sjkim		break;
817238405Sjkim	case ED_TYPE98_NC5098:
818238405Sjkim		sc->type_str = "NC5098";
819238405Sjkim		break;
820238405Sjkim	default:
821238405Sjkim		sc->type_str = NULL;
822238405Sjkim		break;
823238405Sjkim	}
824238405Sjkim
825238405Sjkim	/* Get station address */
826238405Sjkim	switch (sc->type) {
827160814Ssimon	case ED_TYPE98_NC5098:
828142425Snectar		for (n = 0; n < ETHER_ADDR_LEN; n++) {
829160814Ssimon			sc->arpcom.ac_enaddr[n] =
830160814Ssimon				ed_asic_inb(sc, ED_NC5098_ENADDR + n);
831160814Ssimon		}
832160814Ssimon		break;
833238405Sjkim
834238405Sjkim	default:
835238405Sjkim		ed_pio_readmem(sc, 0, romdata, sizeof(romdata));
836237657Sjkim		for (n = 0; n < ETHER_ADDR_LEN; n++) {
837237657Sjkim			sc->arpcom.ac_enaddr[n] =
838237657Sjkim				romdata[n * (sc->isa16bit + 1)];
839237657Sjkim		}
840237657Sjkim		break;
841238405Sjkim	}
842238405Sjkim
843238405Sjkim	/* clear any pending interrupts that might have occurred above */
844238405Sjkim	ed_nic_outb(sc, ED_P0_ISR, 0xff);
845238405Sjkim
846238405Sjkim	return (0);
847238405Sjkim}
848237657Sjkim
849237657Sjkim/*
850237657Sjkim * Probe and vendor-specific initialization routine for SIC-98 boards
851237657Sjkim */
852205128Ssimonstatic int
853238405Sjkimed_probe_SIC98(dev, port_rid, flags)
854238405Sjkim	device_t dev;
855238405Sjkim	int port_rid;
856238405Sjkim	int flags;
857238405Sjkim{
858237657Sjkim	struct ed_softc *sc = device_get_softc(dev);
859238405Sjkim	int error;
860238405Sjkim	int i;
861238405Sjkim	u_char sum;
862238405Sjkim
863238405Sjkim	/*
864238405Sjkim	 * Setup card RAM and I/O address
865237657Sjkim	 * Kernel Virtual to segment C0000-DFFFF????
866238405Sjkim	 */
867238405Sjkim	error = ed98_alloc_port(dev, port_rid);
868238405Sjkim	if (error) {
869238405Sjkim		return (error);
870238405Sjkim	}
871238405Sjkim
872238405Sjkim	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
873160814Ssimon	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
874238405Sjkim
875238405Sjkim	error = ed98_alloc_memory(dev, 0);
876238405Sjkim	if (error) {
877238405Sjkim		return (error);
878237657Sjkim	}
879237657Sjkim
880238405Sjkim	/* Reset card to force it into a known state. */
881238405Sjkim	ed_asic_outb(sc, 0, 0x00);
882238405Sjkim	DELAY(100);
883238405Sjkim	if (ED_TYPE98SUB(flags) == 0) {
884238405Sjkim		/* SIC-98/SIU-98 */
885238405Sjkim		ed_asic_outb(sc, 0, 0x94);
886237657Sjkim		DELAY(100);
887238405Sjkim		ed_asic_outb(sc, 0, 0x94);
888238405Sjkim	} else {
889238405Sjkim		/* SIU-98-D */
890238405Sjkim		ed_asic_outb(sc, 0, 0x80);
891238405Sjkim		DELAY(100);
892238405Sjkim		ed_asic_outb(sc, 0, 0x94);
893238405Sjkim		DELAY(100);
894160814Ssimon		ed_asic_outb(sc, 0, 0x9e);
895238405Sjkim	}
896238405Sjkim	DELAY(100);
897238405Sjkim
898238405Sjkim	/*
899237657Sjkim	 * Here we check the card ROM, if the checksum passes, and the
900237657Sjkim	 * type code and ethernet address check out, then we know we have
901238405Sjkim	 * an SIC card.
902238405Sjkim	 */
903238405Sjkim	sum = sc->mem_start[6 * 2];
904238405Sjkim	for (i = 0; i < ETHER_ADDR_LEN; i++) {
905238405Sjkim		sum ^= (sc->arpcom.ac_enaddr[i] = sc->mem_start[i * 2]);
906238405Sjkim	}
907237657Sjkim#ifdef ED_DEBUG
908238405Sjkim	device_printf(dev, "ed_probe_sic98: got address %6D\n",
909238405Sjkim		      sc->arpcom.ac_enaddr, ":");
910238405Sjkim#endif
911238405Sjkim	if (sum != 0) {
912238405Sjkim		return (ENXIO);
913238405Sjkim	}
914238405Sjkim	if ((sc->arpcom.ac_enaddr[0] | sc->arpcom.ac_enaddr[1] |
915160814Ssimon	     sc->arpcom.ac_enaddr[2]) == 0) {
916160814Ssimon		return (ENXIO);
917160814Ssimon	}
918238405Sjkim
919238405Sjkim	sc->vendor   = ED_VENDOR_MISC;
920238405Sjkim	sc->type_str = "SIC98";
921237657Sjkim	sc->isa16bit = 1;
922237657Sjkim	sc->cr_proto = 0;
923237657Sjkim
924237657Sjkim	/*
925237657Sjkim	 * SIC RAM page 0x0000-0x3fff(or 0x7fff)
926237657Sjkim	 */
927237657Sjkim	if (ED_TYPE98SUB(flags) == 0) {
928237657Sjkim		ed_asic_outb(sc, 0, 0x90);
929237657Sjkim	} else {
930237657Sjkim		ed_asic_outb(sc, 0, 0x8e);
931142425Snectar	}
932142425Snectar	DELAY(100);
933142425Snectar
934238405Sjkim	/*
935238405Sjkim	 * clear interface memory, then sum to make sure its valid
936238405Sjkim	 */
937238405Sjkim	bzero(sc->mem_start, sc->mem_size);
938238405Sjkim
939237657Sjkim	for (i = 0; i < sc->mem_size; i++) {
940237657Sjkim		if (sc->mem_start[i]) {
941238405Sjkim			device_printf(dev, "failed to clear shared memory "
942238405Sjkim				"at %lx - check configuration\n",
943238405Sjkim				kvtop(sc->mem_start + i));
944238405Sjkim
945237657Sjkim			return (ENXIO);
946237657Sjkim		}
947237657Sjkim	}
948237657Sjkim
949237657Sjkim	sc->mem_shared = 1;
950237657Sjkim	sc->mem_end = sc->mem_start + sc->mem_size;
951238405Sjkim
952238405Sjkim	/*
953238405Sjkim	 * allocate one xmit buffer if < 16k, two buffers otherwise
954238405Sjkim	 */
955237657Sjkim	if ((sc->mem_size < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) {
956237657Sjkim		sc->txb_cnt = 1;
957160814Ssimon	} else {
958160814Ssimon		sc->txb_cnt = 2;
959160814Ssimon	}
960238405Sjkim	sc->tx_page_start = 0;
961238405Sjkim
962238405Sjkim	sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE * sc->txb_cnt;
963237657Sjkim	sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE;
964237657Sjkim
965237657Sjkim	sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
966237657Sjkim
967237657Sjkim	return (0);
968237657Sjkim}
969237657Sjkim
970237657Sjkim/*
971237657Sjkim * Contec C-NET(98) series support routines
972237657Sjkim */
973238405Sjkimstatic void
974238405Sjkimed_reset_CNET98(sc, flags)
975238405Sjkim	struct ed_softc *sc;
976238405Sjkim	int flags;
977238405Sjkim{
978238405Sjkim	u_short	init_addr = ED_CNET98_INIT;
979238405Sjkim	u_char tmp;
980238405Sjkim
981238405Sjkim	/* Choose initial register address */
982238405Sjkim	if (ED_TYPE98SUB(flags) != 0) {
983238405Sjkim		init_addr = ED_CNET98_INIT2;
984238405Sjkim	}
985238405Sjkim#ifdef ED_DEBUG
986238405Sjkim	printf("ed?: initial register=%x\n", init_addr);
987238405Sjkim#endif
988238405Sjkim	/*
989238405Sjkim	 * Reset the board to force it into a known state.
990238405Sjkim	 */
991238405Sjkim	outb(init_addr, 0x00);	/* request */
992238405Sjkim	DELAY(5000);
993238405Sjkim	outb(init_addr, 0x01);	/* cancel */
994238405Sjkim	DELAY(5000);
995238405Sjkim
996238405Sjkim	/*
997238405Sjkim	 * Set I/O address(A15-12) and cpu type
998238405Sjkim	 *
999238405Sjkim	 *   AAAAIXXC(8bit)
1000238405Sjkim	 *   AAAA: A15-A12,  I: I/O enable, XX: reserved, C: CPU type
1001238405Sjkim	 *
1002238405Sjkim	 * CPU type is 1:80286 or higher, 0:not.
1003238405Sjkim	 * But FreeBSD runs under i386 or higher, thus it must be 1.
1004238405Sjkim	 */
1005238405Sjkim	tmp = (rman_get_start(sc->port_res) & 0xf000) >> 8;
1006160814Ssimon	tmp |= (0x08 | 0x01);
1007160814Ssimon#ifdef ED_DEBUG
1008160814Ssimon	printf("ed?: outb(%x, %x)\n", init_addr + 2, tmp);
1009238405Sjkim#endif
1010238405Sjkim	outb(init_addr + 2, tmp);
1011238405Sjkim	DELAY(5000);
1012237657Sjkim
1013237657Sjkim	/*
1014237657Sjkim	 * This is needed because some NE clones apparently don't reset the
1015237657Sjkim	 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
1016237657Sjkim	 * - this makes the probe invasive! ...Done against my better
1017237657Sjkim	 * judgement. -DLG
1018237657Sjkim	 */
1019237657Sjkim	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
1020237657Sjkim	DELAY(5000);
1021237657Sjkim}
1022160814Ssimon
1023160814Ssimonstatic void
1024160814Ssimoned_winsel_CNET98(sc, bank)
1025142425Snectar	struct ed_softc *sc;
1026160814Ssimon	u_short bank;
1027238405Sjkim{
1028238405Sjkim	u_char mem = (kvtop(sc->mem_start) >> 12) & 0xff;
1029238405Sjkim
1030238405Sjkim	/*
1031238405Sjkim	 * Disable window memory
1032238405Sjkim	 *    bit7 is 0:disable
1033238405Sjkim	 */
1034238405Sjkim	ed_asic_outb(sc, ED_CNET98_WIN_REG, mem & 0x7f);
1035238405Sjkim	DELAY(10);
1036238405Sjkim
1037238405Sjkim	/*
1038238405Sjkim	 * Select window address
1039238405Sjkim	 *    FreeBSD address 0xf00xxxxx
1040160814Ssimon	 */
1041142425Snectar	ed_asic_outb(sc, ED_CNET98_MAP_REG0L, bank & 0xff);
1042160814Ssimon	DELAY(10);
1043142425Snectar	ed_asic_outb(sc, ED_CNET98_MAP_REG0H, (bank >> 8) & 0xff);
1044238405Sjkim	DELAY(10);
1045238405Sjkim	ed_asic_outb(sc, ED_CNET98_MAP_REG1L, 0x00);
1046238405Sjkim	DELAY(10);
1047237657Sjkim	ed_asic_outb(sc, ED_CNET98_MAP_REG1H, 0x41);
1048237657Sjkim	DELAY(10);
1049237657Sjkim	ed_asic_outb(sc, ED_CNET98_MAP_REG2L, 0x00);
1050237657Sjkim	DELAY(10);
1051237657Sjkim	ed_asic_outb(sc, ED_CNET98_MAP_REG2H, 0x42);
1052237657Sjkim	DELAY(10);
1053237657Sjkim	ed_asic_outb(sc, ED_CNET98_MAP_REG3L, 0x00);
1054237657Sjkim	DELAY(10);
1055237657Sjkim	ed_asic_outb(sc, ED_CNET98_MAP_REG3H, 0x43);
1056237657Sjkim	DELAY(10);
1057
1058	/*
1059	 * Enable window memory(16Kbyte)
1060	 *    bit7 is 1:enable
1061	 */
1062#ifdef ED_DEBUG
1063	printf("ed?: window start address=%x\n", mem);
1064#endif
1065	ed_asic_outb(sc, ED_CNET98_WIN_REG, mem);
1066	DELAY(10);
1067}
1068
1069/*
1070 * Probe and vendor-specific initialization routine for C-NET(98) boards
1071 */
1072static int
1073ed_probe_CNET98(dev, port_rid, flags)
1074	device_t dev;
1075	int port_rid;
1076	int flags;
1077{
1078	struct ed_softc *sc = device_get_softc(dev);
1079	int error;
1080	u_char tmp;
1081	u_long conf_irq, junk;
1082	int i;
1083#ifdef DIAGNOSTIC
1084	u_char tmp_s;
1085#endif
1086
1087	error = ed98_alloc_port(dev, port_rid);
1088	if (error) {
1089		return (error);
1090	}
1091
1092	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
1093	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
1094
1095	error = ed98_alloc_memory(dev, 0);
1096	if (error) {
1097		return (error);
1098	}
1099
1100	/* Check I/O address. 0x[a-f]3d0 are allowed. */
1101	if (((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0)
1102	||  ((rman_get_start(sc->port_res) & 0xf000) < (u_short) 0xa000)) {
1103#ifdef DIAGNOSTIC
1104		device_printf(dev, "Invalid i/o port configuration (0x%x) "
1105			"must be %s for %s\n", rman_get_start(sc->port_res),
1106			"0x[a-f]3d0", "CNET98");
1107#endif
1108		return (ENXIO);
1109	}
1110
1111#ifdef DIAGNOSTIC
1112	/* Check window area address */
1113	tmp_s = kvtop(sc->mem_start) >> 12;
1114	if (tmp_s < 0x80) {
1115		device_printf(dev, "Please change window address(0x%x)\n",
1116			kvtop(sc->mem_start));
1117		return (ENXIO);
1118	}
1119
1120	tmp_s &= 0x0f;
1121	tmp    = rman_get_start(sc->port_res) >> 12;
1122	if ((tmp_s <= tmp) && (tmp < (tmp_s + 4))) {
1123		device_printf(dev, "Please change iobase address(0x%x) "
1124			"or window address(0x%x)\n",
1125	   		rman_get_start(sc->port_res), kvtop(sc->mem_start));
1126		return (ENXIO);
1127	}
1128#endif
1129	/* Reset the board */
1130	ed_reset_CNET98(sc, flags);
1131
1132	/*
1133	 * This is needed because some NE clones apparently don't reset the
1134	 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
1135	 * - this makes the probe invasive! ...Done against my better
1136	 * judgement. -DLG
1137	 */
1138	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
1139	DELAY(5000);
1140
1141	/* Make sure that we really have an 8390 based board */
1142	if (!ed98_probe_generic8390(sc)) {
1143		return (ENXIO);
1144	}
1145
1146	/*
1147	 *  Set window ethernet address area
1148	 *    board memory base 0x480000  data 256byte
1149	 */
1150	ed_winsel_CNET98(sc, 0x4800);
1151
1152	/*
1153	 * Get station address from on-board ROM
1154	 */
1155	bcopy(sc->mem_start, sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
1156
1157	sc->vendor    = ED_VENDOR_MISC;
1158	sc->type_str  = "CNET98";
1159	sc->isa16bit  = 0;
1160	sc->cr_proto  = ED_CR_RD2;
1161
1162	/*
1163	 * Set window buffer memory area
1164	 *    board memory base 0x400000  data 16kbyte
1165	 */
1166	ed_winsel_CNET98(sc, 0x4000);
1167
1168	/*
1169	 * clear interface memory, then sum to make sure its valid
1170	 */
1171	bzero(sc->mem_start, sc->mem_size);
1172
1173	for (i = 0; i < sc->mem_size; i++) {
1174		if (sc->mem_start[i]) {
1175			device_printf(dev, "failed to clear shared memory "
1176				"at %lx - check configuration\n",
1177				kvtop(sc->mem_start + i));
1178
1179			return (ENXIO);
1180		}
1181	}
1182
1183	sc->mem_shared = 1;
1184	sc->mem_end = sc->mem_start + sc->mem_size;
1185
1186	sc->txb_cnt = 1;	/* XXX */
1187	sc->tx_page_start = 0;
1188
1189	sc->rec_page_start = sc->tx_page_start + ED_TXBUF_SIZE;
1190	sc->rec_page_stop = sc->tx_page_start + sc->mem_size / ED_PAGE_SIZE;
1191
1192	sc->mem_ring = sc->mem_start + ED_PAGE_SIZE * ED_TXBUF_SIZE;
1193
1194	/*
1195	 *   Set interrupt level
1196	 */
1197	error = bus_get_resource(dev, SYS_RES_IRQ, 0,
1198				 &conf_irq, &junk);
1199	if (error)
1200		return (error);
1201
1202	switch (conf_irq) {
1203	case 3:
1204		tmp = ED_CNET98_INT_IRQ3;
1205		break;
1206	case 5:
1207		tmp = ED_CNET98_INT_IRQ5;
1208		break;
1209	case 6:
1210		tmp = ED_CNET98_INT_IRQ6;
1211		break;
1212	case 9:
1213		tmp = ED_CNET98_INT_IRQ9;
1214		break;
1215	case 12:
1216		tmp = ED_CNET98_INT_IRQ12;
1217		break;
1218	case 13:
1219		tmp = ED_CNET98_INT_IRQ13;
1220		break;
1221	default:
1222		device_printf(dev, "Invalid irq configuration (%ld) must be "
1223			"%s for %s\n", conf_irq, "3,5,6,9,12,13", "CNET98");
1224		return (ENXIO);
1225	}
1226	ed_asic_outb(sc, ED_CNET98_INT_LEV, tmp);
1227	DELAY(1000);
1228	/*
1229	 *   Set interrupt mask.
1230	 *     bit7:1 all interrupt mask
1231	 *     bit1:1 timer interrupt mask
1232	 *     bit0:0 NS controler interrupt enable
1233	 */
1234	ed_asic_outb(sc, ED_CNET98_INT_MASK, 0x7e);
1235	DELAY(1000);
1236
1237	return (0);
1238}
1239
1240/*
1241 * Probe and vendor-specific initialization routine for C-NET(98)E/L boards
1242 */
1243static int
1244ed_probe_CNET98EL(dev, port_rid, flags)
1245	device_t dev;
1246	int port_rid;
1247	int flags;
1248{
1249	struct ed_softc *sc = device_get_softc(dev);
1250	int error;
1251	int i;
1252	u_char romdata[ETHER_ADDR_LEN * 2], tmp;
1253	u_long conf_irq, junk;
1254
1255	error = ed98_alloc_port(dev, port_rid);
1256	if (error) {
1257		return (error);
1258	}
1259
1260	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
1261	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
1262
1263	/* Check I/O address. 0x[0-f]3d0 are allowed. */
1264	if ((rman_get_start(sc->port_res) & 0x0fff) != 0x03d0) {
1265#ifdef DIAGNOSTIC
1266		device_printf(dev, "Invalid i/o port configuration (0x%x) "
1267			"must be %s for %s\n", rman_get_start(sc->port_res),
1268			"0x?3d0", "CNET98E/L");
1269#endif
1270		return (ENXIO);
1271	}
1272
1273	/* Reset the board */
1274	ed_reset_CNET98(sc, flags);
1275
1276	/*
1277	 * This is needed because some NE clones apparently don't reset the
1278	 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
1279	 * - this makes the probe invasive! ...Done against my better
1280	 * judgement. -DLG
1281	 */
1282	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
1283	DELAY(5000);
1284
1285	/* Make sure that we really have an 8390 based board */
1286	if (!ed98_probe_generic8390(sc)) {
1287		return (ENXIO);
1288	}
1289
1290	/* Test memory via PIO */
1291	sc->cr_proto = ED_CR_RD2;
1292	if (!ed_pio_testmem(sc, ED_CNET98EL_PAGE_OFFSET, 1, flags)) {
1293		return (ENXIO);
1294	}
1295
1296	/* This looks like a C-NET(98)E/L board. */
1297	sc->type_str = "CNET98E/L";
1298
1299	/*
1300	 * Set IRQ. C-NET(98)E/L only allows a choice of irq 3,5,6.
1301	 */
1302	error = bus_get_resource(dev, SYS_RES_IRQ, 0,
1303				 &conf_irq, &junk);
1304	if (error) {
1305		return (error);
1306	}
1307
1308	switch (conf_irq) {
1309	case 3:
1310		tmp = ED_CNET98EL_ICR_IRQ3;
1311		break;
1312	case 5:
1313		tmp = ED_CNET98EL_ICR_IRQ5;
1314		break;
1315	case 6:
1316		tmp = ED_CNET98EL_ICR_IRQ6;
1317		break;
1318#if 0
1319	case 12:
1320		tmp = ED_CNET98EL_ICR_IRQ12;
1321		break;
1322#endif
1323	default:
1324		device_printf(dev, "Invalid irq configuration (%ld) must be "
1325			"%s for %s\n", conf_irq, "3,5,6", "CNET98E/L");
1326		return (ENXIO);
1327	}
1328	ed_asic_outb(sc, ED_CNET98EL_ICR, tmp);
1329	ed_asic_outb(sc, ED_CNET98EL_IMR, 0x7e);
1330
1331	/* Get station address from on-board ROM */
1332	ed_pio_readmem(sc, 16384, romdata, sizeof(romdata));
1333	for (i = 0; i < ETHER_ADDR_LEN; i++) {
1334		sc->arpcom.ac_enaddr[i] = romdata[i * 2];
1335	}
1336
1337	/* clear any pending interrupts that might have occurred above */
1338	ed_nic_outb(sc, ED_P0_ISR, 0xff);
1339
1340	return (0);
1341}
1342
1343/*
1344 * Probe and vendor-specific initialization routine for PC-9801-77 boards
1345 */
1346static int
1347ed_probe_NEC77(dev, port_rid, flags)
1348	device_t dev;
1349	int port_rid;
1350	int flags;
1351{
1352	struct ed_softc *sc = device_get_softc(dev);
1353	int error;
1354	u_char tmp;
1355	u_long conf_irq, junk;
1356
1357	error = ed98_probe_Novell(dev, port_rid, flags);
1358	if (error) {
1359		return (error);
1360	}
1361
1362	/* LA/T-98 does not need IRQ setting. */
1363	if (ED_TYPE98SUB(flags) == 0) {
1364		return (0);
1365	}
1366
1367	/*
1368	 * Set IRQ. PC-9801-77 only allows a choice of irq 3,5,6,12,13.
1369	 */
1370	error = bus_get_resource(dev, SYS_RES_IRQ, 0,
1371				 &conf_irq, &junk);
1372	if (error) {
1373		return (error);
1374	}
1375
1376	switch (conf_irq) {
1377	case 3:
1378		tmp = ED_NEC77_IRQ3;
1379		break;
1380	case 5:
1381		tmp = ED_NEC77_IRQ5;
1382		break;
1383	case 6:
1384		tmp = ED_NEC77_IRQ6;
1385		break;
1386	case 12:
1387		tmp = ED_NEC77_IRQ12;
1388		break;
1389	case 13:
1390		tmp = ED_NEC77_IRQ13;
1391		break;
1392	default:
1393		device_printf(dev, "Invalid irq configuration (%ld) must be "
1394			"%s for %s\n", conf_irq, "3,5,6,12,13", "PC-9801-77");
1395		return (ENXIO);
1396	}
1397	ed_asic_outb(sc, ED_NEC77_IRQ, tmp);
1398
1399	return (0);
1400}
1401
1402/*
1403 * Probe and vendor-specific initialization routine for EC/EP-98X boards
1404 */
1405static int
1406ed_probe_NW98X(dev, port_rid, flags)
1407	device_t dev;
1408	int port_rid;
1409	int flags;
1410{
1411	struct ed_softc *sc = device_get_softc(dev);
1412	int error;
1413	u_char tmp;
1414	u_long conf_irq, junk;
1415
1416	error = ed98_probe_Novell(dev, port_rid, flags);
1417	if (error) {
1418		return (error);
1419	}
1420
1421	/* Networld 98X3 does not need IRQ setting. */
1422	if (ED_TYPE98SUB(flags) == 0) {
1423		return (0);
1424	}
1425
1426	/*
1427	 * Set IRQ. EC/EP-98X only allows a choice of irq 3,5,6,12,13.
1428	 */
1429	error = bus_get_resource(dev, SYS_RES_IRQ, 0,
1430				 &conf_irq, &junk);
1431	if (error) {
1432		return (error);
1433	}
1434
1435	switch (conf_irq) {
1436	case 3:
1437		tmp = ED_NW98X_IRQ3;
1438		break;
1439	case 5:
1440		tmp = ED_NW98X_IRQ5;
1441		break;
1442	case 6:
1443		tmp = ED_NW98X_IRQ6;
1444		break;
1445	case 12:
1446		tmp = ED_NW98X_IRQ12;
1447		break;
1448	case 13:
1449		tmp = ED_NW98X_IRQ13;
1450		break;
1451	default:
1452		device_printf(dev, "Invalid irq configuration (%ld) must be "
1453			"%s for %s\n", conf_irq, "3,5,6,12,13", "EC/EP-98X");
1454		return (ENXIO);
1455	}
1456	ed_asic_outb(sc, ED_NW98X_IRQ, tmp);
1457
1458	return (0);
1459}
1460
1461/*
1462 * Read SB-9801 station address from Serial Two-Wire EEPROM
1463 */
1464static void
1465ed_get_SB98(sc)
1466	struct ed_softc *sc;
1467{
1468	int i, j;
1469	u_char mask, val;
1470
1471        /* enable EEPROM acceess */
1472        ed_asic_outb(sc, ED_SB98_EEPENA, ED_SB98_EEPENA_ENABLE);
1473
1474	/* output start command */
1475	ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL);
1476	DELAY(ED_SB98_EEP_DELAY);
1477	ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL);
1478	DELAY(ED_SB98_EEP_DELAY);
1479
1480       	/* output address (7bit) */
1481	for (mask = 0x40; mask != 0; mask >>= 1) {
1482		val = 0;
1483		if (ED_SB98_ADDRESS & mask)
1484			val = ED_SB98_EEP_SDA;
1485		ed_asic_outb(sc, ED_SB98_EEP, val);
1486		DELAY(ED_SB98_EEP_DELAY);
1487		ed_asic_outb(sc, ED_SB98_EEP, val | ED_SB98_EEP_SCL);
1488		DELAY(ED_SB98_EEP_DELAY);
1489	}
1490
1491	/* output READ command */
1492	ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_READ);
1493	DELAY(ED_SB98_EEP_DELAY);
1494	ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_READ | ED_SB98_EEP_SCL);
1495	DELAY(ED_SB98_EEP_DELAY);
1496
1497	/* read station address */
1498	for (i = 0; i < ETHER_ADDR_LEN; i++) {
1499		/* output ACK */
1500		ed_asic_outb(sc, ED_SB98_EEP, 0);
1501		DELAY(ED_SB98_EEP_DELAY);
1502		ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL);
1503		DELAY(ED_SB98_EEP_DELAY);
1504
1505		val = 0;
1506		for (j = 0; j < 8; j++) {
1507			ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA);
1508			DELAY(ED_SB98_EEP_DELAY);
1509			ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL);
1510			DELAY(ED_SB98_EEP_DELAY);
1511			val <<= 1;
1512			val |= (ed_asic_inb(sc, ED_SB98_EEP) & ED_SB98_EEP_SDA);
1513			DELAY(ED_SB98_EEP_DELAY);
1514	  	}
1515		sc->arpcom.ac_enaddr[i] = val;
1516	}
1517
1518	/* output Last ACK */
1519        ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA);
1520        DELAY(ED_SB98_EEP_DELAY);
1521        ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL);
1522        DELAY(ED_SB98_EEP_DELAY);
1523
1524	/* output stop command */
1525	ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SCL);
1526	DELAY(ED_SB98_EEP_DELAY);
1527	ed_asic_outb(sc, ED_SB98_EEP, ED_SB98_EEP_SDA | ED_SB98_EEP_SCL);
1528	DELAY(ED_SB98_EEP_DELAY);
1529
1530	/* disable EEPROM access */
1531	ed_asic_outb(sc, ED_SB98_EEPENA, ED_SB98_EEPENA_DISABLE);
1532}
1533
1534/*
1535 * Probe and vendor-specific initialization routine for SB-9801 boards
1536 */
1537static int
1538ed_probe_SB98(dev, port_rid, flags)
1539	device_t dev;
1540	int port_rid;
1541	int flags;
1542{
1543	struct ed_softc *sc = device_get_softc(dev);
1544	int error;
1545	u_char tmp;
1546	u_long conf_irq, junk;
1547
1548	error = ed98_alloc_port(dev, port_rid);
1549	if (error) {
1550		return (error);
1551	}
1552
1553	sc->asic_offset = ED_NOVELL_ASIC_OFFSET;
1554	sc->nic_offset  = ED_NOVELL_NIC_OFFSET;
1555
1556	/* Check I/O address. 00d[02468ace] are allowed. */
1557	if ((rman_get_start(sc->port_res) & ~0x000e) != 0x00d0) {
1558#ifdef DIAGNOSTIC
1559		device_printf(dev, "Invalid i/o port configuration (0x%x) "
1560			"must be %s for %s\n", rman_get_start(sc->port_res),
1561			"0xd?", "SB9801");
1562#endif
1563		return (ENXIO);
1564	}
1565
1566	/* Write I/O port address and read 4 times */
1567	outb(ED_SB98_IO_INHIBIT, rman_get_start(sc->port_res) & 0xff);
1568	(void) inb(ED_SB98_IO_INHIBIT); DELAY(300);
1569	(void) inb(ED_SB98_IO_INHIBIT); DELAY(300);
1570	(void) inb(ED_SB98_IO_INHIBIT); DELAY(300);
1571	(void) inb(ED_SB98_IO_INHIBIT); DELAY(300);
1572
1573	/*
1574	 * Check IRQ. Soliton SB-9801 only allows a choice of
1575	 * irq 3,5,6,12
1576	 */
1577	error = bus_get_resource(dev, SYS_RES_IRQ, 0,
1578				 &conf_irq, &junk);
1579	if (error) {
1580		return (error);
1581	}
1582
1583	switch (conf_irq) {
1584	case 3:
1585		tmp = ED_SB98_CFG_IRQ3;
1586		break;
1587	case 5:
1588		tmp = ED_SB98_CFG_IRQ5;
1589		break;
1590	case 6:
1591		tmp = ED_SB98_CFG_IRQ6;
1592		break;
1593	case 12:
1594		tmp = ED_SB98_CFG_IRQ12;
1595		break;
1596	default:
1597		device_printf(dev, "Invalid irq configuration (%ld) must be "
1598			"%s for %s\n", conf_irq, "3,5,6,12", "SB9801");
1599		return (ENXIO);
1600	}
1601
1602	if (flags & ED_FLAGS_DISABLE_TRANCEIVER) {
1603		tmp |= ED_SB98_CFG_ALTPORT;
1604	}
1605	ed_asic_outb(sc, ED_SB98_CFG, ED_SB98_CFG_ENABLE | tmp);
1606	ed_asic_outb(sc, ED_SB98_POLARITY, 0x01);
1607
1608	/* Reset the board. */
1609	ed_asic_outb(sc, ED_NOVELL_RESET, 0x7a);
1610	DELAY(300);
1611	ed_asic_outb(sc, ED_NOVELL_RESET, 0x79);
1612	DELAY(300);
1613
1614	/*
1615	 * This is needed because some NE clones apparently don't reset the
1616	 * NIC properly (or the NIC chip doesn't reset fully on power-up) XXX
1617	 * - this makes the probe invasive! ...Done against my better
1618	 * judgement. -DLG
1619	 */
1620	ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
1621	DELAY(5000);
1622
1623	/* Make sure that we really have an 8390 based board */
1624	if (!ed98_probe_generic8390(sc)) {
1625		return (ENXIO);
1626	}
1627
1628	/* Test memory via PIO */
1629	sc->cr_proto = ED_CR_RD2;
1630	if (!ed_pio_testmem(sc, 16384, 1, flags)) {
1631		return (ENXIO);
1632	}
1633
1634	/* This looks like an SB9801 board. */
1635	sc->type_str = "SB9801";
1636
1637	/* Get station address */
1638	ed_get_SB98(sc);
1639
1640	/* clear any pending interrupts that might have occurred above */
1641	ed_nic_outb(sc, ED_P0_ISR, 0xff);
1642
1643	return (0);
1644}
1645
1646/*
1647 * Test the ability to read and write to the NIC memory.
1648 */
1649static int
1650ed_pio_testmem(sc, page_offset, isa16bit, flags)
1651	struct ed_softc *sc;
1652	int page_offset;
1653	int isa16bit;
1654	int flags;
1655{
1656	u_long memsize;
1657	static char test_pattern[32] = "THIS is A memory TEST pattern";
1658	char test_buffer[32];
1659#ifdef DIAGNOSTIC
1660	int page_end;
1661#endif
1662
1663	sc->vendor = ED_VENDOR_NOVELL;
1664	sc->mem_shared = 0;
1665	sc->isa16bit = isa16bit;
1666
1667	/* 8k of memory plus an additional 8k if 16bit */
1668	memsize = (isa16bit ? 16384 : 8192);
1669
1670	/*
1671	 * This prevents packets from being stored in the NIC memory when the
1672	 * readmem routine turns on the start bit in the CR.
1673	 */
1674	ed_nic_outb(sc, ED_P0_RCR, ED_RCR_MON);
1675
1676	/* Initialize DCR for byte/word operations */
1677	if (isa16bit) {
1678		ed_nic_outb(sc, ED_P0_DCR, ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
1679	} else {
1680		ed_nic_outb(sc, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
1681	}
1682	ed_nic_outb(sc, ED_P0_PSTART, page_offset / ED_PAGE_SIZE);
1683	ed_nic_outb(sc, ED_P0_PSTOP, (page_offset + memsize) / ED_PAGE_SIZE);
1684#ifdef ED_DEBUG
1685	printf("ed?: ed_pio_testmem: page start=%x, end=%x",
1686		      page_offset, page_offset + memsize);
1687#endif
1688
1689	/*
1690	 * Write a test pattern. If this fails, then we don't know
1691	 * what this board is.
1692	 */
1693	ed_pio_writemem(sc, test_pattern, page_offset, sizeof(test_pattern));
1694	ed_pio_readmem(sc, page_offset, test_buffer, sizeof(test_pattern));
1695
1696	if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) {
1697#ifdef ED_DEBUG
1698		printf("ed?: ed_pio_testmem: bcmp(page %x) NG",
1699			      page_offset);
1700#endif
1701		return (0);
1702	}
1703
1704#ifdef DIAGNOSTIC
1705	/* Check the bottom. */
1706	page_end = page_offset + memsize - ED_PAGE_SIZE;
1707	ed_pio_writemem(sc, test_pattern, page_end, sizeof(test_pattern));
1708	ed_pio_readmem(sc, page_end, test_buffer, sizeof(test_pattern));
1709
1710	if (bcmp(test_pattern, test_buffer, sizeof(test_pattern))) {
1711#ifdef ED_DEBUG
1712		printf("ed?: ed_pio_testmem: bcmp(page %x) NG",
1713			      page_end);
1714#endif
1715		return (0);
1716	}
1717#endif
1718	sc->mem_size = memsize;
1719	sc->mem_start = (char *) page_offset;
1720	sc->mem_end   = sc->mem_start + memsize;
1721	sc->tx_page_start = page_offset / ED_PAGE_SIZE;
1722
1723	/*
1724	 * Use one xmit buffer if < 16k, two buffers otherwise (if not told
1725	 * otherwise).
1726	 */
1727	if ((memsize < 16384) || (flags & ED_FLAGS_NO_MULTI_BUFFERING)) {
1728		sc->txb_cnt = 1;
1729	} else {
1730		sc->txb_cnt = 2;
1731	}
1732
1733	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
1734	sc->rec_page_stop  = sc->tx_page_start + memsize / ED_PAGE_SIZE;
1735
1736	sc->mem_ring = sc->mem_start + sc->txb_cnt * ED_PAGE_SIZE * ED_TXBUF_SIZE;
1737
1738	return (1);
1739}
1740#endif	/* PC98 */
1741
1742static device_method_t ed_isa_methods[] = {
1743	/* Device interface */
1744	DEVMETHOD(device_probe,		ed_isa_probe),
1745	DEVMETHOD(device_attach,	ed_isa_attach),
1746
1747	{ 0, 0 }
1748};
1749
1750static driver_t ed_isa_driver = {
1751	"ed",
1752	ed_isa_methods,
1753	sizeof(struct ed_softc)
1754};
1755
1756DRIVER_MODULE(if_ed, isa, ed_isa_driver, ed_devclass, 0, 0);
1757