Module Name:    src
Committed By:   riz
Date:           Sat Nov 20 00:33:49 UTC 2010

Modified Files:
        src/distrib/notes/atari [netbsd-5]: hardware
        src/sys/arch/atari/atari [netbsd-5]: autoconf.c
        src/sys/arch/atari/conf [netbsd-5]: GENERIC.in files.atari
        src/sys/arch/x68k/dev [netbsd-5]: if_ne_intio.c if_ne_neptune.c
        src/sys/conf [netbsd-5]: files
        src/sys/dev/ic [netbsd-5]: dp8390.c ne2000.c ne2000var.h
        src/sys/dev/isa [netbsd-5]: if_ne_isa.c
        src/sys/dev/isapnp [netbsd-5]: if_ne_isapnp.c
Added Files:
        src/sys/arch/atari/dev [netbsd-5]: if_ne_mb.c

Log Message:
Pull up following revision(s) (requested by tsutsui in ticket #1367):
        sys/dev/ic/ne2000var.h: revision 1.25
        sys/arch/atari/conf/MILAN.in: revision 1.24
        sys/arch/atari/conf/MILAN.in: revision 1.25
        sys/dev/ic/ne2000.c: revision 1.71
        sys/dev/ic/ne2000.c: revision 1.72
        sys/arch/atari/dev/if_ne_mb.c: revision 1.1
        sys/arch/atari/dev/if_ne_mb.c: revision 1.2
        sys/arch/atari/conf/MILAN-PCIIDE: revision 1.69
        sys/arch/atari/conf/HADES.in: revision 1.10
        sys/arch/atari/conf/HADES.in: revision 1.11
        sys/arch/x68k/dev/if_ne_neptune.c: revision 1.20
        sys/dev/isa/if_ne_isa.c: revision 1.27
        sys/arch/atari/atari/autoconf.c: revision 1.57
        sys/dev/ic/ne2000.c: revision 1.62
        sys/dev/isapnp/if_ne_isapnp.c: revision 1.27
        sys/arch/atari/conf/files.atari: revision 1.117
        sys/arch/atari/conf/HADES: revision 1.88
        sys/arch/atari/conf/GENERIC.in: revision 1.85
        sys/dev/ic/ne2000.c: revision 1.65
        sys/dev/ic/ne2000.c: revision 1.66
        sys/dev/ic/ne2000.c: revision 1.68
        sys/arch/atari/conf/MILAN-ISAIDE: revision 1.65
        distrib/notes/atari/hardware: revision 1.24
        sys/conf/files: revision 1.980
        sys/dev/ic/ne2000var.h: revision 1.21
        sys/arch/x68k/dev/if_ne_intio.c: revision 1.16
        sys/dev/ic/dp8390.c: revision 1.74
        sys/dev/ic/dp8390.c: revision 1.75
Added NE2000 with 8bit bus width support.
reviewd by tsutsui@ at tech-kern ML.
Fix a wrong calculation bug around RX ring buffer memory address
slipped in about sixteen years ago.  Fortunately, it had been working
for ages because some devices used address zero and other devices
ignored wrong higher bits.
Tested on we(4) (SMC Elite Ultra) and ne(4) (NE2000 compatible
named UL0001) on ISA.
Note FreeBSD also uses the same correct value in their ed(4) driver.
Now dp8390_config() calculates mem_ring correctly so
no longer need to override it in ne2000_attach().
Use roundup2() in <sys/param.h> rather than a conditional.
Also fix a wrong mem_ring calculation in dp8390_ipkdb_attach().
Put several fixes to ne(4) driver for better 8 bit mode support,
especially on RTL8019AS which is also used for non-ISA local bus of
embedded controllers and some m68k machines like atari and x68k.
 * move RTL8019 probe and attach code from each bus attachment
   to MI ne2000_detect() and ne2000_attach()
 * change a method for backend and attachment to specify 8 bit mode
   to use a new sc->sc_quirk member, instead of sc->sc_dmawidth
 * handle more NE2000 8 bit mode specific settings, including
   bus_space(9) access width and available size of buffer memory
 * add a function to detect NE2000 8 bit mode
   (disabled by default, but enalbed by options NE2000_DETECT_8BIT
    to avoid possible regression on various ISA clones)
 * fix ipkdb attachment accordingly (untested)
Tested on two NE2000 ISA variants (RTL8019AS and another clone named UL0001)
in both 8 bit and 16 bit mode on i386. "Looks good" from non...@.
See my post on tech-kern for details:
http://mail-index.NetBSD.org/tech-kern/2010/02/26/msg007423.html
No need to override mem_ring value in ne2000_ipkdb_attach()
since a wrong calculation in dp8390_ipkdb_attach() was fixed.
Don't warn about DMA timeout during probe.
Add support for the EtherNEC.
The EtherNEC is yet another user designed device for Atari machines,
an NE2000 based ISA board connected to Atari's ROM cartridge slot with
simple but ingenious interface and cartridge port adapter, and
it's the most available network solution for the old Atari machines.
See following pages for more details about EtherNEC:
http://hardware.atari.org/ether/
http://home.arcor.de/thomas.redelberger/prj/atari/etherne/
http://www.freemint.org/ethernec/ethernec.html
Also note EtherNEC.
Use callout_schedule(9) rather than callout_reset(9) on polling
as callout(9) man says.
Remove EtherNEC from HADES and MILAN.
They have ISA so no one will bother to connect ISA NE2000 via EtherNEC.
Regen from HADES.in rev 1.11 and MILAN.in rev 1.25:
Remove EtherNEC from HADES and MILAN.
They have ISA so no one will bother to connect ISA NE2000 via EtherNEC.


To generate a diff of this commit:
cvs rdiff -u -r1.21.40.2 -r1.21.40.3 src/distrib/notes/atari/hardware
cvs rdiff -u -r1.54 -r1.54.28.1 src/sys/arch/atari/atari/autoconf.c
cvs rdiff -u -r1.73.4.6 -r1.73.4.7 src/sys/arch/atari/conf/GENERIC.in
cvs rdiff -u -r1.112.20.2 -r1.112.20.3 src/sys/arch/atari/conf/files.atari
cvs rdiff -u -r0 -r1.2.8.2 src/sys/arch/atari/dev/if_ne_mb.c
cvs rdiff -u -r1.11 -r1.11.14.1 src/sys/arch/x68k/dev/if_ne_intio.c
cvs rdiff -u -r1.16 -r1.16.8.1 src/sys/arch/x68k/dev/if_ne_neptune.c
cvs rdiff -u -r1.924.4.6 -r1.924.4.7 src/sys/conf/files
cvs rdiff -u -r1.68 -r1.68.14.1 src/sys/dev/ic/dp8390.c
cvs rdiff -u -r1.59 -r1.59.10.1 src/sys/dev/ic/ne2000.c
cvs rdiff -u -r1.19 -r1.19.10.1 src/sys/dev/ic/ne2000var.h
cvs rdiff -u -r1.26 -r1.26.10.1 src/sys/dev/isa/if_ne_isa.c
cvs rdiff -u -r1.26 -r1.26.10.1 src/sys/dev/isapnp/if_ne_isapnp.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/distrib/notes/atari/hardware
diff -u src/distrib/notes/atari/hardware:1.21.40.2 src/distrib/notes/atari/hardware:1.21.40.3
--- src/distrib/notes/atari/hardware:1.21.40.2	Sat Nov 20 00:26:52 2010
+++ src/distrib/notes/atari/hardware	Sat Nov 20 00:33:48 2010
@@ -1,4 +1,4 @@
-.\"	$NetBSD: hardware,v 1.21.40.2 2010/11/20 00:26:52 riz Exp $
+.\"	$NetBSD: hardware,v 1.21.40.3 2010/11/20 00:33:48 riz Exp $
 .
 .Nx*M
 \*V runs on the TT030, Falcon, Hades and MilanI machines.
@@ -49,6 +49,8 @@
 .It
 The serial interface on the first 68901 UART (modem1)
 .It
+EtherNEC Ethernet on ROM cartridge slot
+.It
 VME-bus devices (TT030/Hades)
 .(bullet -compact
 BVME410 Ethernet

Index: src/sys/arch/atari/atari/autoconf.c
diff -u src/sys/arch/atari/atari/autoconf.c:1.54 src/sys/arch/atari/atari/autoconf.c:1.54.28.1
--- src/sys/arch/atari/atari/autoconf.c:1.54	Mon Dec  3 15:33:21 2007
+++ src/sys/arch/atari/atari/autoconf.c	Sat Nov 20 00:33:47 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: autoconf.c,v 1.54 2007/12/03 15:33:21 ad Exp $	*/
+/*	$NetBSD: autoconf.c,v 1.54.28.1 2010/11/20 00:33:47 riz Exp $	*/
 
 /*
  * Copyright (c) 1995 Leo Weppelman
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.54 2007/12/03 15:33:21 ad Exp $");
+__KERNEL_RCSID(0, "$NetBSD: autoconf.c,v 1.54.28.1 2010/11/20 00:33:47 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -299,6 +299,7 @@
 	config_found(dp, __UNCONST("nvr")     , simple_devprint);
 	config_found(dp, __UNCONST("lpt")     , simple_devprint);
 	config_found(dp, __UNCONST("wdc")     , simple_devprint);
+	config_found(dp, __UNCONST("ne")      , simple_devprint);
 	config_found(dp, __UNCONST("isab")    , simple_devprint);
 	config_found(dp, __UNCONST("pcib")    , simple_devprint);
 	config_found(dp, __UNCONST("avmebus") , simple_devprint);

Index: src/sys/arch/atari/conf/GENERIC.in
diff -u src/sys/arch/atari/conf/GENERIC.in:1.73.4.6 src/sys/arch/atari/conf/GENERIC.in:1.73.4.7
--- src/sys/arch/atari/conf/GENERIC.in:1.73.4.6	Sat Nov 20 00:26:51 2010
+++ src/sys/arch/atari/conf/GENERIC.in	Sat Nov 20 00:33:46 2010
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: GENERIC.in,v 1.73.4.6 2010/11/20 00:26:51 riz Exp $
+#	$NetBSD: GENERIC.in,v 1.73.4.7 2010/11/20 00:33:46 riz Exp $
 #
 # Generic atari
 #
@@ -345,6 +345,7 @@
 ite2		at grfcc2	# 3rd tty
 lp0		at mainbus0	# centronics printer
 ser0		at mainbus0	# UART on first 68901 (ttyB0)
+ne0		at mainbus0	# EtherNEC on Atari ROM cartridge slot
 
 #if defined(TT030_KERNEL)
 avmebus0	at mainbus0	# VME bus

Index: src/sys/arch/atari/conf/files.atari
diff -u src/sys/arch/atari/conf/files.atari:1.112.20.2 src/sys/arch/atari/conf/files.atari:1.112.20.3
--- src/sys/arch/atari/conf/files.atari:1.112.20.2	Sat Nov 20 00:26:51 2010
+++ src/sys/arch/atari/conf/files.atari	Sat Nov 20 00:33:46 2010
@@ -1,5 +1,5 @@
 #
-#	$NetBSD: files.atari,v 1.112.20.2 2010/11/20 00:26:51 riz Exp $
+#	$NetBSD: files.atari,v 1.112.20.3 2010/11/20 00:33:46 riz Exp $
 
 maxpartitions 16
 
@@ -182,6 +182,10 @@
 attach	wdc at mainbus with wdc_mb: mbdma
 file	arch/atari/dev/wdc_mb.c		wdc_mb
 
+# EtherNEC on Atari ROM cartridge slot
+attach	ne at mainbus with ne_mb: rtl80x9
+file	arch/atari/dev/if_ne_mb.c	ne_mb
+
 # ISA Plug 'n Play devices
 file	arch/atari/isa/isapnp_machdep.c	isapnp
 

Index: src/sys/arch/x68k/dev/if_ne_intio.c
diff -u src/sys/arch/x68k/dev/if_ne_intio.c:1.11 src/sys/arch/x68k/dev/if_ne_intio.c:1.11.14.1
--- src/sys/arch/x68k/dev/if_ne_intio.c:1.11	Wed Mar 12 15:07:48 2008
+++ src/sys/arch/x68k/dev/if_ne_intio.c	Sat Nov 20 00:33:47 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ne_intio.c,v 1.11 2008/03/12 15:07:48 tsutsui Exp $	*/
+/*	$NetBSD: if_ne_intio.c,v 1.11.14.1 2010/11/20 00:33:47 riz Exp $	*/
 
 /*
  * Copyright (c) 2001 Tetsuya Isaki. All rights reserved.
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ne_intio.c,v 1.11 2008/03/12 15:07:48 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ne_intio.c,v 1.11.14.1 2010/11/20 00:33:47 riz Exp $");
 
 #include "opt_inet.h"
 #include "opt_ns.h"
@@ -75,8 +75,6 @@
 #include <dev/ic/dp8390var.h>
 #include <dev/ic/ne2000reg.h>
 #include <dev/ic/ne2000var.h>
-#include <dev/ic/rtl80x9reg.h>
-#include <dev/ic/rtl80x9var.h>
 
 #include <arch/x68k/dev/intiovar.h>
 
@@ -189,21 +187,10 @@
 
 	case NE2000_TYPE_NE2000:
 		typestr = "NE2000";
-		/*
-		 * Check for a Realtek 8019.
-		 */
-		bus_space_write_1(iot, ioh, ED_P0_CR,
-			ED_CR_PAGE_0 | ED_CR_STP);
-		if (bus_space_read_1(iot, ioh, NERTL_RTL0_8019ID0) ==
-		      RTL0_8019ID0 &&
-		      bus_space_read_1(iot, ioh, NERTL_RTL0_8019ID1) ==
-		      RTL0_8019ID1) {
-			typestr = "NE2000 (RTL8019)";
-			dsc->sc_mediachange = rtl80x9_mediachange;
-			dsc->sc_mediastatus = rtl80x9_mediastatus;
-			dsc->init_card      = rtl80x9_init_card;
-			dsc->sc_media_init  = rtl80x9_media_init;
-		}
+		break;
+
+	case NE2000_TYPE_RTL8019:
+		typestr = "NE2000 (RTL8019)";
 		break;
 
 	default:

Index: src/sys/arch/x68k/dev/if_ne_neptune.c
diff -u src/sys/arch/x68k/dev/if_ne_neptune.c:1.16 src/sys/arch/x68k/dev/if_ne_neptune.c:1.16.8.1
--- src/sys/arch/x68k/dev/if_ne_neptune.c:1.16	Fri May  9 10:09:27 2008
+++ src/sys/arch/x68k/dev/if_ne_neptune.c	Sat Nov 20 00:33:46 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ne_neptune.c,v 1.16 2008/05/09 10:09:27 tsutsui Exp $	*/
+/*	$NetBSD: if_ne_neptune.c,v 1.16.8.1 2010/11/20 00:33:46 riz Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ne_neptune.c,v 1.16 2008/05/09 10:09:27 tsutsui Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ne_neptune.c,v 1.16.8.1 2010/11/20 00:33:46 riz Exp $");
 
 #include "opt_inet.h"
 #include "opt_ns.h"
@@ -78,9 +78,6 @@
 #include <dev/ic/ne2000reg.h>
 #include <dev/ic/ne2000var.h>
 
-#include <dev/ic/rtl80x9reg.h>
-#include <dev/ic/rtl80x9var.h>
-
 #include <arch/x68k/dev/neptunevar.h>
 
 static int ne_neptune_match(device_t, cfdata_t, void *);
@@ -172,21 +169,10 @@
 
 	case NE2000_TYPE_NE2000:
 		typestr = "NE2000";
-		/*
-		 * Check for a Realtek 8019.
-		 */
-		bus_space_write_1(nict, nich, ED_P0_CR,
-		    ED_CR_PAGE_0 | ED_CR_STP);
-		if (bus_space_read_1(nict, nich, NERTL_RTL0_8019ID0) ==
-								RTL0_8019ID0 &&
-		    bus_space_read_1(nict, nich, NERTL_RTL0_8019ID1) ==
-								RTL0_8019ID1) {
-			typestr = "NE2000 (RTL8019)";
-			dsc->sc_mediachange = rtl80x9_mediachange;
-			dsc->sc_mediastatus = rtl80x9_mediastatus;
-			dsc->init_card = rtl80x9_init_card;
-			dsc->sc_media_init = rtl80x9_media_init;
-		}
+		break;
+
+	case NE2000_TYPE_RTL8019:
+		typestr = "NE2000 (RTL8019)";
 		break;
 
 	default:

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.924.4.6 src/sys/conf/files:1.924.4.7
--- src/sys/conf/files:1.924.4.6	Thu Oct  8 09:47:09 2009
+++ src/sys/conf/files	Sat Nov 20 00:33:48 2010
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.924.4.6 2009/10/08 09:47:09 sborrill Exp $
+#	$NetBSD: files,v 1.924.4.7 2010/11/20 00:33:48 riz Exp $
 
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
@@ -885,7 +885,7 @@
 # Realtek 8019/8029 NE2000-compatible network interface subroutines
 #
 define	rtl80x9
-file	dev/ic/rtl80x9.c		rtl80x9
+file	dev/ic/rtl80x9.c		rtl80x9			needs-flag
 
 # Realtek 8129/8139 Ethernet controllers
 #

Index: src/sys/dev/ic/dp8390.c
diff -u src/sys/dev/ic/dp8390.c:1.68 src/sys/dev/ic/dp8390.c:1.68.14.1
--- src/sys/dev/ic/dp8390.c:1.68	Wed Mar 12 14:31:11 2008
+++ src/sys/dev/ic/dp8390.c	Sat Nov 20 00:33:45 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: dp8390.c,v 1.68 2008/03/12 14:31:11 cube Exp $	*/
+/*	$NetBSD: dp8390.c,v 1.68.14.1 2010/11/20 00:33:45 riz Exp $	*/
 
 /*
  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
@@ -14,7 +14,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: dp8390.c,v 1.68 2008/03/12 14:31:11 cube Exp $");
+__KERNEL_RCSID(0, "$NetBSD: dp8390.c,v 1.68.14.1 2010/11/20 00:33:45 riz Exp $");
 
 #include "opt_ipkdb.h"
 #include "opt_inet.h"
@@ -118,7 +118,8 @@
 	sc->tx_page_start = sc->mem_start >> ED_PAGE_SHIFT;
 	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
 	sc->rec_page_stop = sc->tx_page_start + (sc->mem_size >> ED_PAGE_SHIFT);
-	sc->mem_ring = sc->mem_start + (sc->rec_page_start << ED_PAGE_SHIFT);
+	sc->mem_ring = sc->mem_start +
+	    ((sc->txb_cnt * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
 	sc->mem_end = sc->mem_start + sc->mem_size;
 
 	/* Now zero memory and verify that it is clear. */
@@ -1354,7 +1355,8 @@
 	sc->tx_page_start = sc->mem_start >> ED_PAGE_SHIFT;
 	sc->rec_page_start = sc->tx_page_start + sc->txb_cnt * ED_TXBUF_SIZE;
 	sc->rec_page_stop = sc->tx_page_start + (sc->mem_size >> ED_PAGE_SHIFT);
-	sc->mem_ring = sc->mem_start + (sc->rec_page_start << ED_PAGE_SHIFT);
+	sc->mem_ring = sc->mem_start +
+	    ((sc->txb_cnt * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
 	sc->mem_end = sc->mem_start + sc->mem_size;
 
 	dp8390_stop(sc);

Index: src/sys/dev/ic/ne2000.c
diff -u src/sys/dev/ic/ne2000.c:1.59 src/sys/dev/ic/ne2000.c:1.59.10.1
--- src/sys/dev/ic/ne2000.c:1.59	Mon Apr 28 20:23:50 2008
+++ src/sys/dev/ic/ne2000.c	Sat Nov 20 00:33:44 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ne2000.c,v 1.59 2008/04/28 20:23:50 martin Exp $	*/
+/*	$NetBSD: ne2000.c,v 1.59.10.1 2010/11/20 00:33:44 riz Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -48,10 +48,12 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ne2000.c,v 1.59 2008/04/28 20:23:50 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ne2000.c,v 1.59.10.1 2010/11/20 00:33:44 riz Exp $");
 
 #include "opt_ipkdb.h"
 
+#include "rtl80x9.h"
+
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
@@ -85,6 +87,9 @@
 #include <dev/ic/ne2000reg.h>
 #include <dev/ic/ne2000var.h>
 
+#include <dev/ic/rtl80x9reg.h>
+#include <dev/ic/rtl80x9var.h>
+
 #include <dev/ic/ax88190reg.h>
 
 int	ne2000_write_mbuf(struct dp8390_softc *, struct mbuf *, int);
@@ -98,6 +103,11 @@
 void	ne2000_readmem(bus_space_tag_t, bus_space_handle_t,
 	    bus_space_tag_t, bus_space_handle_t, int, u_int8_t *, size_t, int);
 
+#ifdef NE2000_DETECT_8BIT
+static bool	ne2000_detect_8bit(bus_space_tag_t, bus_space_handle_t,
+		    bus_space_tag_t, bus_space_handle_t);
+#endif
+
 #define	ASIC_BARRIER(asict, asich) \
 	bus_space_barrier((asict), (asich), 0, 0x10, \
 	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
@@ -113,7 +123,7 @@
 	bus_space_tag_t asict = nsc->sc_asict;
 	bus_space_handle_t asich = nsc->sc_asich;
 	u_int8_t romdata[16];
-	int memsize, i, useword;
+	int memstart, memsize, i, useword;
 
 	/*
 	 * Detect it again unless caller specified it; this gives us
@@ -132,23 +142,46 @@
 		aprint_error_dev(dsc->sc_dev, "where did the card go?\n");
 		return (1);
 	case NE2000_TYPE_NE1000:
+		memstart = 8192;
 		memsize = 8192;
 		useword = 0;
 		break;
 	case NE2000_TYPE_NE2000:
 	case NE2000_TYPE_AX88190:		/* XXX really? */
 	case NE2000_TYPE_AX88790:
-		memsize = 8192 * 2;
+#if NRTL80X9 > 0
+	case NE2000_TYPE_RTL8019:
+#endif
+		memstart = 16384;
+		memsize = 16384;
 		useword = 1;
+		if (
+#ifdef NE2000_DETECT_8BIT
+		    ne2000_detect_8bit(nict, nich, asict, asich) ||
+#endif
+		    (nsc->sc_quirk & NE2000_QUIRK_8BIT) != 0) {
+			/* in 8 bit mode, only 8KB memory can be used */
+			memsize = 8192;
+			useword = 0;
+		}
 		break;
 	case NE2000_TYPE_DL10019:
 	case NE2000_TYPE_DL10022:
+		memstart = 8192 * 3;
 		memsize = 8192 * 3;
 		useword = 1;
 		break;
 	}
 
 	nsc->sc_useword = useword;
+#if NRTL80X9 > 0
+	if (nsc->sc_type == NE2000_TYPE_RTL8019) {
+		dsc->init_card = rtl80x9_init_card;
+		dsc->sc_media_init = rtl80x9_media_init;
+		dsc->sc_mediachange = rtl80x9_mediachange;
+		dsc->sc_mediastatus = rtl80x9_mediastatus;
+	}
+#endif
 
 	dsc->cr_proto = ED_CR_RD2;
 	if (nsc->sc_type == NE2000_TYPE_AX88190 ||
@@ -180,16 +213,14 @@
 	/*
 	 * NIC memory doens't start at zero on an NE board.
 	 * The start address is tied to the bus width.
-	 * (It happens to be computed the same way as mem size.)
 	 */
-	dsc->mem_start = memsize;
-
 #ifdef GWETHER
 	{
-		int x, mstart = 0;
+		int x;
 		int8_t pbuf0[ED_PAGE_SIZE], pbuf[ED_PAGE_SIZE],
 		    tbuf[ED_PAGE_SIZE];
 
+		memstart = 0;
 		for (i = 0; i < ED_PAGE_SIZE; i++)
 			pbuf0[i] = 0;
 
@@ -209,14 +240,14 @@
 				    x << ED_PAGE_SHIFT, tbuf, ED_PAGE_SIZE,
 				    useword);
 				if (memcmp(pbuf, tbuf, ED_PAGE_SIZE) == 0) {
-					mstart = x << ED_PAGE_SHIFT;
+					memstart = x << ED_PAGE_SHIFT;
 					memsize = ED_PAGE_SIZE;
 					break;
 				}
 			}
 		}
 
-		if (mstart == 0) {
+		if (memstart == 0) {
 			aprint_error_dev(&dsc->sc_dev, "cannot find start of RAM\n");
 			return (1);
 		}
@@ -245,11 +276,10 @@
 		}
 
 		printf("%s: RAM start 0x%x, size %d\n",
-		    device_xname(&dsc->sc_dev), mstart, memsize);
-
-		dsc->mem_start = mstart;
+		    device_xname(&dsc->sc_dev), memstart, memsize);
 	}
 #endif /* GWETHER */
