tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

NE2000 driver fixes for 8bit mode



Hi,

Currently I'm looking at the NE2000 driver to support Atari's EtherNEC,
which uses RTL8019AS in 8 bit mode connected to the ROM cartridge slot:
http://hardware.atari.org/ether/
(though I don't have the actual hardware yet)

Last year, Nonaka-san added 8 bit bus width support to NE2000 driver:
 http://mail-index.NetBSD.org/tech-kern/2009/05/04/msg005019.html
 http://mail-index.NetBSD.org/tech-kern/2009/05/05/msg005025.html

But there is no actual bus attachment which use 8 bit mode, and
it looks more changes are required.


In current code, bus attachments can explicitly specify
NE2000 8 bit mode via nsc->sc_dmawidth member in ne2000_softc.
If NE2000_DMAWIDTH_8BIT is specified, the ED_DCR_WTS bit
in the DCR is cleared and 8 bit DMA is used:

---
        dsc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
            ((dmawidth == NE2000_DMAWIDTH_16BIT) ? ED_DCR_WTS : 0);
---

But even in that case, nsc->sc_useword is still set for NE2000
and 16 bit word bus_space(9) accesses are still used in
ne2000_writemem(), ne2000_readmem(), and ne2000_write_mbuf()
functions:

---
int
ne2000_write_mbuf(struct dp8390_softc *sc, struct mbuf *m, int buf)
{
        struct ne2000_softc *nsc = (struct ne2000_softc *)sc;
 :
        if (nsc->sc_type == NE2000_TYPE_NE1000) {
 :
        } else {
                /* NE2000s are a bit trickier. */
 :
                                        bus_space_write_multi_stream_2(asict,
                                            asich, NE2000_ASIC_DATA,
                                            (u_int16_t *)data, l >> 1);
 :

int
ne2000_ring_copy(struct dp8390_softc *sc, int src, void *dstv, u_short amount)
{
        struct ne2000_softc *nsc = (struct ne2000_softc *)sc;
 :
        int useword = nsc->sc_useword;
 :
        ne2000_readmem(nict, nich, asict, asich, src, (u_int8_t *)dst,
            amount, useword);
 :

ne2000_readmem(bus_space_tag_t nict, bus_space_handle_t nich,
bus_space_tag_t asict, bus_space_handle_t asich, int src, u_int8_t *dst,
size_t amount, int useword)
{

 :
        if (useword)
                bus_space_read_multi_stream_2(asict, asich, NE2000_ASIC_DATA,
                    (u_int16_t *)dst, amount >> 1);
        else
                bus_space_read_multi_1(asict, asich, NE2000_ASIC_DATA,
                    dst, amount);

---

I'm not sure how these 16 bit bus_space(9) access ops work
on Nonaka-san's machine (evbsh3?) and my ISA NE2000 boards in
XT slot (using maskingtape on 16 bit expansion pins of ISA boards),
but I have revised 8 bit support code for real 8 bit width busses.


In the attached patch, I put the following changes:

(1) Move RTL8019 probe and attach code from each bus attachment
    to MI ne2000_detect() and ne2000_attach()

--> The Realtek RTL8019 is designed for ISA (and ISAPnP),
    but nowadays it's widely used for non-ISA local bus, especially
    on embedded controllers (and some other non-PC local bus like x68k),
    so I move RTL8019 related code into MI place and also add
    "NE2000_TYPE_RTL8019" type value for sc->sc_type in ne2000_softc.

    Some MD drivers don't use rtl80x9.c (no rtl80x9 attribute in files.foo)
    so I also add "needs-flag" and necessary #if NRTL80X9 > 0 checks.

(2) Change a method for backend and attachment to specify 8 bit mode

--> In current code, sc->sc_dmawidth member is used to specify
    bus size, but I change it to use NE2000_QUIRK_8BIT bit in
    a new sc->sc_quirk member.

(3) Handle more NE2000 8 bit mode specific settings

--> Accroding to RTL8019 datasheet and Linux driver etc,
    NE2000 in 8 bit mode seems to require more settings:

  - only 8KB buffer memory can be used on NE2000 8 bit mode
    while it's 16KB in 16 bit mode
    (buffer start address is 0x4000 (16384) on both mode)
  - MAC address in PROM area is stored in the same layout in both
    8 bit and 16 bit mode on NE2000
    (only NE1000 requires the different index)
  - set sc->sc_useword for 8 bit bus_space(9) access properly
    as well as ED_DCR_WTS bit in dsc->dcr_reg for 8/16 bit DMA
  - fix ne2000_detect() to use proper useword on checking buffer memory
    on both 8/16 bit mode
  - also fix ne2000_write_mbuf() to use nsc->sc_useword
    to switch 8/16 bit bus_space(9) access rather than
    nsc->sc_type == NE2000_TYPE_NE1000 check

(4) Add a function to detect NE2000 8 bit mode

--> Per NE2000 spec, bus mode can be read from memory of EEPROM area
    at offset 0x1c. ('B' (0x42) for 8 bit, 'W' (0x57) for 16 bit mode)

    I also add a function that checks the value to detect 8 bit mode,
    but I make it optional and enabled by "options NE2000_DETECT_8BIT"
    to avoid possible regression on existing various NE2000 clones.
    (ne2000_attach() depends on some initialization in ne2000_detect())

(5) Fix ipkdb attachment accordingly

--> ne2000_ipkdb_attach() seems a bit broken (sc_useword isn't set
    in ipkdb attachment, for example) so I also fix it to sync with
    ne2000_attach(). Compile test only.

I have checked this patch on two NE2000 ISA variants
(RTL8019AS and another non-Realtek clone named UL0001)
in both 8 bit and 16 bit mode, and it works fine on i386.

Comments?

---

Index: arch/x68k/dev/if_ne_intio.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/dev/if_ne_intio.c,v
retrieving revision 1.15
diff -u -r1.15 if_ne_intio.c
--- arch/x68k/dev/if_ne_intio.c 19 Jan 2010 22:06:23 -0000      1.15
+++ arch/x68k/dev/if_ne_intio.c 26 Feb 2010 15:15:53 -0000
@@ -74,8 +74,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>
 
@@ -187,21 +185,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: arch/x68k/dev/if_ne_neptune.c
===================================================================
RCS file: /cvsroot/src/sys/arch/x68k/dev/if_ne_neptune.c,v
retrieving revision 1.19
diff -u -r1.19 if_ne_neptune.c
--- arch/x68k/dev/if_ne_neptune.c       19 Jan 2010 22:06:23 -0000      1.19
+++ arch/x68k/dev/if_ne_neptune.c       26 Feb 2010 15:15:54 -0000
@@ -72,9 +72,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 *);
@@ -165,21 +162,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: conf/files
===================================================================
RCS file: /cvsroot/src/sys/conf/files,v
retrieving revision 1.976
diff -u -r1.976 files
--- conf/files  21 Feb 2010 07:01:57 -0000      1.976
+++ conf/files  26 Feb 2010 15:15:55 -0000
@@ -901,7 +901,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: dev/ic/ne2000.c
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/ne2000.c,v
retrieving revision 1.66
diff -u -r1.66 ne2000.c
--- dev/ic/ne2000.c     24 Feb 2010 15:18:15 -0000      1.66
+++ dev/ic/ne2000.c     26 Feb 2010 19:41:27 -0000
@@ -52,6 +52,8 @@
 
 #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)
@@ -111,7 +121,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, dmawidth;
+       int memstart, memsize, i, useword;
 
        /*
         * Detect it again unless caller specified it; this gives us
@@ -130,30 +140,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;
-               dmawidth = NE2000_DMAWIDTH_8BIT;
                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;
-               dmawidth = NE2000_DMAWIDTH_16BIT;
+               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;
-               dmawidth = NE2000_DMAWIDTH_16BIT;
                break;
        }
 
        nsc->sc_useword = useword;
-       if (nsc->sc_dmawidth == NE2000_DMAWIDTH_UNKNOWN)
-               nsc->sc_dmawidth = dmawidth;
-       else
-               dmawidth = nsc->sc_dmawidth;
+#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 ||
@@ -171,8 +197,7 @@
         *
         * NE1000 gets byte-wide DMA, NE2000 gets word-wide DMA.
         */
-       dsc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
-           ((dmawidth == NE2000_DMAWIDTH_16BIT) ? ED_DCR_WTS : 0);
+       dsc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS | (useword ? ED_DCR_WTS : 0);
 
        dsc->test_mem = ne2000_test_mem;
        dsc->ring_copy = ne2000_ring_copy;
@@ -186,16 +211,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;
 
@@ -215,14 +238,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);
                }
@@ -251,11 +274,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;
 
@@ -270,17 +292,19 @@
                        NIC_BARRIER(nict, nich);
                        /* Select word transfer. */
                        bus_space_write_1(nict, nich, ED_P0_DCR,
-                           ((dmawidth == NE2000_DMAWIDTH_16BIT) ? ED_DCR_WTS : 
0));
+                           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));
@@ -310,9 +334,8 @@
        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 dmawidth = NE2000_DMAWIDTH_16BIT;
