diff options
author | paul <paul@FreeBSD.org> | 2000-05-16 02:08:04 +0000 |
---|---|---|
committer | paul <paul@FreeBSD.org> | 2000-05-16 02:08:04 +0000 |
commit | 3c5581f91412c85ac6dc95bbd53016f17664910d (patch) | |
tree | a169db45536ba91d5eda676fd8d880f52eb44c37 /sys/dev/lnc | |
parent | b448bd5eed144c0d3dc78de5655b498f8b791ee2 (diff) | |
download | FreeBSD-src-3c5581f91412c85ac6dc95bbd53016f17664910d.zip FreeBSD-src-3c5581f91412c85ac6dc95bbd53016f17664910d.tar.gz |
Re-organise lnc driver in preparation for newbusifying it.
Diffstat (limited to 'sys/dev/lnc')
-rw-r--r-- | sys/dev/lnc/if_lnc.c | 424 | ||||
-rw-r--r-- | sys/dev/lnc/if_lnc_isa.c | 301 | ||||
-rw-r--r-- | sys/dev/lnc/if_lnc_pc98.c | 147 | ||||
-rw-r--r-- | sys/dev/lnc/if_lnc_pci.c | 58 | ||||
-rw-r--r-- | sys/dev/lnc/if_lncvar.h | 52 |
5 files changed, 540 insertions, 442 deletions
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)); +} |