Subject: LAN adapter driver (port-dreamcast/17493)
To: None <port-dreamcast@netbsd.org>
From: Izumi Tsutsui <tsutsui@ceres.dti.ne.jp>
List: port-dreamcast
Date: 12/24/2002 22:59:53
Hi,
MI mb86960 driver has been cleaned up enough and Christian Groessler
sent me a new patch for the SEGA LAN adapter so I think it's time
to commit it, but I'd like to ask how to implement bus_space(9)
functions for sparse address space.
In his original patch, MD attachment for the adapter has
its own bus space tag and bus_space functions in it are overridden
in the attachment, but I change them and implement a set of
bus_space(9) functions for sparse address space in g2bus_bus_mem.c.
The functions are switched by calling g2bus_set_bus_mem_sparse()
with bus_space_tag in the attachment. I guess it is not so smart
to use a function to switch bus_space_tag, but I think it's acceptable.
If there is no objection, I'll commit it on Thurseday,
but any suggestions are appreciated.
---
Izumi Tsutsui
tsutsui@ceres.dti.ne.jp
Index: conf/GENERIC
===================================================================
RCS file: /cvsroot/src/sys/arch/dreamcast/conf/GENERIC,v
retrieving revision 1.29
diff -u -r1.29 GENERIC
--- conf/GENERIC 2002/11/15 14:15:36 1.29
+++ conf/GENERIC 2002/12/23 10:00:09
@@ -166,6 +166,8 @@
rtk* at pci? dev ? function ? # SEGA Broadband Adapter
ukphy* at mii? phy ?
+mbe* at g2bus? # SEGA LAN Adapter
+
#pseudo-device cgd 2 # cryptographic disk devices
pseudo-device md 1 # memory disk device (ramdisk)
pseudo-device vnd 2 # disk-like interface to files
Index: conf/files.dreamcast
===================================================================
RCS file: /cvsroot/src/sys/arch/dreamcast/conf/files.dreamcast,v
retrieving revision 1.22
diff -u -r1.22 files.dreamcast
--- conf/files.dreamcast 2002/11/19 09:37:25 1.22
+++ conf/files.dreamcast 2002/12/23 10:00:09
@@ -91,4 +91,8 @@
file arch/dreamcast/dev/g2/gapspci_dma.c gapspci
file arch/dreamcast/dev/g2/gapspci_pci.c gapspci
+# LAN Adapter
+attach mbe at g2bus with mbe_g2bus
+file arch/dreamcast/dev/g2/if_mbe_g2.c mbe_g2bus
+
include "arch/dreamcast/conf/majors.dreamcast"
Index: dev/g2/g2bus_bus_mem.c
===================================================================
RCS file: /cvsroot/src/sys/arch/dreamcast/dev/g2/g2bus_bus_mem.c,v
retrieving revision 1.5
diff -u -r1.5 g2bus_bus_mem.c
--- dev/g2/g2bus_bus_mem.c 2002/03/03 14:31:29 1.5
+++ dev/g2/g2bus_bus_mem.c 2002/12/23 10:00:09
@@ -77,6 +77,29 @@
void g2bus_bus_mem_write_region_1(void *, bus_space_handle_t, bus_size_t,
const u_int8_t *, bus_size_t);
+u_int8_t g2bus_sparse_bus_mem_read_1(void *, bus_space_handle_t, bus_size_t);
+u_int16_t g2bus_sparse_bus_mem_read_2(void *, bus_space_handle_t, bus_size_t);
+u_int32_t g2bus_sparse_bus_mem_read_4(void *, bus_space_handle_t, bus_size_t);
+
+void g2bus_sparse_bus_mem_write_1(void *, bus_space_handle_t, bus_size_t,
+ u_int8_t);
+void g2bus_sparse_bus_mem_write_2(void *, bus_space_handle_t, bus_size_t,
+ u_int16_t);
+void g2bus_sparse_bus_mem_write_4(void *, bus_space_handle_t, bus_size_t,
+ u_int32_t);
+
+void g2bus_sparse_bus_mem_read_region_1(void *, bus_space_handle_t,
+ bus_size_t, u_int8_t *, bus_size_t);
+
+void g2bus_sparse_bus_mem_write_region_1(void *, bus_space_handle_t,
+ bus_size_t, const u_int8_t *, bus_size_t);
+
+void g2bus_sparse_bus_mem_read_multi_1(void *, bus_space_handle_t,
+ bus_size_t, u_int8_t *, bus_size_t);
+
+void g2bus_sparse_bus_mem_write_multi_1(void *, bus_space_handle_t,
+ bus_size_t, const u_int8_t *, bus_size_t);
+
void
g2bus_bus_mem_init(struct g2bus_softc *sc)
{
@@ -240,6 +263,165 @@
while (len--)
*baddr++ = *addr++;
+
+ G2_UNLOCK;
+}
+
+void
+g2bus_set_bus_mem_sparse(bus_space_tag_t memt)
+{
+
+ memt->dbs_r_1 = g2bus_sparse_bus_mem_read_1;
+ memt->dbs_r_2 = g2bus_sparse_bus_mem_read_2;
+ memt->dbs_r_4 = g2bus_sparse_bus_mem_read_4;
+
+ memt->dbs_w_1 = g2bus_sparse_bus_mem_write_1;
+ memt->dbs_w_2 = g2bus_sparse_bus_mem_write_2;
+ memt->dbs_w_4 = g2bus_sparse_bus_mem_write_4;
+
+ memt->dbs_rr_1 = g2bus_sparse_bus_mem_read_region_1;
+
+ memt->dbs_wr_1 = g2bus_sparse_bus_mem_write_region_1;
+
+ memt->dbs_rm_1 = g2bus_sparse_bus_mem_read_multi_1;
+
+ memt->dbs_wm_1 = g2bus_sparse_bus_mem_write_multi_1;
+}
+
+u_int8_t
+g2bus_sparse_bus_mem_read_1(void *v, bus_space_handle_t sh, bus_size_t off)
+{
+ u_int8_t rv;
+
+ G2_LOCK;
+
+ rv = *(__volatile u_int8_t *)(sh + (off * 4));
+
+ G2_UNLOCK;
+
+ return (rv);
+}
+
+u_int16_t
+g2bus_sparse_bus_mem_read_2(void *v, bus_space_handle_t sh, bus_size_t off)
+{
+ u_int16_t rv;
+
+ G2_LOCK;
+
+ rv = *(__volatile u_int16_t *)(sh + (off * 4));
+
+ G2_UNLOCK;
+
+ return (rv);
+}
+
+u_int32_t
+g2bus_sparse_bus_mem_read_4(void *v, bus_space_handle_t sh, bus_size_t off)
+{
+ u_int32_t rv;
+
+ G2_LOCK;
+
+ rv = *(__volatile u_int32_t *)(sh + (off * 4));
+
+ G2_UNLOCK;
+
+ return (rv);
+}
+
+void
+g2bus_sparse_bus_mem_write_1(void *v, bus_space_handle_t sh, bus_size_t off,
+ u_int8_t val)
+{
+
+ G2_LOCK;
+
+ *(__volatile u_int8_t *)(sh + (off * 4)) = val;
+
+ G2_UNLOCK;
+}
+
+void
+g2bus_sparse_bus_mem_write_2(void *v, bus_space_handle_t sh, bus_size_t off,
+ u_int16_t val)
+{
+
+ G2_LOCK;
+
+ *(__volatile u_int16_t *)(sh + (off * 4)) = val;
+
+ G2_UNLOCK;
+}
+
+void
+g2bus_sparse_bus_mem_write_4(void *v, bus_space_handle_t sh, bus_size_t off,
+ u_int32_t val)
+{
+
+ G2_LOCK;
+
+ *(__volatile u_int32_t *)(sh + (off * 4)) = val;
+
+ G2_UNLOCK;
+}
+
+void
+g2bus_sparse_bus_mem_read_region_1(void *v, bus_space_handle_t sh,
+ bus_size_t off, u_int8_t *addr, bus_size_t len)
+{
+ __volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
+
+ G2_LOCK;
+
+ while (len--) {
+ *addr++ = *baddr;
+ baddr += 4;
+ }
+
+ G2_UNLOCK;
+}
+
+void
+g2bus_sparse_bus_mem_write_region_1(void *v, bus_space_handle_t sh,
+ bus_size_t off, const u_int8_t *addr, bus_size_t len)
+{
+ __volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
+
+ G2_LOCK;
+
+ while (len--) {
+ *baddr = *addr++;
+ baddr += 4;
+ }
+
+ G2_UNLOCK;
+}
+
+void
+g2bus_sparse_bus_mem_read_multi_1(void *v, bus_space_handle_t sh,
+ bus_size_t off, u_int8_t *addr, bus_size_t len)
+{
+ __volatile const u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
+
+ G2_LOCK;
+
+ while (len--)
+ *addr++ = *baddr;
+
+ G2_UNLOCK;
+}
+
+void
+g2bus_sparse_bus_mem_write_multi_1(void *v, bus_space_handle_t sh,
+ bus_size_t off, const u_int8_t *addr, bus_size_t len)
+{
+ __volatile u_int8_t *baddr = (u_int8_t *)(sh + (off * 4));
+
+ G2_LOCK;
+
+ while (len--)
+ *baddr = *addr++;
G2_UNLOCK;
}
Index: dev/g2/g2busvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/dreamcast/dev/g2/g2busvar.h,v
retrieving revision 1.3
diff -u -r1.3 g2busvar.h
--- dev/g2/g2busvar.h 2002/12/23 09:59:25 1.3
+++ dev/g2/g2busvar.h 2002/12/23 10:00:09
@@ -64,5 +64,6 @@
};
void g2bus_bus_mem_init(struct g2bus_softc *);
+void g2bus_set_bus_mem_sparse(bus_space_tag_t);
#endif /* _DREAMCAST_G2BUSVAR_H_ */
Index: include/sysasicvar.h
===================================================================
RCS file: /cvsroot/src/sys/arch/dreamcast/include/sysasicvar.h,v
retrieving revision 1.3
diff -u -r1.3 sysasicvar.h
--- include/sysasicvar.h 2002/11/15 13:29:27 1.3
+++ include/sysasicvar.h 2002/12/23 10:00:10
@@ -43,6 +43,7 @@
#define SYSASIC_EVENT_MAPLE_ERROR 13
#define SYSASIC_EVENT_GDROM 32
#define SYSASIC_EVENT_AICA 33
+#define SYSASIC_EVENT_8BIT 34
#define SYSASIC_EVENT_EXT 35
#define SYSASIC_EVENT_MAX 65
--- /dev/null Tue Dec 24 02:11:01 2002
+++ dev/g2/if_mbe_g2.c Tue Dec 24 22:32:57 2002
@@ -0,0 +1,239 @@
+/* $NetBSD$ */
+
+/*
+ * Copyright (c) 2002 Christian Groessler
+ * 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.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * 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.
+ */
+
+/*
+ * All Rights Reserved, Copyright (C) Fujitsu Limited 1995
+ *
+ * This software may be used, modified, copied, distributed, and sold, in
+ * both source and binary form provided that the above copyright, these
+ * terms and the following disclaimer are retained. The name of the author
+ * and/or the contributor may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND THE CONTRIBUTOR ``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 OR THE CONTRIBUTOR 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.
+ */
+
+/*
+ * Portions copyright (C) 1993, David Greenman. This software may be used,
+ * modified, copied, distributed, and sold, in both source and binary form
+ * provided that the above copyright and these terms are retained. Under no
+ * circumstances is the author responsible for the proper functioning of this
+ * software, nor does the author assume any responsibility for damages
+ * incurred with its use.
+ */
+
+/*
+ * Driver for Sega LAN Adapter (HIT-0300)
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD$");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <net/if.h>
+#include <net/if_ether.h>
+#include <net/if_media.h>
+
+#include <machine/bus.h>
+#include <machine/intr.h>
+#include <machine/sysasicvar.h>
+#include <machine/cpu.h>
+
+#include <dev/ic/mb86960reg.h>
+#include <dev/ic/mb86960var.h>
+
+#include <dreamcast/dev/g2/g2busvar.h>
+
+
+int mbe_g2_match(struct device *, struct cfdata *, void *);
+void mbe_g2_attach(struct device *, struct device *, void *);
+static int mbe_g2_detect(bus_space_tag_t, bus_space_handle_t, u_int8_t *);
+
+struct mbe_g2_softc {
+ struct mb86960_softc sc_mb86960; /* real "mb86960" softc */
+};
+
+CFATTACH_DECL(mbe_g2bus, sizeof(struct mbe_g2_softc),
+ mbe_g2_match, mbe_g2_attach, NULL, NULL);
+
+#define LANA_NPORTS (0x20 * 4)
+
+static struct dreamcast_bus_space mbe_g2_dbs;
+
+/*
+ * Determine if the device is present.
+ */
+int
+mbe_g2_match(struct device *parent, struct cfdata *cf, void *aux)
+{
+ struct g2bus_attach_args *ga = aux;
+ bus_space_handle_t memh;
+ struct dreamcast_bus_space dbs;
+ bus_space_tag_t memt = &dbs;
+ static int lanafound;
+ int rv;
+ u_int8_t myea[ETHER_ADDR_LEN];
+
+ if (lanafound)
+ return (0);
+
+ if (strcmp("mbe", cf->cf_name))
+ return (0);
+
+ memcpy(memt, ga->ga_memt, sizeof(struct dreamcast_bus_space));
+ g2bus_set_bus_mem_sparse(memt);
+
+ /* Map i/o ports. */
+ if (bus_space_map(memt, 0x00600400, LANA_NPORTS, 0, &memh)) {
+#ifdef LANA_DEBUG
+ printf("mbe_g2_match: couldn't map iospace 0x%x\n",
+ 0x00600400);
+#endif
+ return (0);
+ }
+
+ rv = 0;
+ if (mbe_g2_detect(memt, memh, myea) == 0) {
+#ifdef LANA_DEBUG
+ printf("mbe_g2_match: LAN Adapter detection failed\n");
+#endif
+ goto out;
+ }
+
+ rv = 1;
+ lanafound = 1;
+ out:
+ bus_space_unmap(memt, memh, LANA_NPORTS);
+ return (rv);
+}
+
+
+/*
+ * Determine type and ethernet address.
+ */
+static int
+mbe_g2_detect(iot, ioh, enaddr)
+ bus_space_tag_t iot;
+ bus_space_handle_t ioh;
+ u_int8_t *enaddr;
+{
+ u_int8_t eeprom[FE_EEPROM_SIZE];
+
+ memset(eeprom, 0, FE_EEPROM_SIZE);
+
+ /* Get our station address from EEPROM. */
+ mb86965_read_eeprom(iot, ioh, eeprom);
+ memcpy(enaddr, eeprom, ETHER_ADDR_LEN);
+
+#if LANA_DEBUG > 1
+ printf("Ethernet address: %s\n", ether_sprintf(enaddr));
+#endif
+
+ /* Make sure we got a valid station address. */
+ if ((enaddr[0] & 0x03) != 0x00 ||
+ (enaddr[0] == 0x00 && enaddr[1] == 0x00 && enaddr[2] == 0x00)) {
+#ifdef LANA_DEBUG
+ printf("mbe_g2_detect: invalid ethernet address\n");
+#endif
+ return (0);
+ }
+
+ /* Read the chip type */
+ if ((bus_space_read_1(iot, ioh, FE_DLCR7) & FE_D7_IDENT) !=
+ FE_D7_IDENT_86967) {
+#ifdef LANA_DEBUG
+ printf("mbe_g2_detect: unknown chip type\n");
+#endif
+ return (0);
+ }
+
+ return (1);
+}
+
+void
+mbe_g2_attach(parent, self, aux)
+ struct device *parent, *self;
+ void *aux;
+{
+ struct g2bus_attach_args *ga = aux;
+ struct mbe_g2_softc *isc = (struct mbe_g2_softc *)self;
+ struct mb86960_softc *sc = &isc->sc_mb86960;
+ bus_space_tag_t memt = &mbe_g2_dbs;
+ bus_space_handle_t memh;
+ u_int8_t myea[ETHER_ADDR_LEN];
+
+ memcpy(memt, ga->ga_memt, sizeof(struct dreamcast_bus_space));
+ g2bus_set_bus_mem_sparse(memt);
+
+ /* Map i/o ports. */
+ if (bus_space_map(memt, 0x00600400, LANA_NPORTS, 0, &memh)) {
+ printf(": can't map i/o space\n");
+ return;
+ }
+
+ sc->sc_bst = memt;
+ sc->sc_bsh = memh;
+
+ /* Determine the card type. */
+ if (mbe_g2_detect(memt, memh, myea) == 0) {
+ printf(": where did the card go?!\n");
+ panic("unknown card");
+ }
+
+ printf(": Sega LAN-Adapter Ethernet\n");
+
+ /* This interface is always enabled. */
+ sc->sc_stat |= FE_STAT_ENABLED;
+
+ /* The LAN-Adapter uses 8 bit bus mode. */
+ sc->sc_flags |= FE_FLAGS_SBW_BYTE;
+
+ /*
+ * Do generic MB86960 attach.
+ */
+ mb86960_attach(sc, myea);
+
+ mb86960_config(sc, NULL, 0, 0);
+
+ sysasic_intr_establish(SYSASIC_EVENT_8BIT, IPL_NET, mb86960_intr, sc);
+}