+       int useword;
 
- restart:
        /* Reset the board. */
 #ifdef GWETHER
        bus_space_write_1(asict, asich, NE2000_ASIC_RESET, 0);
@@ -426,48 +449,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_FT1 | ED_DCR_LS
-                   | ((dmawidth == NE2000_DMAWIDTH_16BIT) ? 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,
-                   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))) {
-                       if (dmawidth == NE2000_DMAWIDTH_16BIT) {
-                               /* try 8bit dma */
-                               dmawidth = NE2000_DMAWIDTH_8BIT;
-                               goto restart;
-                       }
-                       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;
-               dmawidth = NE2000_DMAWIDTH_8BIT;
+               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, 0);
+       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.
@@ -521,8 +592,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,
@@ -536,7 +607,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
@@ -814,7 +885,9 @@
        struct dp8390_softc *dp = &np->sc_dp8390;
        bus_space_tag_t nict = dp->sc_regt;
        bus_space_handle_t nich = dp->sc_regh;
-       int i, useword, dmawidth;
+       bus_space_tag_t asict = np->sc_asict;
+       bus_space_handle_t asich = np->sc_asich;
+       int i, useword;
 
 #ifdef GWETHER
        /* Not supported (yet?) */
@@ -822,54 +895,80 @@
 #endif
 
        if (np->sc_type == NE2000_TYPE_UNKNOWN)