+	dsc->mem_start = memstart;
 
 	dsc->mem_size = memsize;
 
@@ -263,17 +293,20 @@
 			    ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
 			NIC_BARRIER(nict, nich);
 			/* Select word transfer. */
-			bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_WTS);
+			bus_space_write_1(nict, nich, ED_P0_DCR,
+			    useword ? ED_DCR_WTS : 0);
 			NIC_BARRIER(nict, nich);
 			ne2000_readmem(nict, nich, asict, asich,
 			    AX88190_NODEID_OFFSET, dsc->sc_enaddr,
 			    ETHER_ADDR_LEN, useword);
 		} else {
+			bool ne1000 = (nsc->sc_type == NE2000_TYPE_NE1000);
+
 			ne2000_readmem(nict, nich, asict, asich, 0, romdata,
 			    sizeof(romdata), useword);
 			for (i = 0; i < ETHER_ADDR_LEN; i++)
 				dsc->sc_enaddr[i] =
-				    romdata[i * (useword ? 2 : 1)];
+				    romdata[i * (ne1000 ? 1 : 2)];
 		}
 	} else
 		memcpy(dsc->sc_enaddr, myea, sizeof(dsc->sc_enaddr));
@@ -291,13 +324,6 @@
 		return (1);
 	}
 
-	/*
-	 * We need to compute mem_ring a bit differently; override the
-	 * value set up in dp8390_config().
-	 */
-	dsc->mem_ring =
-	    dsc->mem_start + ((dsc->txb_cnt * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
-
 	return (0);
 }
 
@@ -314,6 +340,7 @@
 	static u_int8_t test_pattern[32] = "THIS is A memory TEST pattern";
 	u_int8_t test_buffer[32], tmp;
 	int i, rv = NE2000_TYPE_UNKNOWN;
+	int useword;
 
 	/* Reset the board. */
 #ifdef GWETHER
@@ -428,41 +455,96 @@
 	ne2000_readmem(nict, nich, asict, asich, 8192, test_buffer,
 	    sizeof(test_buffer), 0);
 
-	if (memcmp(test_pattern, test_buffer, sizeof(test_pattern))) {
-		/* not an NE1000 - try NE2000 */
-		bus_space_write_1(nict, nich, ED_P0_DCR,
-		    ED_DCR_WTS | ED_DCR_FT1 | ED_DCR_LS);
-		bus_space_write_1(nict, nich, ED_P0_PSTART,
-		    16384 >> ED_PAGE_SHIFT);
-		bus_space_write_1(nict, nich, ED_P0_PSTOP,
-		    32768 >> ED_PAGE_SHIFT);
-
-		/*
-		 * Write the test pattern in word mode.  If this also fails,
-		 * then we don't know what this board is.
-		 */
-		ne2000_writemem(nict, nich, asict, asich, test_pattern, 16384,
-		    sizeof(test_pattern), 1, 0);
-		ne2000_readmem(nict, nich, asict, asich, 16384, test_buffer,
-		    sizeof(test_buffer), 1);
-
-		if (memcmp(test_pattern, test_buffer, sizeof(test_pattern)))
-			goto out;	/* not an NE2000 either */
-
-		rv = NE2000_TYPE_NE2000;
-	} else {
+	if (memcmp(test_pattern, test_buffer, sizeof(test_pattern)) == 0) {
 		/* We're an NE1000. */
 		rv = NE2000_TYPE_NE1000;
+		goto out;
 	}
 
+	/* not an NE1000 - try NE2000 */
+
+	/* try 16 bit mode first */
+	useword = 1;
+
+#ifdef NE2000_DETECT_8BIT
+	/*
+	 * Check bus type in EEPROM first because some NE2000 compatible wedges
+	 * on 16 bit DMA access if the chip is configured in 8 bit mode.
+	 */
+	if (ne2000_detect_8bit(nict, nich, asict, asich))
+		useword = 0;
+#endif
+ again:
+	bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS |
+	    (useword ? ED_DCR_WTS : 0));
+	bus_space_write_1(nict, nich, ED_P0_PSTART, 16384 >> ED_PAGE_SHIFT);
+	bus_space_write_1(nict, nich, ED_P0_PSTOP,
+	    (16384 + (useword ? 16384 : 8192)) >> ED_PAGE_SHIFT);
+
+	/*
+	 * Write the test pattern in word mode.  If this also fails,
+	 * then we don't know what this board is.
+	 */
+	ne2000_writemem(nict, nich, asict, asich, test_pattern, 16384,
+	    sizeof(test_pattern), useword, 1);
+	ne2000_readmem(nict, nich, asict, asich, 16384, test_buffer,
+	    sizeof(test_buffer), useword);
+
+	if (memcmp(test_pattern, test_buffer, sizeof(test_pattern)) != 0) {
+		if (useword == 1) {
+			/* try 8 bit mode */
+			useword = 0;
+			goto again;
+		}
+		return NE2000_TYPE_UNKNOWN;	/* not an NE2000 either */
+	}
+
+	rv = NE2000_TYPE_NE2000;
+
+#if NRTL80X9 > 0
+	/* Check for a Realtek RTL8019. */
+	if (bus_space_read_1(nict, nich, NERTL_RTL0_8019ID0) == RTL0_8019ID0 &&
+	    bus_space_read_1(nict, nich, NERTL_RTL0_8019ID1) == RTL0_8019ID1)
+		rv = NE2000_TYPE_RTL8019;
+#endif
+
+ out:
 	/* Clear any pending interrupts that might have occurred above. */
 	NIC_BARRIER(nict, nich);
 	bus_space_write_1(nict, nich, ED_P0_ISR, 0xff);
 
- out:
 	return (rv);
 }
 
