Re-organise lnc driver in preparation for newbusifying it.

This commit is contained in:
Paul Richards 2000-05-16 02:08:04 +00:00
parent 14a8a54168
commit 9b55e84fec
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=60616
6 changed files with 541 additions and 441 deletions

View file

@ -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

View file

@ -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,27 +143,10 @@ 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)
{
@ -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)
{

301
sys/dev/lnc/if_lnc_isa.c Normal file
View file

@ -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);
}

147
sys/dev/lnc/if_lnc_pc98.c Normal file
View file

@ -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

View file

@ -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,14 +104,41 @@ 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);
sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT);
if (!lnc)
return;
if(!(pci_map_int(config_id, lncintr_sc, (void *)lnc, &net_imask))) {
free (lnc, M_DEVBUF);
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;
}

View file

@ -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));
}