-               np->sc_type = ne2000_detect(nict, nich,
-                       np->sc_asict, np->sc_asich);
+               np->sc_type = ne2000_detect(nict, nich, asict, asich);
        if (np->sc_type == NE2000_TYPE_UNKNOWN)
                return -1;
 
-       useword = np->sc_useword;
-       dmawidth = np->sc_dmawidth;
-
-       dp->cr_proto = ED_CR_RD2;
-       dp->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
-           ((dmawidth == NE2000_DMAWIDTH_16BIT) ? 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;
 
@@ -889,15 +988,18 @@
                        NIC_BARRIER(nict, nich);
                        /* Select word transfer */
                        bus_space_write_1(nict, nich, ED_P0_DCR,
-                           ((dmawidth == NE2000_DMAWIDTH_16BIT) ? ED_DCR_WTS : 
0));
-                       ne2000_readmem(nict, nich, np->sc_asict, np->sc_asich,
+                           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: dev/ic/ne2000var.h
===================================================================
RCS file: /cvsroot/src/sys/dev/ic/ne2000var.h,v
retrieving revision 1.23
diff -u -r1.23 ne2000var.h
--- dev/ic/ne2000var.h  8 Jan 2010 20:02:39 -0000       1.23
+++ dev/ic/ne2000var.h  26 Feb 2010 15:15:56 -0000
@@ -46,14 +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;
-       enum {
-               NE2000_DMAWIDTH_UNKNOWN = 0,
-               NE2000_DMAWIDTH_16BIT,
-               NE2000_DMAWIDTH_8BIT,
-       } sc_dmawidth;
+       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: dev/isa/if_ne_isa.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isa/if_ne_isa.c,v
retrieving revision 1.26
diff -u -r1.26 if_ne_isa.c
--- dev/isa/if_ne_isa.c 28 Apr 2008 20:23:52 -0000      1.26
+++ dev/isa/if_ne_isa.c 26 Feb 2010 15:15:57 -0000
@@ -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: dev/isapnp/if_ne_isapnp.c
===================================================================
RCS file: /cvsroot/src/sys/dev/isapnp/if_ne_isapnp.c,v
retrieving revision 1.26
diff -u -r1.26 if_ne_isapnp.c
--- dev/isapnp/if_ne_isapnp.c   28 Apr 2008 20:23:53 -0000      1.26
+++ dev/isapnp/if_ne_isapnp.c   26 Feb 2010 15:15:57 -0000
@@ -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:
 

---
Izumi Tsutsui


Home | Main Index | Thread Index | Old Index