+#ifdef NE2000_DETECT_8BIT
+static bool
+ne2000_detect_8bit(bus_space_tag_t nict, bus_space_handle_t nich,
+    bus_space_tag_t asict, bus_space_handle_t asich)
+{
+	bool is8bit;
+	uint8_t romdata[32];
+
+	is8bit = false;
+
+	/* Set DCR for 8 bit DMA. */
+	bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
+	/* Read PROM area. */
+	ne2000_readmem(nict, nich, asict, asich, 0, romdata,
+	    sizeof(romdata), 0);
+	if (romdata[28] == 'B' && romdata[30] == 'B') {
+		/* 'B' (0x42) in 8 bit mode, 'W' (0x57) in 16 bit mode */
+		is8bit = true;
+	} 
+	if (!is8bit) {
+		/* not in 8 bit mode; put back DCR setting for 16 bit DMA */
+		bus_space_write_1(nict, nich, ED_P0_DCR,
+		    ED_DCR_FT1 | ED_DCR_LS | ED_DCR_WTS);
+	}
+
+	return is8bit;
+}
+#endif
+
 /*
  * Write an mbuf chain to the destination NIC memory address using programmed
  * I/O.
@@ -519,8 +601,8 @@
 	 * so that case requires some extra code to patch over odd-length
 	 * mbufs.
 	 */
