summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpaul <paul@FreeBSD.org>2000-05-16 02:08:04 +0000
committerpaul <paul@FreeBSD.org>2000-05-16 02:08:04 +0000
commit3c5581f91412c85ac6dc95bbd53016f17664910d (patch)
treea169db45536ba91d5eda676fd8d880f52eb44c37 /sys
parentb448bd5eed144c0d3dc78de5655b498f8b791ee2 (diff)
downloadFreeBSD-src-3c5581f91412c85ac6dc95bbd53016f17664910d.zip
FreeBSD-src-3c5581f91412c85ac6dc95bbd53016f17664910d.tar.gz
Re-organise lnc driver in preparation for newbusifying it.
Diffstat (limited to 'sys')
-rw-r--r--sys/conf/files2
-rw-r--r--sys/dev/lnc/if_lnc.c424
-rw-r--r--sys/dev/lnc/if_lnc_isa.c301
-rw-r--r--sys/dev/lnc/if_lnc_pc98.c147
-rw-r--r--sys/dev/lnc/if_lnc_pci.c58
-rw-r--r--sys/dev/lnc/if_lncvar.h52
6 files changed, 542 insertions, 442 deletions
diff --git a/sys/conf/files b/sys/conf/files
index 778a5ac..e1e062a 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -172,6 +172,8 @@ dev/isp/isp_freebsd.c optional isp
dev/isp/isp_target.c optional isp
dev/lmc/if_lmc.c optional lmc
dev/lnc/if_lnc.c optional lnc
+dev/lnc/if_lnc_isa.c optional lnc isa
+dev/lnc/if_lnc_pc98.c optional lnc isa
dev/lnc/if_lnc_pci.c optional lnc pci
dev/mca/mca_bus.c optional mca
dev/md/md.c optional md
diff --git a/sys/dev/lnc/if_lnc.c b/sys/dev/lnc/if_lnc.c
index 2730a5c..633e889 100644
--- a/sys/dev/lnc/if_lnc.c
+++ b/sys/dev/lnc/if_lnc.c
@@ -84,40 +84,13 @@
#include <net/bpf.h>
-#ifdef PC98
-#include <machine/clock.h>
-#endif
#include <machine/md_var.h>
#include <i386/isa/isa_device.h>
#include <dev/lnc/if_lncvar.h>
#include <dev/lnc/if_lncreg.h>
-struct lnc_softc {
- struct arpcom arpcom; /* see ../../net/if_arp.h */
- struct nic_info nic; /* NIC specific info */
- int nrdre;
- struct host_ring_entry *recv_ring; /* start of alloc'd mem */
- int recv_next;
- int ntdre;
- struct host_ring_entry *trans_ring;
- int trans_next;
- struct init_block *init_block; /* Initialisation block */
- int pending_transmits; /* No. of transmit descriptors in use */
- int next_to_send;
- struct mbuf *mbufs;
- int mbuf_count;
- int flags;
- int rap;
- int rdp;
- int bdp;
-#ifdef DEBUG
- int lnc_debug;
-#endif
- LNCSTATS_STRUCT
-};
-
-static struct lnc_softc lnc_softc[NLNC];
+struct lnc_softc lnc_softc[NLNC];
static char const * const nic_ident[] = {
"Unknown",
@@ -156,20 +129,10 @@ static __inline struct mbuf *mbuf_packet __P((struct lnc_softc *sc,
int pkt_len));
static __inline void lnc_rint __P((struct lnc_softc *sc));
static __inline void lnc_tint __P((struct lnc_softc *sc));
-static int lnc_probe __P((struct isa_device *isa_dev));
-#ifdef PC98
-static int cnet98s_probe __P((struct lnc_softc *sc, unsigned iobase));
-#endif
-static int ne2100_probe __P((struct lnc_softc *sc, unsigned iobase));
-static int bicc_probe __P((struct lnc_softc *sc, unsigned iobase));
-static int dec_macaddr_extract __P((u_char ring[], struct lnc_softc *sc));
-static int depca_probe __P((struct lnc_softc *sc, unsigned iobase));
-static int lance_probe __P((struct lnc_softc *sc));
-static int pcnet_probe __P((struct lnc_softc *sc));
-static int lnc_attach_sc __P((struct lnc_softc *sc, int unit));
-static int lnc_attach __P((struct isa_device *isa_dev));
+extern int lnc_probe __P((struct isa_device *isa_dev));
+int lnc_attach_sc __P((struct lnc_softc *sc, int unit));
+extern int lnc_attach __P((struct isa_device *isa_dev));
static void lnc_init __P((void *));
-static ointhand2_t lncintr;
static __inline int mbuf_to_buffer __P((struct mbuf *m, char *buffer));
static __inline struct mbuf *chain_to_cluster __P((struct mbuf *m));
static void lnc_start __P((struct ifnet *ifp));
@@ -180,28 +143,11 @@ void lnc_dump_state __P((struct lnc_softc *sc));
void mbuf_dump_chain __P((struct mbuf *m));
#endif
-#if NPCI > 0
-void *lnc_attach_ne2100_pci __P((int unit, unsigned iobase));
-#endif
void lncintr_sc __P((struct lnc_softc *sc));
struct isa_driver lncdriver = {lnc_probe, lnc_attach, "lnc"};
static __inline void
-write_csr(struct lnc_softc *sc, u_short port, u_short val)
-{
- outw(sc->rap, port);
- outw(sc->rdp, val);
-}
-
-static __inline u_short
-read_csr(struct lnc_softc *sc, u_short port)
-{
- outw(sc->rap, port);
- return (inw(sc->rdp));
-}
-
-static __inline void
write_bcr(struct lnc_softc *sc, u_short port, u_short val)
{
outw(sc->rap, port);
@@ -860,294 +806,7 @@ lnc_tint(struct lnc_softc *sc)
}
-static int
-lnc_probe(struct isa_device * isa_dev)
-{
- int nports;
- int unit = isa_dev->id_unit;
- struct lnc_softc *sc = &lnc_softc[unit];
- unsigned iobase = isa_dev->id_iobase;
-
-#ifdef DIAGNOSTIC
- int vsw;
- vsw = inw(isa_dev->id_iobase + PCNET_VSW);
- printf("Vendor Specific Word = %x\n", vsw);
-#endif
-
- nports = bicc_probe(sc, iobase);
- if (nports == 0)
- nports = ne2100_probe(sc, iobase);
- if (nports == 0)
- nports = depca_probe(sc, iobase);
-#ifdef PC98
- if (nports == 0)
- nports = cnet98s_probe(sc, iobase);
-#endif
- return (nports);
-}
-
-#ifdef PC98
-/* ISA Bus Configuration Registers */
-/* XXX - Should be in ic/Am7990.h */
-#define MSRDA 0x0000 /* ISACSR0: Master Mode Read Activity */
-#define MSWRA 0x0001 /* ISACSR1: Master Mode Write Activity */
-#define MC 0x0002 /* ISACSR2: Miscellaneous Configuration */
-
-#define LED1 0x0005 /* ISACSR5: LED1 Status */
-#define LED2 0x0006 /* ISACSR6: LED2 Status */
-#define LED3 0x0007 /* ISACSR7: LED3 Status */
-
-#define LED_PSE 0x0080 /* Pulse Stretcher */
-#define LED_XMTE 0x0010 /* Transmit Status */
-#define LED_RVPOLE 0x0008 /* Receive Polarity */
-#define LED_RCVE 0x0004 /* Receive Status */
-#define LED_JABE 0x0002 /* Jabber */
-#define LED_COLE 0x0001 /* Collision */
-
-static int
-cnet98s_probe(struct lnc_softc *sc, unsigned iobase)
-{
- int i;
- ushort tmp;
-
- sc->rap = iobase + CNET98S_RAP;
- sc->rdp = iobase + CNET98S_RDP;
-
- /* Reset */
- tmp = inw(iobase + CNET98S_RESET);
- outw(iobase + CNET98S_RESET, tmp);
- DELAY(500);
-
- sc->nic.ic = pcnet_probe(sc);
- if ((sc->nic.ic == UNKNOWN) || (sc->nic.ic > PCnet_32)) {
- return (0);
- }
-
- sc->nic.ident = CNET98S;
- sc->nic.mem_mode = DMA_FIXED;
-
- /* XXX - For now just use the defines */
- sc->nrdre = NRDRE;
- sc->ntdre = NTDRE;
-
- /* Extract MAC address from PROM */
- for (i = 0; i < ETHER_ADDR_LEN; i++) {
- sc->arpcom.ac_enaddr[i] = inb(iobase + (i * 2));
- }
-
- /*
- * ISA Configuration
- *
- * XXX - Following parameters are Contec C-NET(98)S only.
- * So, check the Ethernet address here.
- *
- * Contec uses 00 80 4c ?? ?? ??
- */
- if (sc->arpcom.ac_enaddr[0] == (u_char)0x00
- && sc->arpcom.ac_enaddr[1] == (u_char)0x80
- && sc->arpcom.ac_enaddr[2] == (u_char)0x4c) {
- outw(sc->rap, MSRDA);
- outw(iobase + CNET98S_IDP, 0x0006);
- outw(sc->rap, MSWRA);
- outw(iobase + CNET98S_IDP, 0x0006);
-#ifdef DIAGNOSTIC
- outw(sc->rap, MC);
- printf("ISACSR2 = %x\n", inw(iobase + CNET98S_IDP));
-#endif
- outw(sc->rap, LED1);
- outw(iobase + CNET98S_IDP, LED_PSE | LED_XMTE);
- outw(sc->rap, LED2);
- outw(iobase + CNET98S_IDP, LED_PSE | LED_RCVE);
- outw(sc->rap, LED3);
- outw(iobase + CNET98S_IDP, LED_PSE | LED_COLE);
- }
-
- return (CNET98S_IOSIZE);
-}
-#endif
-
-static int
-ne2100_probe(struct lnc_softc *sc, unsigned iobase)
-{
- int i;
-
- sc->rap = iobase + PCNET_RAP;
- sc->rdp = iobase + PCNET_RDP;
-
- sc->nic.ic = pcnet_probe(sc);
- if ((sc->nic.ic > 0) && (sc->nic.ic < PCnet_PCI)) {
- sc->nic.ident = NE2100;
- sc->nic.mem_mode = DMA_FIXED;
-
- /* XXX - For now just use the defines */
- sc->nrdre = NRDRE;
- sc->ntdre = NTDRE;
-
- /* Extract MAC address from PROM */
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- sc->arpcom.ac_enaddr[i] = inb(iobase + i);
- return (NE2100_IOSIZE);
- } else {
- return (0);
- }
-}
-
-static int
-bicc_probe(struct lnc_softc *sc, unsigned iobase)
-{
- int i;
-
- /*
- * There isn't any way to determine if a NIC is a BICC. Basically, if
- * the lance probe succeeds using the i/o addresses of the BICC then
- * we assume it's a BICC.
- *
- */
-
- sc->rap = iobase + BICC_RAP;
- sc->rdp = iobase + BICC_RDP;
-
- /* I think all these cards us the Am7990 */
-
- if ((sc->nic.ic = lance_probe(sc))) {
- sc->nic.ident = BICC;
- sc->nic.mem_mode = DMA_FIXED;
-
- /* XXX - For now just use the defines */
- sc->nrdre = NRDRE;
- sc->ntdre = NTDRE;
-
- /* Extract MAC address from PROM */
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- sc->arpcom.ac_enaddr[i] = inb(iobase + (i * 2));
-
- return (BICC_IOSIZE);
- } else {
- return (0);
- }
-}
-
-/*
- * I don't have data sheets for the dec cards but it looks like the mac
- * address is contained in a 32 byte ring. Each time you read from the port
- * you get the next byte in the ring. The mac address is stored after a
- * signature so keep searching for the signature first.
- */
-static int
-dec_macaddr_extract(u_char ring[], struct lnc_softc * sc)
-{
- const unsigned char signature[] = {0xff, 0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa};
-
- int i, j, rindex;
-
- for (i = 0; i < sizeof ring; i++) {
- for (j = 0, rindex = i; j < sizeof signature; j++) {
- if (ring[rindex] != signature[j])
- break;
- if (++rindex > sizeof ring)
- rindex = 0;
- }
- if (j == sizeof signature) {
- for (j = 0, rindex = i; j < ETHER_ADDR_LEN; j++) {
- sc->arpcom.ac_enaddr[j] = ring[rindex];
- if (++rindex > sizeof ring)
- rindex = 0;
- }
- return (1);
- }
- }
- return (0);
-}
-
-static int
-depca_probe(struct lnc_softc *sc, unsigned iobase)
-{
- int i;
- unsigned char maddr_ring[DEPCA_ADDR_ROM_SIZE];
-
- sc->rap = iobase + DEPCA_RAP;
- sc->rdp = iobase + DEPCA_RDP;
-
- if ((sc->nic.ic = lance_probe(sc))) {
- sc->nic.ident = DEPCA;
- sc->nic.mem_mode = SHMEM;
-
- /* Extract MAC address from PROM */
- for (i = 0; i < DEPCA_ADDR_ROM_SIZE; i++)
- maddr_ring[i] = inb(iobase + DEPCA_ADP);
- if (dec_macaddr_extract(maddr_ring, sc)) {
- return (DEPCA_IOSIZE);
- }
- }
- return (0);
-}
-
-static int
-lance_probe(struct lnc_softc *sc)
-{
- write_csr(sc, CSR0, STOP);
-
- if ((inw(sc->rdp) & STOP) && !(read_csr(sc, CSR3))) {
- /*
- * Check to see if it's a C-LANCE. For the LANCE the INEA bit
- * cannot be set while the STOP bit is. This restriction is
- * removed for the C-LANCE.
- */
- write_csr(sc, CSR0, INEA);
- if (read_csr(sc, CSR0) & INEA)
- return (C_LANCE);
- else
- return (LANCE);
- } else
- return (UNKNOWN);
-}
-
-static int
-pcnet_probe(struct lnc_softc *sc)
-{
- u_long chip_id;
- int type;
-
- /*
- * The PCnet family don't reset the RAP register on reset so we'll
- * have to write during the probe :-) It does have an ID register
- * though so the probe is just a matter of reading it.
- */
-
- if ((type = lance_probe(sc))) {
- chip_id = read_csr(sc, CSR89);
- chip_id <<= 16;
- chip_id |= read_csr(sc, CSR88);
- if (chip_id & AMD_MASK) {
- chip_id >>= 12;
- switch (chip_id & PART_MASK) {
- case Am79C960:
- return (PCnet_ISA);
- case Am79C961:
- return (PCnet_ISAplus);
- case Am79C961A:
- return (PCnet_ISA_II);
- case Am79C965:
- return (PCnet_32);
- case Am79C970:
- return (PCnet_PCI);
- case Am79C970A:
- return (PCnet_PCI_II);
- case Am79C971:
- return (PCnet_FAST);
- case Am79C972:
- return (PCnet_FASTplus);
- case Am79C978:
- return (PCnet_Home);
- default:
- break;
- }
- }
- }
- return (type);
-}
-
-static int
+int
lnc_attach_sc(struct lnc_softc *sc, int unit)
{
int lnc_mem_size;
@@ -1248,72 +907,6 @@ lnc_attach_sc(struct lnc_softc *sc, int unit)
return (1);
}
-static int
-lnc_attach(struct isa_device * isa_dev)
-{
- int unit = isa_dev->id_unit;
- struct lnc_softc *sc = &lnc_softc[unit];
- int result;
-
- isa_dev->id_ointr = lncintr;
- result = lnc_attach_sc (sc, unit);
- if (result == 0)
- return (0);
-
-#ifndef PC98
- /*
- * XXX - is it safe to call isa_dmacascade() after if_attach()
- * and ether_ifattach() have been called in lnc_attach() ???
- */
- if ((sc->nic.mem_mode != SHMEM) &&
- (sc->nic.ic < PCnet_32))
- isa_dmacascade(isa_dev->id_drq);
-#endif
-
- return result;
-}
-
-#if NPCI > 0
-void *
-lnc_attach_ne2100_pci(int unit, unsigned iobase)
-{
- int i;
- struct lnc_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
-
- if (sc) {
- bzero (sc, sizeof *sc);
-
- sc->rap = iobase + PCNET_RAP;
- sc->rdp = iobase + PCNET_RDP;
- sc->bdp = iobase + PCNET_BDP;
-
- sc->nic.ic = pcnet_probe(sc);
- if (sc->nic.ic >= PCnet_32) {
- sc->nic.ident = NE2100;
- sc->nic.mem_mode = DMA_FIXED;
-
- /* XXX - For now just use the defines */
- sc->nrdre = NRDRE;
- sc->ntdre = NTDRE;
-
- /* Extract MAC address from PROM */
- for (i = 0; i < ETHER_ADDR_LEN; i++)
- sc->arpcom.ac_enaddr[i] = inb(iobase + i);
-
- if (lnc_attach_sc(sc, unit) == 0) {
- free(sc, M_DEVBUF);
- sc = NULL;
- }
- }
- else {
- free(sc, M_DEVBUF);
- sc = NULL;
- }
- }
- return sc;
-}
-#endif
-
static void
lnc_init(xsc)
void *xsc;
@@ -1580,13 +1173,6 @@ lncintr_sc(struct lnc_softc *sc)
}
}
-static void
-lncintr(int unit)
-{
- struct lnc_softc *sc = &lnc_softc[unit];
- lncintr_sc (sc);
-}
-
static __inline int
mbuf_to_buffer(struct mbuf *m, char *buffer)
{
diff --git a/sys/dev/lnc/if_lnc_isa.c b/sys/dev/lnc/if_lnc_isa.c
new file mode 100644
index 0000000..0bef8b5
--- /dev/null
+++ b/sys/dev/lnc/if_lnc_isa.c
@@ -0,0 +1,301 @@
+/*-
+ * Copyright (c) 2000
+ * Paul Richards. 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,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 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 Paul Richards may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``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 PAUL RICHARDS 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <i386/isa/isa_device.h>
+#include <dev/lnc/if_lncvar.h>
+#include <dev/lnc/if_lncreg.h>
+
+int ne2100_probe __P((struct lnc_softc *, unsigned));
+int bicc_probe __P((struct lnc_softc *, unsigned));
+int depca_probe __P((struct lnc_softc *, unsigned));
+int lance_probe __P((struct lnc_softc *));
+int pcnet_probe __P((struct lnc_softc *));
+int lnc_probe __P((struct isa_device *));
+int lnc_attach __P((struct isa_device *));
+
+static int dec_macaddr_extract __P((u_char[], struct lnc_softc *));
+static ointhand2_t lncintr;
+
+extern struct lnc_softc lnc_softc[];
+extern int lnc_attach_sc __P((struct lnc_softc *, int));
+extern void lncintr_sc __P((struct lnc_softc *));
+
+int
+ne2100_probe(struct lnc_softc *sc, unsigned iobase)
+{
+ int i;
+
+ sc->rap = iobase + PCNET_RAP;
+ sc->rdp = iobase + PCNET_RDP;
+
+ sc->nic.ic = pcnet_probe(sc);
+ if ((sc->nic.ic > 0) && (sc->nic.ic < PCnet_PCI)) {
+ sc->nic.ident = NE2100;
+ sc->nic.mem_mode = DMA_FIXED;
+
+ /* XXX - For now just use the defines */
+ sc->nrdre = NRDRE;
+ sc->ntdre = NTDRE;
+
+ /* Extract MAC address from PROM */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->arpcom.ac_enaddr[i] = inb(iobase + i);
+ return (NE2100_IOSIZE);
+ } else {
+ return (0);
+ }
+}
+
+int
+bicc_probe(struct lnc_softc *sc, unsigned iobase)
+{
+ int i;
+
+ /*
+ * There isn't any way to determine if a NIC is a BICC. Basically, if
+ * the lance probe succeeds using the i/o addresses of the BICC then
+ * we assume it's a BICC.
+ *
+ */
+
+ sc->rap = iobase + BICC_RAP;
+ sc->rdp = iobase + BICC_RDP;
+
+ /* I think all these cards us the Am7990 */
+
+ if ((sc->nic.ic = lance_probe(sc))) {
+ sc->nic.ident = BICC;
+ sc->nic.mem_mode = DMA_FIXED;
+
+ /* XXX - For now just use the defines */
+ sc->nrdre = NRDRE;
+ sc->ntdre = NTDRE;
+
+ /* Extract MAC address from PROM */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->arpcom.ac_enaddr[i] = inb(iobase + (i * 2));
+
+ return (BICC_IOSIZE);
+ } else {
+ return (0);
+ }
+}
+
+/*
+ * I don't have data sheets for the dec cards but it looks like the mac
+ * address is contained in a 32 byte ring. Each time you read from the port
+ * you get the next byte in the ring. The mac address is stored after a
+ * signature so keep searching for the signature first.
+ */
+static int
+dec_macaddr_extract(u_char ring[], struct lnc_softc * sc)
+{
+ const unsigned char signature[] = {0xff, 0x00, 0x55, 0xaa, 0xff, 0x00, 0x55, 0xaa};
+
+ int i, j, rindex;
+
+ for (i = 0; i < sizeof ring; i++) {
+ for (j = 0, rindex = i; j < sizeof signature; j++) {
+ if (ring[rindex] != signature[j])
+ break;
+ if (++rindex > sizeof ring)
+ rindex = 0;
+ }
+ if (j == sizeof signature) {
+ for (j = 0, rindex = i; j < ETHER_ADDR_LEN; j++) {
+ sc->arpcom.ac_enaddr[j] = ring[rindex];
+ if (++rindex > sizeof ring)
+ rindex = 0;
+ }
+ return (1);
+ }
+ }
+ return (0);
+}
+
+int
+depca_probe(struct lnc_softc *sc, unsigned iobase)
+{
+ int i;
+ unsigned char maddr_ring[DEPCA_ADDR_ROM_SIZE];
+
+ sc->rap = iobase + DEPCA_RAP;
+ sc->rdp = iobase + DEPCA_RDP;
+
+ if ((sc->nic.ic = lance_probe(sc))) {
+ sc->nic.ident = DEPCA;
+ sc->nic.mem_mode = SHMEM;
+
+ /* Extract MAC address from PROM */
+ for (i = 0; i < DEPCA_ADDR_ROM_SIZE; i++)
+ maddr_ring[i] = inb(iobase + DEPCA_ADP);
+ if (dec_macaddr_extract(maddr_ring, sc)) {
+ return (DEPCA_IOSIZE);
+ }
+ }
+ return (0);
+}
+
+int
+lance_probe(struct lnc_softc *sc)
+{
+ write_csr(sc, CSR0, STOP);
+
+ if ((inw(sc->rdp) & STOP) && !(read_csr(sc, CSR3))) {
+ /*
+ * Check to see if it's a C-LANCE. For the LANCE the INEA bit
+ * cannot be set while the STOP bit is. This restriction is
+ * removed for the C-LANCE.
+ */
+ write_csr(sc, CSR0, INEA);
+ if (read_csr(sc, CSR0) & INEA)
+ return (C_LANCE);
+ else
+ return (LANCE);
+ } else
+ return (UNKNOWN);
+}
+
+int
+pcnet_probe(struct lnc_softc *sc)
+{
+ u_long chip_id;
+ int type;
+
+ /*
+ * The PCnet family don't reset the RAP register on reset so we'll
+ * have to write during the probe :-) It does have an ID register
+ * though so the probe is just a matter of reading it.
+ */
+
+ if ((type = lance_probe(sc))) {
+ chip_id = read_csr(sc, CSR89);
+ chip_id <<= 16;
+ chip_id |= read_csr(sc, CSR88);
+ if (chip_id & AMD_MASK) {
+ chip_id >>= 12;
+ switch (chip_id & PART_MASK) {
+ case Am79C960:
+ return (PCnet_ISA);
+ case Am79C961:
+ return (PCnet_ISAplus);
+ case Am79C961A:
+ return (PCnet_ISA_II);
+ case Am79C965:
+ return (PCnet_32);
+ case Am79C970:
+ return (PCnet_PCI);
+ case Am79C970A:
+ return (PCnet_PCI_II);
+ case Am79C971:
+ return (PCnet_FAST);
+ case Am79C972:
+ return (PCnet_FASTplus);
+ case Am79C978:
+ return (PCnet_Home);
+ default:
+ break;
+ }
+ }
+ }
+ return (type);
+}
+
+int
+lnc_probe(struct isa_device * isa_dev)
+{
+ int nports;
+ int unit = isa_dev->id_unit;
+ struct lnc_softc *sc = &lnc_softc[unit];
+ unsigned iobase = isa_dev->id_iobase;
+
+#ifdef DIAGNOSTIC
+ int vsw;
+ vsw = inw(isa_dev->id_iobase + PCNET_VSW);
+ printf("Vendor Specific Word = %x\n", vsw);
+#endif
+
+ nports = bicc_probe(sc, iobase);
+ if (nports == 0)
+ nports = ne2100_probe(sc, iobase);
+ if (nports == 0)
+ nports = depca_probe(sc, iobase);
+#ifdef PC98
+ if (nports == 0)
+ nports = cnet98s_probe(sc, iobase);
+#endif
+ return (nports);
+}
+
+int
+lnc_attach(struct isa_device * isa_dev)
+{
+ int unit = isa_dev->id_unit;
+ struct lnc_softc *sc = &lnc_softc[unit];
+ int result;
+
+ isa_dev->id_ointr = lncintr;
+ result = lnc_attach_sc (sc, unit);
+ if (result == 0)
+ return (0);
+
+#ifndef PC98
+ /*
+ * XXX - is it safe to call isa_dmacascade() after if_attach()
+ * and ether_ifattach() have been called in lnc_attach() ???
+ */
+ if ((sc->nic.mem_mode != SHMEM) &&
+ (sc->nic.ic < PCnet_32))
+ isa_dmacascade(isa_dev->id_drq);
+#endif
+
+ return result;
+}
+
+static void
+lncintr(int unit)
+{
+ struct lnc_softc *sc = &lnc_softc[unit];
+ lncintr_sc (sc);
+}
diff --git a/sys/dev/lnc/if_lnc_pc98.c b/sys/dev/lnc/if_lnc_pc98.c
new file mode 100644
index 0000000..4595619
--- /dev/null
+++ b/sys/dev/lnc/if_lnc_pc98.c
@@ -0,0 +1,147 @@
+/*-
+ * Copyright (c) 2000
+ * Paul Richards. 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,
+ * verbatim and that no modifications are made prior to this
+ * point in the file.
+ * 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 Paul Richards may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY PAUL RICHARDS ``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 PAUL RICHARDS 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifdef PC98
+#include "lnc.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/systm.h>
+
+#include <machine/clock.h>
+
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <i386/isa/isa_device.h>
+
+#include <dev/lnc/if_lncvar.h>
+#include <dev/lnc/if_lncreg.h>
+
+int pcnet_probe __P((struct lnc_softc *sc));
+static int cnet98s_probe __P((struct lnc_softc *sc, unsigned iobase));
+
+/* C-NET(98)S port addresses */
+#define CNET98S_RDP 0x400 /* Register Data Port */
+#define CNET98S_RAP 0x402 /* Register Address Port */
+#define CNET98S_RESET 0x404
+#define CNET98S_IDP 0x406
+#define CNET98S_EEPROM 0x40e
+/*
+ * XXX - The I/O address range is fragmented in the C-NET(98)S.
+ * This is the number of regs at iobase.
+ */
+#define CNET98S_IOSIZE 16 /* # of i/o addresses used. */
+
+/* ISA Bus Configuration Registers */
+/* XXX - Should be in ic/Am7990.h */
+#define MSRDA 0x0000 /* ISACSR0: Master Mode Read Activity */
+#define MSWRA 0x0001 /* ISACSR1: Master Mode Write Activity */
+#define MC 0x0002 /* ISACSR2: Miscellaneous Configuration */
+
+#define LED1 0x0005 /* ISACSR5: LED1 Status */
+#define LED2 0x0006 /* ISACSR6: LED2 Status */
+#define LED3 0x0007 /* ISACSR7: LED3 Status */
+
+#define LED_PSE 0x0080 /* Pulse Stretcher */
+#define LED_XMTE 0x0010 /* Transmit Status */
+#define LED_RVPOLE 0x0008 /* Receive Polarity */
+#define LED_RCVE 0x0004 /* Receive Status */
+#define LED_JABE 0x0002 /* Jabber */
+#define LED_COLE 0x0001 /* Collision */
+
+static int
+cnet98s_probe(struct lnc_softc *sc, unsigned iobase)
+{
+ int i;
+ ushort tmp;
+
+ sc->rap = iobase + CNET98S_RAP;
+ sc->rdp = iobase + CNET98S_RDP;
+
+ /* Reset */
+ tmp = inw(iobase + CNET98S_RESET);
+ outw(iobase + CNET98S_RESET, tmp);
+ DELAY(500);
+
+ sc->nic.ic = pcnet_probe(sc);
+ if ((sc->nic.ic == UNKNOWN) || (sc->nic.ic > PCnet_32)) {
+ return (0);
+ }
+
+ sc->nic.ident = CNET98S;
+ sc->nic.mem_mode = DMA_FIXED;
+
+ /* XXX - For now just use the defines */
+ sc->nrdre = NRDRE;
+ sc->ntdre = NTDRE;
+
+ /* Extract MAC address from PROM */
+ for (i = 0; i < ETHER_ADDR_LEN; i++) {
+ sc->arpcom.ac_enaddr[i] = inb(iobase + (i * 2));
+ }
+
+ /*
+ * ISA Configuration
+ *
+ * XXX - Following parameters are Contec C-NET(98)S only.
+ * So, check the Ethernet address here.
+ *
+ * Contec uses 00 80 4c ?? ?? ??
+ */
+ if (sc->arpcom.ac_enaddr[0] == (u_char)0x00
+ && sc->arpcom.ac_enaddr[1] == (u_char)0x80
+ && sc->arpcom.ac_enaddr[2] == (u_char)0x4c) {
+ outw(sc->rap, MSRDA);
+ outw(iobase + CNET98S_IDP, 0x0006);
+ outw(sc->rap, MSWRA);
+ outw(iobase + CNET98S_IDP, 0x0006);
+#ifdef DIAGNOSTIC
+ outw(sc->rap, MC);
+ printf("ISACSR2 = %x\n", inw(iobase + CNET98S_IDP));
+#endif
+ outw(sc->rap, LED1);
+ outw(iobase + CNET98S_IDP, LED_PSE | LED_XMTE);
+ outw(sc->rap, LED2);
+ outw(iobase + CNET98S_IDP, LED_PSE | LED_RCVE);
+ outw(sc->rap, LED3);
+ outw(iobase + CNET98S_IDP, LED_PSE | LED_COLE);
+ }
+
+ return (CNET98S_IOSIZE);
+}
+#endif
diff --git a/sys/dev/lnc/if_lnc_pci.c b/sys/dev/lnc/if_lnc_pci.c
index 8d8745a..e459377 100644
--- a/sys/dev/lnc/if_lnc_pci.c
+++ b/sys/dev/lnc/if_lnc_pci.c
@@ -27,6 +27,17 @@
#include <pci/pcireg.h>
#include <pci/pcivar.h>
+#include <sys/socket.h>
+#include <net/ethernet.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+
+#include <dev/lnc/if_lncvar.h>
+
#include "lnc.h"
#ifndef COMPAT_OLDPCI
@@ -36,7 +47,8 @@
#define PCI_DEVICE_ID_PCNet_PCI 0x20001022
#define PCI_DEVICE_ID_PCHome_PCI 0x20011022
-extern void *lnc_attach_ne2100_pci __P((int unit, unsigned iobase));
+extern int pcnet_probe __P((struct lnc_softc *sc));
+extern int lnc_attach_sc __P((struct lnc_softc *sc, int unit));
static const char* lnc_pci_probe __P((pcici_t tag, pcidi_t type));
static void lnc_pci_attach __P((pcici_t config_id, int unit));
@@ -76,9 +88,10 @@ lnc_pci_attach(config_id, unit)
pcici_t config_id;
int unit;
{
+ struct lnc_softc *sc;
unsigned iobase;
unsigned data; /* scratch to make this device a bus master*/
- void *lnc; /* device specific data for interrupt handler ... */
+ int i;
if ( !pci_map_port(config_id,PCI_MAP_REG_START,(u_short *)&iobase) )
printf("lnc%d: pci_port_map_attach failed?!\n",unit);
@@ -91,13 +104,40 @@ lnc_pci_attach(config_id, unit)
data |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN;
pci_cfgwrite(config_id, PCIR_COMMAND, data, 4);
- lnc = lnc_attach_ne2100_pci(unit, iobase);
-
- if (!lnc)
- return;
- if(!(pci_map_int(config_id, lncintr_sc, (void *)lnc, &net_imask))) {
- free (lnc, M_DEVBUF);
- return;
+ sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
+
+ if (sc) {
+ bzero (sc, sizeof *sc);
+
+ sc->rap = iobase + PCNET_RAP;
+ sc->rdp = iobase + PCNET_RDP;
+ sc->bdp = iobase + PCNET_BDP;
+
+ sc->nic.ic = pcnet_probe(sc);
+ if (sc->nic.ic >= PCnet_32) {
+ sc->nic.ident = NE2100;
+ sc->nic.mem_mode = DMA_FIXED;
+
+ /* XXX - For now just use the defines */
+ sc->nrdre = NRDRE;
+ sc->ntdre = NTDRE;
+
+ /* Extract MAC address from PROM */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->arpcom.ac_enaddr[i] = inb(iobase + i);
+
+ if (lnc_attach_sc(sc, unit) == 0) {
+ free(sc, M_DEVBUF);
+ sc = NULL;
+ }
+
+ if(!(pci_map_int(config_id, lncintr_sc, (void *)sc, &net_imask))) {
+ free (sc, M_DEVBUF);
+ return;
+ }
+ } else {
+ free(sc, M_DEVBUF);
+ }
}
return;
diff --git a/sys/dev/lnc/if_lncvar.h b/sys/dev/lnc/if_lncvar.h
index 54284eb..5a4de23 100644
--- a/sys/dev/lnc/if_lncvar.h
+++ b/sys/dev/lnc/if_lncvar.h
@@ -76,20 +76,6 @@
/* DEPCA specific defines */
#define DEPCA_ADDR_ROM_SIZE 32
-#ifdef PC98
-/* C-NET(98)S port addresses */
-#define CNET98S_RDP 0x400 /* Register Data Port */
-#define CNET98S_RAP 0x402 /* Register Address Port */
-#define CNET98S_RESET 0x404
-#define CNET98S_IDP 0x406
-#define CNET98S_EEPROM 0x40e
-/*
- * XXX - The I/O address range is fragmented in the C-NET(98)S.
- * This is the number of regs at iobase.
- */
-#define CNET98S_IOSIZE 16 /* # of i/o addresses used. */
-#endif
-
/* Chip types */
#define LANCE 1 /* Am7990 */
#define C_LANCE 2 /* Am79C90 */
@@ -199,6 +185,30 @@ struct host_ring_entry {
#define LNCSTATS(X)
#endif
+struct lnc_softc {
+ struct arpcom arpcom; /* see ../../net/if_arp.h */
+ struct nic_info nic; /* NIC specific info */
+ int nrdre;
+ struct host_ring_entry *recv_ring; /* start of alloc'd mem */
+ int recv_next;
+ int ntdre;
+ struct host_ring_entry *trans_ring;
+ int trans_next;
+ struct init_block *init_block; /* Initialisation block */
+ int pending_transmits; /* No. of transmit descriptors in use */
+ int next_to_send;
+ struct mbuf *mbufs;
+ int mbuf_count;
+ int flags;
+ int rap;
+ int rdp;
+ int bdp;
+#ifdef DEBUG
+ int lnc_debug;
+#endif
+ LNCSTATS_STRUCT
+};
+
#define NDESC(len2) (1 << len2)
#define INC_MD_PTR(ptr, no_entries) \
@@ -211,3 +221,17 @@ struct host_ring_entry {
#define RECV_NEXT (sc->recv_ring->base + sc->recv_next)
#define TRANS_NEXT (sc->trans_ring->base + sc->trans_next)
+
+static __inline void
+write_csr(struct lnc_softc *sc, u_short port, u_short val)
+{
+ outw(sc->rap, port);
+ outw(sc->rdp, val);
+}
+
+static __inline u_short
+read_csr(struct lnc_softc *sc, u_short port)
+{
+ outw(sc->rap, port);
+ return (inw(sc->rdp));
+}
OpenPOWER on IntegriCloud