-	if (nsc->sc_type == NE2000_TYPE_NE1000) {
-		/* NE1000s are easy. */
+	if (nsc->sc_useword == 0) {
+		/* byte ops are easy. */
 		for (; m != 0; m = m->m_next) {
 			if (m->m_len) {
 				bus_space_write_multi_1(asict, asich,
@@ -534,7 +616,7 @@
 				    NE2000_ASIC_DATA, 0);
 		}
 	} else {
-		/* NE2000s are a bit trickier. */
+		/* word ops are a bit trickier. */
 		u_int8_t *data, savebyte[2];
 		int l, leftover;
 #ifdef DIAGNOSTIC
@@ -729,8 +811,7 @@
 	NIC_BARRIER(nict, nich);
 
 	/* Round up to a word. */
-	if (amount & 1)
-		++amount;
+	amount = roundup2(amount, sizeof(uint16_t));
 
 	/* Set up DMA byte count. */
 	bus_space_write_1(nict, nich, ED_P0_RBCR0, amount);
@@ -840,6 +921,8 @@
 	struct dp8390_softc *dp = &np->sc_dp8390;
 	bus_space_tag_t nict = dp->sc_regt;
 	bus_space_handle_t nich = dp->sc_regh;
+	bus_space_tag_t asict = np->sc_asict;
+	bus_space_handle_t asich = np->sc_asich;
 	int i, useword;
 
 #ifdef GWETHER
@@ -847,59 +930,84 @@
 	return -1;
 #endif
 
-	if (np->sc_type == 0)
-		np->sc_type = ne2000_detect(nict, nich,
-			np->sc_asict, np->sc_asich);
-	if (np->sc_type == 0)
+	if (np->sc_type == NE2000_TYPE_UNKNOWN)
+		np->sc_type = ne2000_detect(nict, nich, asict, asich);
+	if (np->sc_type == NE2000_TYPE_UNKNOWN)
 		return -1;
 
-	useword = np->sc_useword;
-
-	dp->cr_proto = ED_CR_RD2;
-	dp->dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (useword ? ED_DCR_WTS : 0);
-	dp->rcr_proto = 0;
-
-	dp->test_mem = ne2000_test_mem;
-	dp->ring_copy = ne2000_ring_copy;
-	dp->write_mbuf = ne2000_write_mbuf;
-	dp->read_hdr = ne2000_read_hdr;
-
-	for (i = 0; i < 16; i++)
-		dp->sc_reg_map[i] = i;
-
 	switch (np->sc_type) {
 	case NE2000_TYPE_NE1000:
-		dp->mem_start = dp->mem_size = 8192;
+		dp->mem_start = 8192;
+		dp->mem_size = 8192;
+		useword = 0;
 		kip->name = "ne1000";
 		break;
 	case NE2000_TYPE_NE2000:
-		dp->mem_start = dp->mem_size = 8192 * 2;
-		kip->name = "ne2000";
+	case NE2000_TYPE_AX88190:
+	case NE2000_TYPE_AX88790:
+#if NRTL80X9 > 0
+	case NE2000_TYPE_RTL8019:
+#endif
+		dp->mem_start = 16384;
+		dp->mem_size = 16384;
+		useword = 1;
+		if (
+#ifdef NE2000_DETECT_8BIT
+		    ne2000_detect_8bit(nict, nich, asict, asich) ||
+#endif
+		    (np->sc_quirk & NE2000_QUIRK_8BIT) != 0) {
+			/* in 8 bit mode, only 8KB memory can be used */
+			dp->mem_size = 8192;
+			useword = 0;
+		}
+		kip->name =
+		    (np->sc_type == NE2000_TYPE_AX88190 ||
+		     np->sc_type == NE2000_TYPE_AX88790) ?
+		    "ax88190" : "ne2000";
 		break;
 	case NE2000_TYPE_DL10019:
 	case NE2000_TYPE_DL10022:
-		dp->mem_start = dp->mem_size = 8192 * 3;
+		dp->mem_start = 8192 * 3;
+		dp->mem_size = 8192 * 3;
+		useword = 1;
 		kip->name = (np->sc_type == NE2000_TYPE_DL10019) ?
 		    "dl10022" : "dl10019";
 		break;
-	case NE2000_TYPE_AX88190:
-	case NE2000_TYPE_AX88790:
-		dp->rcr_proto = ED_RCR_INTT;
-		dp->sc_flags |= DP8390_DO_AX88190_WORKAROUND;
-		dp->mem_start = dp->mem_size = 8192 * 2;
-		kip->name = "ax88190";
-		break;
 	default:
 		return -1;
 		break;
 	}
 
+	np->sc_useword = useword;
+#if NRTL80X9 > 0
+	if (np->sc_type == NE2000_TYPE_RTL8019) {
+		dp->init_card = rtl80x9_init_card;
+		dp->sc_media_init = rtl80x9_media_init;
+		dp->sc_mediachange = rtl80x9_mediachange;
+		dp->sc_mediastatus = rtl80x9_mediastatus;
+	}
+#endif
+
+	dp->cr_proto = ED_CR_RD2;
+	if (np->sc_type == NE2000_TYPE_AX88190 ||
+	    np->sc_type == NE2000_TYPE_AX88790) {
+		dp->rcr_proto = ED_RCR_INTT;
+		dp->sc_flags |= DP8390_DO_AX88190_WORKAROUND;
+	} else
+		dp->rcr_proto = 0;
+	dp->dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (useword ? ED_DCR_WTS : 0);
+
+	dp->test_mem = ne2000_test_mem;
+	dp->ring_copy = ne2000_ring_copy;
+	dp->write_mbuf = ne2000_write_mbuf;
+	dp->read_hdr = ne2000_read_hdr;
+
+	for (i = 0; i < 16; i++)
+		dp->sc_reg_map[i] = i;
+
 	if (dp8390_ipkdb_attach(kip))
 		return -1;
 
-	dp->mem_ring = dp->mem_start
-		+ ((dp->txb_cnt * ED_TXBUF_SIZE) << ED_PAGE_SHIFT);
-
 	if (!(kip->flags & IPKDB_MYHW)) {
 		char romdata[16];
 
@@ -912,15 +1020,19 @@
 				ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
 			NIC_BARRIER(nict, nich);
 			/* Select word transfer */
-			bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_WTS);
-			ne2000_readmem(nict, nich, np->sc_asict, np->sc_asich,
+			bus_space_write_1(nict, nich, ED_P0_DCR,
+			    useword ? ED_DCR_WTS : 0);
+			ne2000_readmem(nict, nich, asict, asich,
 				AX88190_NODEID_OFFSET, kip->myenetaddr,
 				ETHER_ADDR_LEN, useword);
 		} else {
-			ne2000_readmem(nict, nich, np->sc_asict, np->sc_asich,
+			bool ne1000 = (np->sc_type == NE2000_TYPE_NE1000);
+
+			ne2000_readmem(nict, nich, asict, asich,
 				0, romdata, sizeof romdata, useword);
 			for (i = 0; i < ETHER_ADDR_LEN; i++)
-				kip->myenetaddr[i] = romdata[i << useword];
+				kip->myenetaddr[i] =
+				    romdata[i * (ne1000 ? 1 : 2)];
 		}
 		kip->flags |= IPKDB_MYHW;
 

Index: src/sys/dev/ic/ne2000var.h
diff -u src/sys/dev/ic/ne2000var.h:1.19 src/sys/dev/ic/ne2000var.h:1.19.10.1
--- src/sys/dev/ic/ne2000var.h:1.19	Mon Apr 28 20:23:50 2008
+++ src/sys/dev/ic/ne2000var.h	Sat Nov 20 00:33:44 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: ne2000var.h,v 1.19 2008/04/28 20:23:50 martin Exp $	*/
+/*	$NetBSD: ne2000var.h,v 1.19.10.1 2010/11/20 00:33:44 riz Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -46,9 +46,12 @@
 		NE2000_TYPE_DL10019,
 		NE2000_TYPE_DL10022,
 		NE2000_TYPE_AX88190,
-		NE2000_TYPE_AX88790
+		NE2000_TYPE_AX88790,
+		NE2000_TYPE_RTL8019
 	} sc_type;
 	int sc_useword;
+	u_int sc_quirk;			/* quirks passed from attachments */
+#define	NE2000_QUIRK_8BIT	0x0001	/* force 8bit mode even on NE2000 */
 };
 
 int	ne2000_attach(struct ne2000_softc *, u_int8_t *);

Index: src/sys/dev/isa/if_ne_isa.c
diff -u src/sys/dev/isa/if_ne_isa.c:1.26 src/sys/dev/isa/if_ne_isa.c:1.26.10.1
--- src/sys/dev/isa/if_ne_isa.c:1.26	Mon Apr 28 20:23:52 2008
+++ src/sys/dev/isa/if_ne_isa.c	Sat Nov 20 00:33:47 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ne_isa.c,v 1.26 2008/04/28 20:23:52 martin Exp $	*/
+/*	$NetBSD: if_ne_isa.c,v 1.26.10.1 2010/11/20 00:33:47 riz Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ne_isa.c,v 1.26 2008/04/28 20:23:52 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ne_isa.c,v 1.26.10.1 2010/11/20 00:33:47 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -57,9 +57,6 @@
 #include <dev/ic/ne2000reg.h>
 #include <dev/ic/ne2000var.h>
 
-#include <dev/ic/rtl80x9reg.h>
-#include <dev/ic/rtl80x9var.h>
-
 #include <dev/isa/isavar.h>
 
 int	ne_isa_match(device_t, cfdata_t, void *);
@@ -178,21 +175,10 @@
 
 	case NE2000_TYPE_NE2000:
 		typestr = "NE2000";
-		/*
-		 * Check for a Realtek 8019.
-		 */
-		bus_space_write_1(nict, nich, ED_P0_CR,
-		    ED_CR_PAGE_0 | ED_CR_STP);
-		if (bus_space_read_1(nict, nich, NERTL_RTL0_8019ID0) ==
-								RTL0_8019ID0 &&
-		    bus_space_read_1(nict, nich, NERTL_RTL0_8019ID1) ==
-								RTL0_8019ID1) {
-			typestr = "NE2000 (RTL8019)";
-			dsc->sc_mediachange = rtl80x9_mediachange;
-			dsc->sc_mediastatus = rtl80x9_mediastatus;
-			dsc->init_card = rtl80x9_init_card;
-			dsc->sc_media_init = rtl80x9_media_init;
-		}
+		break;
+
+	case NE2000_TYPE_RTL8019:
+		typestr = "NE2000 (RTL8019)";
 		break;
 
 	default:

Index: src/sys/dev/isapnp/if_ne_isapnp.c
diff -u src/sys/dev/isapnp/if_ne_isapnp.c:1.26 src/sys/dev/isapnp/if_ne_isapnp.c:1.26.10.1
--- src/sys/dev/isapnp/if_ne_isapnp.c:1.26	Mon Apr 28 20:23:53 2008
+++ src/sys/dev/isapnp/if_ne_isapnp.c	Sat Nov 20 00:33:48 2010
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_ne_isapnp.c,v 1.26 2008/04/28 20:23:53 martin Exp $	*/
+/*	$NetBSD: if_ne_isapnp.c,v 1.26.10.1 2010/11/20 00:33:48 riz Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_ne_isapnp.c,v 1.26 2008/04/28 20:23:53 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_ne_isapnp.c,v 1.26.10.1 2010/11/20 00:33:48 riz Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -57,9 +57,6 @@
 #include <dev/ic/ne2000reg.h>
 #include <dev/ic/ne2000var.h>
 
-#include <dev/ic/rtl80x9reg.h>
-#include <dev/ic/rtl80x9var.h>
-
 #include <dev/isa/isavar.h>
 
 #include <dev/isapnp/isapnpreg.h>
@@ -142,21 +139,10 @@
 
 	case NE2000_TYPE_NE2000:
 		typestr = "NE2000";
-		/*
-		 * Check for a Realtek 8019.
-		 */
-		bus_space_write_1(nict, nich, ED_P0_CR,
-		    ED_CR_PAGE_0 | ED_CR_STP);
-		if (bus_space_read_1(nict, nich, NERTL_RTL0_8019ID0) ==
-								RTL0_8019ID0 &&
-		    bus_space_read_1(nict, nich, NERTL_RTL0_8019ID1) ==
-								RTL0_8019ID1) {
-			typestr = "NE2000 (RTL8019)";
-			dsc->sc_mediachange = rtl80x9_mediachange;
-			dsc->sc_mediastatus = rtl80x9_mediastatus;
-			dsc->init_card = rtl80x9_init_card;
-			dsc->sc_media_init = rtl80x9_media_init;
-		}
+		break;
+
+	case NE2000_TYPE_RTL8019:
+		typestr = "NE2000 (RTL8019)";
 		break;
 
 	default:

Added files:

Index: src/sys/arch/atari/dev/if_ne_mb.c
diff -u /dev/null src/sys/arch/atari/dev/if_ne_mb.c:1.2.8.2
--- /dev/null	Sat Nov 20 00:33:49 2010
+++ src/sys/arch/atari/dev/if_ne_mb.c	Sat Nov 20 00:33:46 2010
@@ -0,0 +1,459 @@
+/*	$NetBSD$	*/
+
+/*
+ * Copyright (c) 2010 Izumi Tsutsui.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Device driver for the EtherNEC,
+ * NE2000 in 8bit mode over Atari ROM cartridge slot.
+ * http://hardware.atari.org/ether/
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/kernel.h>
+#include <sys/callout.h>
+
+#include <sys/bus.h>
+#include <sys/intr.h>
+
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+
+#include <machine/cpu.h>
+#include <machine/iomap.h>
+
+#include <atari/atari/device.h>
+
+#include <dev/ic/dp8390reg.h>
+#include <dev/ic/dp8390var.h>
+#include <dev/ic/ne2000reg.h>
+#include <dev/ic/ne2000var.h>
+
+/*
+ * EtherNEC specific address configuration
+ */
+
+/* I/O read ops are through /ROM4 area (0xFA0000) */
+#define AD_CART_ROM4		(AD_CART + 0x00000)
+#define ETHERNEC_READ_PORT	AD_CART_ROM4
+
+/* I/O write ops are through /ROM3 area (0xFB0000) */
+#define AD_CART_ROM3		(AD_CART + 0x10000)
+#define ETHERNEC_WRITE_PORT	AD_CART_ROM3
+
+/* CPU address lines A13-A9 are connected to ISA A4-A0 */
+#define ETHERNEC_PORT_STRIDE	9
+
+/* Using A8-A1 lines to specify write data (no A0 but UDS/LDS on m68k) */
+#define ETHERNEC_WR_ADDR_SHIFT	1
+
+/* interrupt polling per HZ */
+#define ETHERNEC_TICK		1
+
+static int  ne_mb_probe(device_t, cfdata_t, void *);
+static void ne_mb_attach(device_t, device_t, void *);
+
+static void ne_mb_poll(void *);
+
+static bus_space_tag_t ethernec_init_bus_space_tag(bus_space_tag_t);
+static void    ethernec_bus_space_unimpl(void);
+
+static int     ethernec_bus_space_peek_1(bus_space_tag_t, bus_space_handle_t,
+    bus_size_t);
+static uint8_t ethernec_bus_space_read_1(bus_space_tag_t, bus_space_handle_t,
+    bus_size_t);
+static void    ethernec_bus_space_write_1(bus_space_tag_t, bus_space_handle_t,
+    bus_size_t, uint8_t);
+static void    ethernec_bus_space_read_multi_1(bus_space_tag_t,
+    bus_space_handle_t, bus_size_t, uint8_t *, bus_size_t);
+static void    ethernec_bus_space_read_multi_2(bus_space_tag_t,
+    bus_space_handle_t, bus_size_t, uint16_t *, bus_size_t);
+static void    ethernec_bus_space_write_multi_1(bus_space_tag_t,
+    bus_space_handle_t, bus_size_t, const uint8_t *, bus_size_t);
+static void    ethernec_bus_space_write_multi_2(bus_space_tag_t,
+    bus_space_handle_t, bus_size_t, const uint16_t *, bus_size_t);
+
+struct ne_mb_softc {
+	struct ne2000_softc sc_ne2000;		/* MI ne2000 softc */
+
+	struct atari_bus_space sc_bs;
+	struct callout sc_poll;
+};
+
+CFATTACH_DECL_NEW(ne_mb, sizeof(struct ne_mb_softc),
+    ne_mb_probe, ne_mb_attach, NULL, NULL);
+
+static int
+ne_mb_probe(device_t parent, cfdata_t cf, void *aux)
+{
+	static bool ne_matched = false;
+	struct atari_bus_space bs;
+	bus_space_tag_t iot, asict;
+	bus_space_handle_t ioh, iowh, asich;
+	int netype, rv;
+
+	rv = 0;
+
+	if (!atari_realconfig)
+		goto out;
+	if (strcmp("ne", aux) || ne_matched)
+		goto out;
+
+	iot = ethernec_init_bus_space_tag(&bs);
+
+	/* map I/O space for read ops */
+	if (bus_space_map(iot, ETHERNEC_READ_PORT,
+	    NE2000_NPORTS << ETHERNEC_PORT_STRIDE, 0, &ioh) != 0)
+		goto out;
+
+	/* map I/O space for write ops */
+	if (bus_space_map(iot, ETHERNEC_WRITE_PORT,
+	    NE2000_NPORTS << ETHERNEC_PORT_STRIDE, 0, &iowh) != 0)
+		goto out1;
+
+	/* XXX abuse stride for offset of write ports from read ones */
+	iot->stride =
+	    (vaddr_t)bus_space_vaddr(iot, iowh) -
+	    (vaddr_t)bus_space_vaddr(iot, ioh);
+
+	/* check if register regions are vaild */
+	if (bus_space_peek_1(iot, ioh, 0) == 0)
+		goto out2;
+
+	asict = iot;
+	if (bus_space_subregion(iot, ioh,
+	    NE2000_ASIC_OFFSET << ETHERNEC_PORT_STRIDE,
+	    NE2000_ASIC_NPORTS << ETHERNEC_PORT_STRIDE, &asich))
+		goto out2;
+
+	/* Look for an NE2000 compatible card */
+	netype = ne2000_detect(iot, ioh, asict, asich);
+	switch (netype) {
+	/* XXX should we reject non RTL8019 variants? */
+	case NE2000_TYPE_NE1000:
+	case NE2000_TYPE_NE2000:
+	case NE2000_TYPE_RTL8019:
+		ne_matched = true;
+		rv = 1;
+		break;
+	default:
+		break;
+	}
+
+ out2:
+	bus_space_unmap(iot, iowh, NE2000_NPORTS << ETHERNEC_PORT_STRIDE);
+ out1:
+	bus_space_unmap(iot, ioh, NE2000_NPORTS << ETHERNEC_PORT_STRIDE);
+ out:
+	return rv;
+}
+
+static void
+ne_mb_attach(device_t parent, device_t self, void *aux)
+{
+	struct ne_mb_softc *sc = device_private(self);
+	struct ne2000_softc *nsc = &sc->sc_ne2000;
+	struct dp8390_softc *dsc = &nsc->sc_dp8390;
+	bus_space_tag_t iot, asict;
+	bus_space_handle_t ioh, iowh, asich;
+	const char *typestr;
+	int netype;
+
+	dsc->sc_dev = self;
+	aprint_normal(": EtherNEC on Atari ROM cartridge slot\n");
+
+	iot = ethernec_init_bus_space_tag(&sc->sc_bs);
+
+	/* map I/O space for read ops */
+	if (bus_space_map(iot, ETHERNEC_READ_PORT,
+	    NE2000_NPORTS << ETHERNEC_PORT_STRIDE, 0, &ioh) != 0)
+		goto out;
+
+	/* map I/O space for write ops */
+	if (bus_space_map(iot, ETHERNEC_WRITE_PORT,
+	    NE2000_NPORTS << ETHERNEC_PORT_STRIDE, 0, &iowh) != 0)
+		goto out1;
+
+	/* XXX abuse stride */
+	iot->stride =
+	    (vaddr_t)bus_space_vaddr(iot, iowh) -
+	    (vaddr_t)bus_space_vaddr(iot, ioh);
+
+	asict = iot;
+	if (bus_space_subregion(iot, ioh,
+	    NE2000_ASIC_OFFSET << ETHERNEC_PORT_STRIDE,
+	    NE2000_ASIC_NPORTS << ETHERNEC_PORT_STRIDE, &asich))
+		goto out2;
+
+	dsc->sc_regt = iot;
+	dsc->sc_regh = ioh;
+
+	nsc->sc_asict = asict;
+	nsc->sc_asich = asich;
+
+	/* EtherNEC uses 8-bit data bus */
+	nsc->sc_quirk = NE2000_QUIRK_8BIT;
+
+	/*
+	 * detect it again, so we can print some information about
+	 * the interface.
+	 * XXX: Should we accept only RTL8019?
+	 */
+	netype = ne2000_detect(iot, ioh, asict, asich);
+	switch (netype) {
+	case NE2000_TYPE_NE1000:
+		typestr = "NE1000";
+		break;
+
+	case NE2000_TYPE_NE2000:
+		typestr = "NE2000";
+		break;
+
+	case NE2000_TYPE_RTL8019:
+		typestr = "NE2000 (RTL8019)";
+		break;
+
+	default:
+		aprint_error_dev(self, "where did the card go?!\n");
+		goto out2;
+	}
+
+	aprint_normal_dev(self, "%s Ethernet (8-bit)\n", typestr);
+
+	/* this interface is always enabled */
+	dsc->sc_enabled = 1;
+
+	/* call MI ne2000 attach function */
+	ne2000_attach(nsc, NULL);
+
+	/* emulate interrupts by callout(9) */
+	aprint_normal_dev(self, "using %d Hz polling\n", hz / ETHERNEC_TICK);
+	callout_init(&sc->sc_poll, 0);
+	callout_reset(&sc->sc_poll, ETHERNEC_TICK, ne_mb_poll, sc);
+
+	return;
+
+ out2:
+	bus_space_unmap(iot, iowh, NE2000_NPORTS << ETHERNEC_PORT_STRIDE);
+ out1:
+	bus_space_unmap(iot, ioh, NE2000_NPORTS << ETHERNEC_PORT_STRIDE);
+ out:
+	return;
+}
+
+static void
+ne_mb_poll(void *arg)
+{
+	struct ne_mb_softc *sc;
+	struct ne2000_softc *nsc;
+	struct dp8390_softc *dsc;
+	int s;
+
+	sc = arg;
+	nsc = &sc->sc_ne2000;
+	dsc = &nsc->sc_dp8390;
+
+	s = splnet();
+	(void)dp8390_intr(dsc);
+	splx(s);
+
+	callout_schedule(&sc->sc_poll, ETHERNEC_TICK);
+}
+
+/*
+ * bus_space(9) functions for EtherNEC
+ *
+ *  XXX: should these belong to an independent cartridge slot bus?
+ */
+static bus_space_tag_t
+ethernec_init_bus_space_tag(bus_space_tag_t en_t)
+{
+
+	if (en_t == NULL)
+		return NULL;
+
+	memset(en_t, 0, sizeof(*en_t));
+
+	/* XXX: implement functions used by MI ne2000 and dp8390 only */
+	en_t->abs_p_1   = ethernec_bus_space_peek_1;
+	en_t->abs_p_2   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_p_4   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_p_8   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_r_1   = ethernec_bus_space_read_1;
+	en_t->abs_r_2   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_r_4   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_r_8   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rs_1  = ethernec_bus_space_read_1;
+	en_t->abs_rs_2  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rs_4  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rs_8  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rm_1  = ethernec_bus_space_read_multi_1;
+	en_t->abs_rm_2  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rm_4  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rm_8  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rms_1 = ethernec_bus_space_read_multi_1;
+	en_t->abs_rms_2 = ethernec_bus_space_read_multi_2;	/* XXX dummy */
+	en_t->abs_rms_4 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rms_8 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rr_1  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rr_2  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rr_4  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rr_8  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rrs_1 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rrs_2 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rrs_4 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_rrs_8 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_w_1   = ethernec_bus_space_write_1;
+	en_t->abs_w_2   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_w_4   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_w_8   = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_ws_1  = ethernec_bus_space_write_1;
+	en_t->abs_ws_2  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_ws_4  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_ws_8  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wm_1  = ethernec_bus_space_write_multi_1;
+	en_t->abs_wm_2  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wm_4  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wm_8  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wms_1 = ethernec_bus_space_write_multi_1;
+	en_t->abs_wms_2 = ethernec_bus_space_write_multi_2;	/* XXX dummy */
+	en_t->abs_wms_4 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wms_8 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wr_1  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wr_2  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wr_4  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wr_8  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wrs_1 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wrs_2 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wrs_4 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_wrs_8 = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_sm_1  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_sm_2  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_sm_4  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_sm_8  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_sr_1  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_sr_2  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_sr_4  = (void *)ethernec_bus_space_unimpl;
+	en_t->abs_sr_8  = (void *)ethernec_bus_space_unimpl;
+
+	return en_t;
+}
+
+static void
+ethernec_bus_space_unimpl(void)
+{
+
+	panic("%s: unimplemented EtherNEC bus_space(9) function called",
+	    __func__);
+}
+
+static int
+ethernec_bus_space_peek_1(bus_space_tag_t bt, bus_space_handle_t bh,
+    bus_size_t reg)
+{
+	uint8_t *va;
+
+	va = (uint8_t *)(bh + (reg << ETHERNEC_PORT_STRIDE));
+
+	return !badbaddr(va, sizeof(uint8_t));
+}
+
+static uint8_t
+ethernec_bus_space_read_1(bus_space_tag_t bt, bus_space_handle_t bh,
+    bus_size_t reg)
+{
+	volatile uint8_t *ba;
+
+	ba = (volatile uint8_t *)(bh + (reg << ETHERNEC_PORT_STRIDE));
+
+	return *ba;
+}
+
+static void
+ethernec_bus_space_write_1(bus_space_tag_t bt, bus_space_handle_t bh,
+    bus_size_t reg, uint8_t val)
+{
+	volatile uint8_t *wport;
+
+	/*
+	 * Write ops are done by read against write region (ROM3) address.
+	 * 8-bit write data is specified via lower address bits.
+	 */
+	wport = (volatile uint8_t *)(bh +
+	    bt->stride + (reg << ETHERNEC_PORT_STRIDE));
+	wport += (u_int)val << ETHERNEC_WR_ADDR_SHIFT;
+
+	(void)*wport;
+}
+
+static void
+ethernec_bus_space_read_multi_1(bus_space_tag_t bt, bus_space_handle_t bh,
+    bus_size_t reg, uint8_t *a, bus_size_t c)
+{
+	volatile uint8_t *ba;
+
+	ba = (volatile uint8_t *)(bh + (reg << ETHERNEC_PORT_STRIDE));
+	for (; c != 0; c--)
+		*a++ = *ba;
+}
+
+static void
+ethernec_bus_space_read_multi_2(bus_space_tag_t bt, bus_space_handle_t bh,
+    bus_size_t reg, uint16_t *a, bus_size_t c)
+{
+
+	/* XXX: dummy function for probe ops in ne2000_detect() */
+}
+
+static void
+ethernec_bus_space_write_multi_1(bus_space_tag_t bt, bus_space_handle_t bh,
+    bus_size_t reg, const uint8_t *a, bus_size_t c)
+{
+	volatile uint8_t *ba, *wport;
+	u_int val;
+
+	ba = (volatile uint8_t *)(bh +
+	    bt->stride + (reg << ETHERNEC_PORT_STRIDE));
+
+	for (; c != 0; c--) {
+		val = *a++;
+		wport = ba + (val << ETHERNEC_WR_ADDR_SHIFT);
+		(void)*wport;
+	}
+}
+
+static void
+ethernec_bus_space_write_multi_2(bus_space_tag_t bt, bus_space_handle_t bh,
+    bus_size_t reg, const uint16_t *a, bus_size_t c)
+{
+
+	/* XXX: dummy function for probe ops in ne2000_detect() */
+}

Reply via email to