summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorpaul <paul@FreeBSD.org>2000-12-16 01:33:28 +0000
committerpaul <paul@FreeBSD.org>2000-12-16 01:33:28 +0000
commit00fcc3d35ac764fd8deb0e9698adee70e7c6fb1a (patch)
tree5ab459146d5f60f89822fc6bbc21d103480060b9 /sys
parent55b774ba6e1a3e1f4755f6ddd840757227d2d7d0 (diff)
downloadFreeBSD-src-00fcc3d35ac764fd8deb0e9698adee70e7c6fb1a.zip
FreeBSD-src-00fcc3d35ac764fd8deb0e9698adee70e7c6fb1a.tar.gz
Newbusify.
Temporarily disable PC98 until I bring it up to date.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/lnc/if_lnc.c262
-rw-r--r--sys/dev/lnc/if_lnc_isa.c471
-rw-r--r--sys/dev/lnc/if_lnc_pc98.c34
-rw-r--r--sys/dev/lnc/if_lnc_pci.c284
-rw-r--r--sys/dev/lnc/if_lncreg.h28
-rw-r--r--sys/dev/lnc/if_lncvar.h92
6 files changed, 627 insertions, 544 deletions
diff --git a/sys/dev/lnc/if_lnc.c b/sys/dev/lnc/if_lnc.c
index 1d77356..03f12be 100644
--- a/sys/dev/lnc/if_lnc.c
+++ b/sys/dev/lnc/if_lnc.c
@@ -30,15 +30,12 @@
* $FreeBSD$
*/
-/*
#define DIAGNOSTIC
#define DEBUG
+/*
*
* TODO ----
*
- * This driver will need bounce buffer support when dma'ing to mbufs above the
- * 16Mb mark.
- *
* Check all the XXX comments -- some of them are just things I've left
* unfinished rather than "difficult" problems that were hacked around.
*
@@ -65,13 +62,18 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/bus.h>
#include <sys/kernel.h>
-#include <sys/sockio.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
+#include <sys/module.h>
#include <sys/socket.h>
+#include <sys/sockio.h>
#include <sys/syslog.h>
-#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
#include <net/ethernet.h>
#include <net/if.h>
@@ -85,14 +87,9 @@
#include <machine/md_var.h>
-#include <i386/isa/isa_device.h>
#include <dev/lnc/if_lncvar.h>
#include <dev/lnc/if_lncreg.h>
-#ifndef COMPAT_OLDISA
-#error "The lnc device requires the old isa compatibility shims"
-#endif
-
static char const * const nic_ident[] = {
"Unknown",
"BICC",
@@ -116,23 +113,20 @@ static char const * const ic_ident[] = {
"PCnet-Home",
};
-static void lnc_setladrf __P((lnc_softc_t *sc));
-static void lnc_stop __P((lnc_softc_t *sc));
-static void lnc_reset __P((lnc_softc_t *sc));
-static void lnc_free_mbufs __P((lnc_softc_t *sc));
-static __inline int alloc_mbuf_cluster __P((lnc_softc_t *sc,
+static void lnc_setladrf __P((struct lnc_softc *sc));
+static void lnc_reset __P((struct lnc_softc *sc));
+static void lnc_free_mbufs __P((struct lnc_softc *sc));
+static __inline int alloc_mbuf_cluster __P((struct lnc_softc *sc,
struct host_ring_entry *desc));
-static __inline struct mbuf *chain_mbufs __P((lnc_softc_t *sc,
+static __inline struct mbuf *chain_mbufs __P((struct lnc_softc *sc,
int start_of_packet,
int pkt_len));
-static __inline struct mbuf *mbuf_packet __P((lnc_softc_t *sc,
+static __inline struct mbuf *mbuf_packet __P((struct lnc_softc *sc,
int start_of_packet,
int pkt_len));
-static __inline void lnc_rint __P((lnc_softc_t *sc));
-static __inline void lnc_tint __P((lnc_softc_t *sc));
-extern int lnc_probe __P((struct isa_device *isa_dev));
-int lnc_attach_sc __P((lnc_softc_t *sc, int unit));
-extern int lnc_attach __P((struct isa_device *isa_dev));
+static __inline void lnc_rint __P((struct lnc_softc *sc));
+static __inline void lnc_tint __P((struct lnc_softc *sc));
+
static void lnc_init __P((void *));
static __inline int mbuf_to_buffer __P((struct mbuf *m, char *buffer));
static __inline struct mbuf *chain_to_cluster __P((struct mbuf *m));
@@ -140,29 +134,40 @@ static void lnc_start __P((struct ifnet *ifp));
static int lnc_ioctl __P((struct ifnet *ifp, u_long command, caddr_t data));
static void lnc_watchdog __P((struct ifnet *ifp));
#ifdef DEBUG
-void lnc_dump_state __P((lnc_softc_t *sc));
+void lnc_dump_state __P((struct lnc_softc *sc));
void mbuf_dump_chain __P((struct mbuf *m));
#endif
-void lncintr_sc __P((lnc_softc_t *sc));
+void write_csr(struct lnc_softc *, u_short, u_short);
+u_short read_csr(struct lnc_softc *, u_short);
+void lnc_release_resources(device_t);
-struct isa_driver lncdriver = {
- INTR_TYPE_NET,
- lnc_probe,
- lnc_attach,
- "lnc"
-};
-COMPAT_ISA_DRIVER(lnc, lncdriver);
+u_short
+read_csr(struct lnc_softc *sc, u_short port)
+{
+ bus_space_write_2(sc->lnc_btag, sc->lnc_bhandle, sc->rap, port);
+ return(bus_space_read_2(sc->lnc_btag, sc->lnc_bhandle, sc->rdp));
+}
+
+void
+write_csr(struct lnc_softc *sc, u_short port, u_short val)
+{
+ bus_space_write_2(sc->lnc_btag, sc->lnc_bhandle, sc->rap, port);
+ bus_space_write_2(sc->lnc_btag, sc->lnc_bhandle, sc->rdp, val);
+}
+
+#define inw(port) bus_space_read_2(sc->lnc_btag, sc->lnc_bhandle, port)
+#define outw(port, val) bus_space_write_2(sc->lnc_btag, sc->lnc_bhandle, port, val)
static __inline void
-write_bcr(lnc_softc_t *sc, u_short port, u_short val)
+write_bcr(struct lnc_softc *sc, u_short port, u_short val)
{
outw(sc->rap, port);
outw(sc->bdp, val);
}
static __inline u_short
-read_bcr(lnc_softc_t *sc, u_short port)
+read_bcr(struct lnc_softc *sc, u_short port)
{
outw(sc->rap, port);
return (inw(sc->bdp));
@@ -186,11 +191,36 @@ ether_crc(const u_char *ether_addr)
#undef POLYNOMIAL
}
+void
+lnc_release_resources(device_t dev)
+{
+ lnc_softc_t *sc = device_get_softc(dev);
+
+ if (sc->irqres) {
+ bus_teardown_intr(dev, sc->irqres, sc->intrhand);
+ bus_release_resource(dev, SYS_RES_IRQ, sc->irqrid, sc->irqres);
+ }
+
+ if (sc->portres)
+ bus_release_resource(dev, SYS_RES_IOPORT,
+ sc->portrid, sc->portres);
+ if (sc->drqres)
+ bus_release_resource(dev, SYS_RES_DRQ, sc->drqrid, sc->drqres);
+
+ if (sc->dmat) {
+ if (sc->dmamap) {
+ bus_dmamap_unload(sc->dmat, sc->dmamap);
+ bus_dmamem_free(sc->dmat, sc->recv_ring, sc->dmamap);
+ }
+ bus_dma_tag_destroy(sc->dmat);
+ }
+}
+
/*
* Set up the logical address filter for multicast packets
*/
static __inline void
-lnc_setladrf(lnc_softc_t *sc)
+lnc_setladrf(struct lnc_softc *sc)
{
struct ifnet *ifp = &sc->arpcom.ac_if;
struct ifmultiaddr *ifma;
@@ -222,20 +252,20 @@ lnc_setladrf(lnc_softc_t *sc)
}
}
-static void
-lnc_stop(lnc_softc_t *sc)
+void
+lnc_stop(struct lnc_softc *sc)
{
write_csr(sc, CSR0, STOP);
}
static void
-lnc_reset(lnc_softc_t *sc)
+lnc_reset(struct lnc_softc *sc)
{
lnc_init(sc);
}
static void
-lnc_free_mbufs(lnc_softc_t *sc)
+lnc_free_mbufs(struct lnc_softc *sc)
{
int i;
@@ -257,7 +287,7 @@ lnc_free_mbufs(lnc_softc_t *sc)
}
static __inline int
-alloc_mbuf_cluster(lnc_softc_t *sc, struct host_ring_entry *desc)
+alloc_mbuf_cluster(struct lnc_softc *sc, struct host_ring_entry *desc)
{
register struct mds *md = desc->md;
struct mbuf *m=0;
@@ -290,7 +320,7 @@ alloc_mbuf_cluster(lnc_softc_t *sc, struct host_ring_entry *desc)
}
static __inline struct mbuf *
-chain_mbufs(lnc_softc_t *sc, int start_of_packet, int pkt_len)
+chain_mbufs(struct lnc_softc *sc, int start_of_packet, int pkt_len)
{
struct mbuf *head, *m;
struct host_ring_entry *desc;
@@ -325,7 +355,7 @@ chain_mbufs(lnc_softc_t *sc, int start_of_packet, int pkt_len)
}
static __inline struct mbuf *
-mbuf_packet(lnc_softc_t *sc, int start_of_packet, int pkt_len)
+mbuf_packet(struct lnc_softc *sc, int start_of_packet, int pkt_len)
{
struct host_ring_entry *start;
@@ -400,7 +430,7 @@ mbuf_packet(lnc_softc_t *sc, int start_of_packet, int pkt_len)
static __inline void
-lnc_rint(lnc_softc_t *sc)
+lnc_rint(struct lnc_softc *sc)
{
struct host_ring_entry *next, *start;
int start_of_packet;
@@ -552,19 +582,18 @@ lnc_rint(lnc_softc_t *sc)
* vmware ethernet hardware emulation loops
* packets back to itself, violates IFF_SIMPLEX.
* drop it if it is from myself.
- */
+ */
if (bcmp(eh->ether_shost,
sc->arpcom.ac_enaddr, ETHER_ADDR_LEN) == 0) {
- m_freem(head);
+ m_freem(head);
} else {
- /* Skip over the ether header */
- head->m_data += sizeof *eh;
- head->m_len -= sizeof *eh;
- head->m_pkthdr.len -= sizeof *eh;
+ /* Skip over the ether header */
+ head->m_data += sizeof *eh;
+ head->m_len -= sizeof *eh;
+ head->m_pkthdr.len -= sizeof *eh;
- ether_input(&sc->arpcom.ac_if, eh, head);
+ ether_input(&sc->arpcom.ac_if, eh, head);
}
-
} else {
int unit = sc->arpcom.ac_if.if_unit;
log(LOG_ERR,"lnc%d: Packet dropped, no mbufs\n",unit);
@@ -585,7 +614,7 @@ lnc_rint(lnc_softc_t *sc)
}
static __inline void
-lnc_tint(lnc_softc_t *sc)
+lnc_tint(struct lnc_softc *sc)
{
struct host_ring_entry *next, *start;
int start_of_packet;
@@ -817,71 +846,20 @@ lnc_tint(lnc_softc_t *sc)
*/
outw(sc->rdp, TINT | INEA);
-
- /* XXX only while doing if_is comparisons */
- if (!(sc->arpcom.ac_if.if_flags & IFF_OACTIVE))
- lnc_start(&sc->arpcom.ac_if);
-
}
int
-lnc_attach_sc(lnc_softc_t *sc, int unit)
+lnc_attach_common(device_t dev)
{
- int lnc_mem_size;
-
- /*
- * Allocate memory for use by the controller.
- *
- * XXX -- the Am7990 and Am79C960 only have 24 address lines and so can
- * only access the lower 16Mb of physical memory. For the moment we
- * assume that malloc will allocate memory within the lower 16Mb
- * range. This is not a very valid assumption but there's nothing
- * that can be done about it yet. For shared memory NICs this isn't
- * relevant.
- *
- */
-
- lnc_mem_size = ((NDESC(sc->nrdre) + NDESC(sc->ntdre)) *
- sizeof(struct host_ring_entry));
-
- if (sc->nic.mem_mode != SHMEM)
- lnc_mem_size += sizeof(struct init_block) + (sizeof(struct mds) *
- (NDESC(sc->nrdre) + NDESC(sc->ntdre))) +
- MEM_SLEW;
-
- /* If using DMA to fixed host buffers then allocate memory for them */
-
- if (sc->nic.mem_mode == DMA_FIXED)
- lnc_mem_size += (NDESC(sc->nrdre) * RECVBUFSIZE) + (NDESC(sc->ntdre) * TRANSBUFSIZE);
-
- if (sc->nic.mem_mode != SHMEM) {
- if (sc->nic.ic < PCnet_32) {
- /* ISA based cards */
- sc->recv_ring = contigmalloc(lnc_mem_size, M_DEVBUF, M_NOWAIT,
- 0ul, 0xfffffful, 4ul, 0x1000000);
- } else {
- /* Non-ISA based cards, 32 bit capable */
-#ifdef notyet
- /*
- * For the 32 bit driver we're not fussed where we DMA to
- * though it'll still need to be contiguous
- */
- sc->recv_ring = malloc(lnc_mem_size, M_DEVBUF, M_NOWAIT);
-#else
- /*
- * For now it still needs to be below 16MB because the
- * descriptor's can only hold 16 bit addresses.
- */
- sc->recv_ring = contigmalloc(lnc_mem_size, M_DEVBUF, M_NOWAIT,
- 0ul, 0xfffffful, 4ul, 0x1000000);
-#endif
- }
- }
+ int unit = device_get_unit(dev);
+ lnc_softc_t *sc = device_get_softc(dev);
+ int i;
+ int skip;
- if (!sc->recv_ring) {
- log(LOG_ERR, "lnc%d: Couldn't allocate memory for NIC\n", unit);
- return (0); /* XXX -- attach failed -- not tested in
- * calling routines */
+ if (sc->nic.ident == BICC) {
+ skip = 2;
+ } else {
+ skip = 1;
}
/* Set default mode */
@@ -890,9 +868,8 @@ lnc_attach_sc(lnc_softc_t *sc, int unit)
/* Fill in arpcom structure entries */
sc->arpcom.ac_if.if_softc = sc;
- sc->arpcom.ac_if.if_name = lncdriver.name;
+ sc->arpcom.ac_if.if_name = "lnc";
sc->arpcom.ac_if.if_unit = unit;
- sc->arpcom.ac_if.if_mtu = ETHERMTU;
sc->arpcom.ac_if.if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
sc->arpcom.ac_if.if_timer = 0;
sc->arpcom.ac_if.if_output = ether_output;
@@ -900,11 +877,16 @@ lnc_attach_sc(lnc_softc_t *sc, int unit)
sc->arpcom.ac_if.if_ioctl = lnc_ioctl;
sc->arpcom.ac_if.if_watchdog = lnc_watchdog;
sc->arpcom.ac_if.if_init = lnc_init;
- sc->arpcom.ac_if.if_type = IFT_ETHER;
- sc->arpcom.ac_if.if_addrlen = ETHER_ADDR_LEN;
- sc->arpcom.ac_if.if_hdrlen = ETHER_HDR_LEN;
sc->arpcom.ac_if.if_snd.ifq_maxlen = IFQ_MAXLEN;
+ /* Extract MAC address from PROM */
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ sc->arpcom.ac_enaddr[i] = inb(sc->iobase + (i * skip));
+
+ /*
+ * XXX -- should check return status of if_attach
+ */
+
ether_ifattach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
printf("lnc%d: ", unit);
@@ -922,14 +904,16 @@ static void
lnc_init(xsc)
void *xsc;
{
- lnc_softc_t *sc = xsc;
+ struct lnc_softc *sc = xsc;
int s, i;
char *lnc_mem;
/* Check that interface has valid address */
- if (TAILQ_EMPTY(&sc->arpcom.ac_if.if_addrhead)) /* XXX unlikely */
+ if (TAILQ_EMPTY(&sc->arpcom.ac_if.if_addrhead)) { /* XXX unlikely */
+printf("XXX no address?\n");
return;
+ }
/* Shut down interface */
@@ -947,8 +931,6 @@ lnc_init(xsc)
* The alignment tests are particularly paranoid.
*/
-
-
sc->recv_next = 0;
sc->trans_ring = sc->recv_ring + NDESC(sc->nrdre);
sc->trans_next = 0;
@@ -1066,11 +1048,11 @@ lnc_init(xsc)
write_csr(sc, CSR3, 0);
/* Let's see if it starts */
-
- write_csr(sc, CSR0, INIT);
- for (i = 0; i < 1000; i++)
- if (read_csr(sc, CSR0) & IDON)
- break;
+/*
+printf("Enabling lnc interrupts\n");
+ sc->arpcom.ac_if.if_timer = 10;
+ write_csr(sc, CSR0, INIT|INEA);
+*/
/*
* Now that the initialisation is complete there's no reason to
@@ -1079,6 +1061,11 @@ lnc_init(xsc)
* time.
*/
+ write_csr(sc, CSR0, INIT);
+ for(i=0; i < 1000; i++)
+ if (read_csr(sc, CSR0) & IDON)
+ break;
+
if (read_csr(sc, CSR0) & IDON) {
/*
* Enable interrupts, start the LANCE, mark the interface as
@@ -1117,8 +1104,9 @@ lnc_init(xsc)
*/
void
-lncintr_sc(lnc_softc_t *sc)
+lncintr(void *arg)
{
+ lnc_softc_t *sc = arg;
int unit = sc->arpcom.ac_if.if_unit;
u_short csr0;
@@ -1137,10 +1125,20 @@ lncintr_sc(lnc_softc_t *sc)
* be missed.
*/
-/* outw(sc->rdp, IDON | CERR | BABL | MISS | MERR | RINT | TINT | INEA); */
outw(sc->rdp, csr0);
+ /*outw(sc->rdp, IDON | CERR | BABL | MISS | MERR | RINT | TINT | INEA);*/
- /* We don't do anything with the IDON flag */
+#ifdef notyet
+ if (csr0 & IDON) {
+printf("IDON\n");
+ sc->arpcom.ac_if.if_timer = 0;
+ write_csr(sc, CSR0, STRT | INEA);
+ sc->arpcom.ac_if.if_flags |= IFF_RUNNING;
+ sc->arpcom.ac_if.if_flags &= ~IFF_OACTIVE;
+ lnc_start(&sc->arpcom.ac_if);
+ continue;
+ }
+#endif
if (csr0 & ERR) {
if (csr0 & CERR) {
@@ -1228,7 +1226,7 @@ static void
lnc_start(struct ifnet *ifp)
{
- lnc_softc_t *sc = ifp->if_softc;
+ struct lnc_softc *sc = ifp->if_softc;
struct host_ring_entry *desc;
int tmp;
int end_of_packet;
@@ -1384,7 +1382,7 @@ static int
lnc_ioctl(struct ifnet * ifp, u_long command, caddr_t data)
{
- lnc_softc_t *sc = ifp->if_softc;
+ struct lnc_softc *sc = ifp->if_softc;
int s, error = 0;
s = splimp();
@@ -1462,7 +1460,7 @@ lnc_watchdog(struct ifnet *ifp)
#ifdef DEBUG
void
-lnc_dump_state(lnc_softc_t *sc)
+lnc_dump_state(struct lnc_softc *sc)
{
int i;
diff --git a/sys/dev/lnc/if_lnc_isa.c b/sys/dev/lnc/if_lnc_isa.c
index ce501b5..5c298d1 100644
--- a/sys/dev/lnc/if_lnc_isa.c
+++ b/sys/dev/lnc/if_lnc_isa.c
@@ -1,6 +1,6 @@
-/*-
- * Copyright (c) 2000
- * Paul Richards. All rights reserved.
+/*
+ * Copyright (c) 1994-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
@@ -31,98 +31,72 @@
*/
#include <sys/param.h>
-#include <sys/malloc.h>
#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/socket.h>
+#include <machine/bus_memio.h>
+#include <machine/bus_pio.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
#include <net/ethernet.h>
#include <net/if.h>
-#include <net/if_dl.h>
-#include <net/if_types.h>
+#include <net/if_arp.h>
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
+#include <isa/isavar.h>
-#include <i386/isa/isa_device.h>
-#include <dev/lnc/if_lncvar.h>
-#include <dev/lnc/if_lncreg.h>
+#include <dev/lnc/if_lnc.h>
-int ne2100_probe __P((lnc_softc_t *, unsigned));
-int bicc_probe __P((lnc_softc_t *, unsigned));
-int depca_probe __P((lnc_softc_t *, unsigned));
-#ifdef PC98
-int cnet98s_probe __P((lnc_softc_t *, unsigned));
-#endif
-int lance_probe __P((lnc_softc_t *));
-int pcnet_probe __P((lnc_softc_t *));
-int lnc_probe __P((struct isa_device *));
-int lnc_attach __P((struct isa_device *));
-
-static int dec_macaddr_extract __P((u_char[], lnc_softc_t *));
-static ointhand2_t lncintr;
+static struct isa_pnp_id lnc_pnp_ids[] = {
+ {0, NULL}
+};
-extern int lnc_attach_sc __P((lnc_softc_t *, int));
-extern void lncintr_sc __P((lnc_softc_t *));
+extern void write_csr(struct lnc_softc *, u_short, u_short);
+extern u_short read_csr(struct lnc_softc *, u_short);
+extern void lnc_release_resources(device_t);
-static lnc_softc_t *
-lnc_getsoftc(int unit)
+static int
+lance_probe(struct lnc_softc *sc)
{
- static lnc_softc_t **sc;
- static int units;
-
- if (unit >= units) {
- /* Reallocate more softc pointers */
-
- lnc_softc_t **nsc;
- int n;
-
- n = unit + 1;
- nsc = malloc(sizeof(lnc_softc_t *) * n, M_DEVBUF, M_WAITOK);
- if (units)
- bcopy(sc, nsc, sizeof(lnc_softc_t *) * units);
- bzero(nsc + units, sizeof(lnc_softc_t *) * (n - units));
- if (sc)
- free(sc, M_DEVBUF);
- units = n;
- sc = nsc;
- }
-
- if (sc[unit] == NULL)
- sc[unit] = malloc(sizeof(lnc_softc_t), M_DEVBUF, M_WAITOK);
+ write_csr(sc, CSR0, STOP);
- return sc[unit];
+ if ((bus_space_read_2(sc->lnc_btag, sc->lnc_bhandle, 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
-ne2100_probe(lnc_softc_t *sc, unsigned iobase)
+static int
+lnc_legacy_probe(device_t dev)
{
- int i;
+ struct lnc_softc *sc = device_get_softc(dev);
- 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;
+ sc->portrid = 0;
+ sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->portrid,
+ 0, ~0, 1, RF_ACTIVE);
- /* 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);
+ if (! sc->portres) {
+ device_printf(dev, "Failed to allocate I/O ports\n");
+ lnc_release_resources(dev);
+ return (ENXIO);
}
-}
-int
-bicc_probe(lnc_softc_t *sc, unsigned iobase)
-{
- int i;
+ sc->lnc_btag = rman_get_bustag(sc->portres);
+ sc->lnc_bhandle = rman_get_bushandle(sc->portres);
/*
* There isn't any way to determine if a NIC is a BICC. Basically, if
@@ -130,204 +104,213 @@ bicc_probe(lnc_softc_t *sc, unsigned iobase)
* we assume it's a BICC.
*
*/
-
- sc->rap = iobase + BICC_RAP;
- sc->rdp = iobase + BICC_RDP;
-
- /* I think all these cards us the Am7990 */
+ sc->rap = BICC_RAP;
+ sc->rdp = BICC_RDP;
+ sc->nic.mem_mode = DMA_FIXED;
+ /* XXX Should set BICC_IOSIZE et al somewhere to alloc
+ resources correctly */
if ((sc->nic.ic = lance_probe(sc))) {
+ device_set_desc(dev, "BICC Isolan");
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);
+ lnc_release_resources(dev);
+ return (0);
} else {
+ /* It's not a BICC so try the standard NE2100 ports */
+ sc->rap = PCNET_RAP;
+ sc->rdp = PCNET_RDP;
+ if ((sc->nic.ic = lance_probe(sc))) {
+ sc->nic.ident = NE2100;
+ device_set_desc(dev, "NE2100");
+ lnc_release_resources(dev);
return (0);
+ } else {
+ lnc_release_resources(dev);
+ return (ENXIO);
+ }
}
}
-/*
- * 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[], lnc_softc_t * sc)
+lnc_isa_probe(device_t dev)
{
- 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);
- }
+ int pnp;
+
+ pnp = ISA_PNP_PROBE(device_get_parent(dev), dev, lnc_pnp_ids);
+ if (pnp == ENOENT) {
+ /* It's not a PNP card, see if we support it by probing it */
+ return (lnc_legacy_probe(dev));
+ } else if (pnp == ENXIO) {
+ return (ENXIO);
+ } else {
+ /* Found PNP card we support */
+ return (0);
}
- return (0);
}
-int
-depca_probe(lnc_softc_t *sc, unsigned iobase)
+static void
+lnc_alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)
{
- int i;
- unsigned char maddr_ring[DEPCA_ADDR_ROM_SIZE];
+ /* Do nothing */
+ return;
+}
- sc->rap = iobase + DEPCA_RAP;
- sc->rdp = iobase + DEPCA_RDP;
+static int
+lnc_isa_attach(device_t dev)
+{
+ lnc_softc_t *sc = device_get_softc(dev);
+ int err = 0;
+ bus_size_t lnc_mem_size;
- 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);
- }
+ device_printf(dev, "Attaching %s\n", device_get_desc(dev));
+
+ sc->portrid = 0;
+ sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->portrid,
+ 0, ~0, 1, RF_ACTIVE);
+
+ if (! sc->portres) {
+ device_printf(dev, "Failed to allocate I/O ports\n");
+ lnc_release_resources(dev);
+ return (ENXIO);
}
- return (0);
-}
-int
-lance_probe(lnc_softc_t *sc)
-{
- write_csr(sc, CSR0, STOP);
+ sc->drqrid = 0;
+ sc->drqres = bus_alloc_resource(dev, SYS_RES_DRQ, &sc->drqrid,
+ 0, ~0, 1, RF_ACTIVE);
- 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);
-}
+ if (! sc->drqres) {
+ device_printf(dev, "Failed to allocate DMA channel\n");
+ lnc_release_resources(dev);
+ return (ENXIO);
+ }
-int
-pcnet_probe(lnc_softc_t *sc)
-{
- u_long chip_id;
- int type;
+ if (isa_get_irq(dev) == -1)
+ bus_set_resource(dev, SYS_RES_IRQ, 0, 10, 1);
- /*
- * 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.
- */
+ sc->irqrid = 0;
+ sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irqrid, 0, ~0, 1,
+ RF_ACTIVE);
- 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:
- case Am79C973:
- return (PCnet_FASTplus);
- case Am79C978:
- return (PCnet_Home);
- default:
- break;
- }
- }
+ if (! sc->irqres) {
+ device_printf(dev, "Failed to allocate irq\n");
+ lnc_release_resources(dev);
+ return (ENXIO);
}
- return (type);
-}
-int
-lnc_probe(struct isa_device * isa_dev)
-{
- int nports;
- int unit = isa_dev->id_unit;
- lnc_softc_t *sc = lnc_getsoftc(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
+ err = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, lncintr,
+ sc, &sc->intrhand);
- 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);
-}
+ if (err) {
+ device_printf(dev, "Failed to setup irq handler\n");
+ lnc_release_resources(dev);
+ return (err);
+ }
-int
-lnc_attach(struct isa_device * isa_dev)
-{
- int unit = isa_dev->id_unit;
- lnc_softc_t *sc = lnc_getsoftc(unit);
- int result;
+ /* XXX temp setting for nic */
+ sc->nic.mem_mode = DMA_FIXED;
+ sc->nrdre = NRDRE;
+ sc->ntdre = NTDRE;
- isa_dev->id_ointr = lncintr;
- result = lnc_attach_sc (sc, unit);
- if (result == 0)
- return (0);
+ if (sc->nic.ident == NE2100) {
+ sc->rap = PCNET_RAP;
+ sc->rdp = PCNET_RDP;
+ sc->bdp = PCNET_BDP;
+ } else {
+ sc->rap = BICC_RAP;
+ sc->rdp = BICC_RDP;
+ }
-#ifndef PC98
- /*
- * XXX - is it safe to call isa_dmacascade() after
- * ether_ifattach() has been called in lnc_attach() ???
- */
- if ((sc->nic.mem_mode != SHMEM) &&
- (sc->nic.ic < PCnet_32))
- isa_dmacascade(isa_dev->id_drq);
-#endif
+ printf("rap = %x\n", sc->rap);
+
+ /* Create a DMA tag describing the ring memory we need */
+
+ lnc_mem_size = ((NDESC(sc->nrdre) + NDESC(sc->ntdre)) *
+ sizeof(struct host_ring_entry));
+
+ lnc_mem_size += (NDESC(sc->nrdre) * RECVBUFSIZE) +
+ (NDESC(sc->ntdre) * TRANSBUFSIZE);
+
+ err = bus_dma_tag_create(NULL, /* parent */
+ 4, /* alignement */
+ 0, /* boundary */
+ BUS_SPACE_MAXADDR_24BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ lnc_mem_size, /* segsize */
+ 1, /* nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ &sc->dmat);
+
+ if (err) {
+ device_printf(dev, "Can't create DMA tag\n");
+ lnc_release_resources(dev);
+ return (ENOMEM);
+ }
+
+ err = bus_dmamem_alloc(sc->dmat, (void **)&sc->recv_ring,
+ BUS_DMA_NOWAIT, &sc->dmamap);
+
+ if (err) {
+ device_printf(dev, "Couldn't allocate memory\n");
+ lnc_release_resources(dev);
+ return (ENOMEM);
+ }
+
+ err = bus_dmamap_load(sc->dmat, sc->dmamap, sc->recv_ring, lnc_mem_size,
+ lnc_alloc_callback, sc->recv_ring, BUS_DMA_NOWAIT);
+
+ if (err) {
+ device_printf(dev, "Couldn't load DMA map\n");
+ lnc_release_resources(dev);
+ return (ENOMEM);
+ }
+
+ isa_dmacascade(rman_get_start(sc->drqres));
- return result;
+ /* Call generic attach code */
+ if (! lnc_attach_common(dev)) {
+ device_printf(dev, "Generic attach code failed\n");
+ lnc_release_resources(dev);
+ return (ENXIO);
+ }
+ return (0);
}
-static void
-lncintr(int unit)
+static int
+lnc_isa_detach(device_t dev)
{
- lncintr_sc(lnc_getsoftc(unit));
+ lnc_softc_t *sc = device_get_softc(dev);
+ int s = splimp();
+
+ ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
+ splx(s);
+
+ lnc_stop(sc);
+ lnc_release_resources(dev);
+
+ return (0);
}
+
+static device_method_t lnc_isa_methods[] = {
+/* DEVMETHOD(device_identify, lnc_isa_identify), */
+ DEVMETHOD(device_probe, lnc_isa_probe),
+ DEVMETHOD(device_attach, lnc_isa_attach),
+ DEVMETHOD(device_detach, lnc_isa_detach),
+#ifdef notyet
+ DEVMETHOD(device_suspend, lnc_isa_suspend),
+ DEVMETHOD(device_resume, lnc_isa_resume),
+ DEVMETHOD(device_shutdown, lnc_isa_shutdown),
+#endif
+ { 0, 0 }
+};
+
+static driver_t lnc_isa_driver = {
+ "lnc",
+ lnc_isa_methods,
+ sizeof(struct lnc_softc),
+};
+
+static devclass_t lnc_devclass;
+
+DRIVER_MODULE(lnc_isa, isa, lnc_isa_driver, lnc_devclass, 0, 0);
diff --git a/sys/dev/lnc/if_lnc_pc98.c b/sys/dev/lnc/if_lnc_pc98.c
index 4484a14..f05a3f5 100644
--- a/sys/dev/lnc/if_lnc_pc98.c
+++ b/sys/dev/lnc/if_lnc_pc98.c
@@ -30,6 +30,8 @@
* $FreeBSD$
*/
+#ifdef notyet
+
#ifdef PC98
#include "lnc.h"
@@ -55,35 +57,6 @@
int pcnet_probe __P((lnc_softc_t *sc));
int cnet98s_probe __P((lnc_softc_t *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 */
-
int
cnet98s_probe(lnc_softc_t *sc, unsigned iobase)
{
@@ -144,4 +117,7 @@ cnet98s_probe(lnc_softc_t *sc, unsigned iobase)
return (CNET98S_IOSIZE);
}
+
#endif
+
+#endif /* notyet */
diff --git a/sys/dev/lnc/if_lnc_pci.c b/sys/dev/lnc/if_lnc_pci.c
index c69716d..7ef57d5 100644
--- a/sys/dev/lnc/if_lnc_pci.c
+++ b/sys/dev/lnc/if_lnc_pci.c
@@ -1,142 +1,220 @@
/*
- *
- * Copyright (c) 1996 Stefan Esser <se@freebsd.org>
- * All rights reserved.
+ * Copyright (c) 1994-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 immediately at the beginning of the file, without modification,
- * this list of conditions, and the following disclaimer.
+ * 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. Absolutely no warranty of function or purpose is made by the author
- * Stefan Esser.
- * 4. Modifications may be freely made to this file if the above conditions
- * are met.
+ * 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 <sys/malloc.h>
#include <sys/kernel.h>
-#include <pci/pcireg.h>
-#include <pci/pcivar.h>
-#include <sys/socket.h>
+#include <machine/bus_memio.h>
+#include <machine/bus_pio.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/bus.h>
+#include <sys/rman.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
-#error "The lnc device requires the old pci compatibility shims"
-#endif
-
-#define PCI_DEVICE_ID_PCNet_PCI 0x20001022
-#define PCI_DEVICE_ID_PCHome_PCI 0x20011022
+#include <net/if_arp.h>
-extern int pcnet_probe __P((lnc_softc_t *sc));
-extern int lnc_attach_sc __P((lnc_softc_t *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));
-
-static u_long lnc_pci_count = NLNC;
+#include <pci/pcireg.h>
+#include <pci/pcivar.h>
-static struct pci_device lnc_pci_driver = {
- "lnc",
- lnc_pci_probe,
- lnc_pci_attach,
- &lnc_pci_count,
- NULL
-};
+#include <dev/lnc/if_lnc.h>
-COMPAT_PCI_DRIVER (lnc_pci, lnc_pci_driver);
+#define AMD_VENDOR_ID 0x1022
+#define PCI_DEVICE_ID_PCNet_PCI 0x2000
+#define PCI_DEVICE_ID_PCHome_PCI 0x2001
-static const char*
-lnc_pci_probe (pcici_t tag, pcidi_t type)
+static int
+lnc_pci_probe(device_t dev)
{
- switch(type) {
+ if (pci_get_vendor(dev) != AMD_VENDOR_ID)
+ return (ENXIO);
+
+ switch(pci_get_device(dev)) {
case PCI_DEVICE_ID_PCNet_PCI:
- return ("PCNet/PCI Ethernet adapter");
+ device_set_desc(dev, "PCNet/PCI Ethernet adapter");
+ return(0);
break;
case PCI_DEVICE_ID_PCHome_PCI:
- return ("PCHome/PCI Ethernet adapter");
+ device_set_desc(dev, "PCHome/PCI Ethernet adapter");
+ return(0);
break;
default:
+ return (ENXIO);
break;
}
- return (0);
+ return (ENXIO);
}
-void lncintr_sc (void*);
-
static void
-lnc_pci_attach(config_id, unit)
- pcici_t config_id;
- int unit;
+lnc_alloc_callback(void *arg, bus_dma_segment_t *seg, int nseg, int error)
{
- lnc_softc_t *sc;
- unsigned iobase;
- unsigned data; /* scratch to make this device a bus master*/
- 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);
-
-
- /* Make this device a bus master. This was implictly done by
- pci_map_port under 2.2.x -- tvf */
-
- data = pci_cfgread(config_id, PCIR_COMMAND, 4);
- data |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN;
- pci_cfgwrite(config_id, PCIR_COMMAND, data, 4);
-
- sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT | M_ZERO);
-
- if (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);
- }
+ /* Do nothing */
+ return;
+}
+
+static int
+lnc_pci_attach(device_t dev)
+{
+ lnc_softc_t *sc = device_get_softc(dev);
+ unsigned command;
+ int rid = 0;
+ int err = 0;
+ bus_size_t lnc_mem_size;
+
+ device_printf(dev, "Attaching %s\n", device_get_desc(dev));
+
+ command = pci_read_config(dev, PCIR_COMMAND, 4);
+ command |= PCIM_CMD_PORTEN | PCIM_CMD_BUSMASTEREN;
+ pci_write_config(dev, PCIR_COMMAND, command, 4);
+
+ rid = PCIR_MAPS;
+ sc->portres = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 1,
+ RF_ACTIVE);
+
+ if (! sc->portres)
+ device_printf(dev, "Cannot allocate I/O ports\n");
+
+ rid = 0;
+ sc->irqres = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
+ RF_ACTIVE|RF_SHAREABLE);
+
+ if (! sc->irqres)
+ device_printf(dev, "Cannot allocate irq\n");
+
+ err = bus_setup_intr(dev, sc->irqres, INTR_TYPE_NET, lncintr,
+ sc, &sc->intrhand);
+ if (err)
+ device_printf(dev, "Cannot setup irq handler\n");
+
+ sc->iobase = rman_get_start(sc->portres);
+
+ /* XXX temp setting for nic */
+ sc->nic.ic = PCnet_PCI;
+ sc->nic.ident = NE2100;
+ sc->nic.mem_mode = DMA_FIXED;
+ sc->nrdre = NRDRE;
+ sc->ntdre = NTDRE;
+ sc->rap = sc->iobase + PCNET_RAP;
+ sc->rdp = sc->iobase + PCNET_RDP;
+ sc->bdp = sc->iobase + PCNET_BDP;
+
+ /* Create a DMA tag describing the ring memory we need */
+
+ lnc_mem_size = ((NDESC(sc->nrdre) + NDESC(sc->ntdre)) *
+ sizeof(struct host_ring_entry));
+
+ lnc_mem_size += (NDESC(sc->nrdre) * RECVBUFSIZE) +
+ (NDESC(sc->ntdre) * TRANSBUFSIZE);
+
+ err = bus_dma_tag_create(NULL, /* parent */
+ 1, /* alignement */
+ 0, /* boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ lnc_mem_size, /* segsize */
+ 1, /* nsegments */
+ BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
+ 0, /* flags */
+ &sc->dmat);
+
+ if (err) {
+ device_printf(dev, "Can't create DMA tag\n");
+ /* XXX need to free currently allocated resources here */
+ return (ENOMEM);
}
- return;
+ err = bus_dmamem_alloc(sc->dmat, (void **)&sc->recv_ring,
+ BUS_DMA_NOWAIT, &sc->dmamap);
+
+ if (err) {
+ device_printf(dev, "Couldn't allocate memory\n");
+ /* XXX need to free currently allocated resources here */
+ return (ENOMEM);
+ }
+
+ bus_dmamap_load(sc->dmat, sc->dmamap, sc->recv_ring, lnc_mem_size,
+ lnc_alloc_callback, sc->recv_ring, BUS_DMA_NOWAIT);
+
+ /* Call generic attach code */
+ if (! lnc_attach_common(dev)) {
+ device_printf(dev, "Generic attach code failed\n");
+ }
+ return (0);
+}
+
+static int
+lnc_pci_detach(device_t dev)
+{
+ lnc_softc_t *sc = device_get_softc(dev);
+ int s = splimp();
+
+ ether_ifdetach(&sc->arpcom.ac_if, ETHER_BPF_SUPPORTED);
+
+ lnc_stop(sc);
+ bus_teardown_intr(dev, sc->irqres, sc->intrhand);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irqres);
+ bus_release_resource(dev, SYS_RES_IOPORT, PCIR_MAPS, sc->portres);
+
+ bus_dmamap_unload(sc->dmat, sc->dmamap);
+ bus_dmamem_free(sc->dmat, sc->recv_ring, sc->dmamap);
+ bus_dma_tag_destroy(sc->dmat);
+
+ splx(s);
+ return (0);
}
+
+static device_method_t lnc_pci_methods[] = {
+ DEVMETHOD(device_probe, lnc_pci_probe),
+ DEVMETHOD(device_attach, lnc_pci_attach),
+ DEVMETHOD(device_detach, lnc_pci_detach),
+#ifdef notyet
+ DEVMETHOD(device_suspend, lnc_pci_suspend),
+ DEVMETHOD(device_resume, lnc_pci_resume),
+ DEVMETHOD(device_shutdown, lnc_pci_shutdown),
+#endif
+ { 0, 0 }
+};
+
+static driver_t lnc_pci_driver = {
+ "lnc",
+ lnc_pci_methods,
+ sizeof(struct lnc_softc),
+};
+
+static devclass_t lnc_devclass;
+
+DRIVER_MODULE(lnc_pci, pci, lnc_pci_driver, lnc_devclass, 0, 0);
diff --git a/sys/dev/lnc/if_lncreg.h b/sys/dev/lnc/if_lncreg.h
index ae584c2..a57d7ff 100644
--- a/sys/dev/lnc/if_lncreg.h
+++ b/sys/dev/lnc/if_lncreg.h
@@ -192,3 +192,31 @@ struct mds {
#define RTRY 0x0400 /* Tried 16 times */
#define TDR 0x03FF /* Time domain reflectometry */
+/* 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 */
diff --git a/sys/dev/lnc/if_lncvar.h b/sys/dev/lnc/if_lncvar.h
index c1ba321..df205ea 100644
--- a/sys/dev/lnc/if_lncvar.h
+++ b/sys/dev/lnc/if_lncvar.h
@@ -33,6 +33,8 @@
* $FreeBSD$
*/
+#include <dev/lnc/if_lncreg.h>
+
/*
* Initialize multicast address hashing registers to accept
* all multicasts (only used when in promiscuous mode)
@@ -76,6 +78,20 @@
/* 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 */
@@ -101,7 +117,7 @@
#define Am79C970A 0x2621
#define Am79C971 0x2623
#define Am79C972 0x2624
-#define Am79C973 0x2625
+#define Am79C972 0x2625
#define Am79C978 0x2626
/* Board types */
@@ -135,22 +151,6 @@
#define TRANS_MD3 \
"\20\6BUFF\5UFLO\4RES\3LCOL\2LCAR\1RTRY"
-struct nic_info {
- int ident; /* Type of card */
- int ic; /* Type of ic, Am7990, Am79C960 etc. */
- int mem_mode;
- int iobase;
- int mode; /* Mode setting at initialization */
-};
-
-struct host_ring_entry {
- struct mds *md;
- union {
- struct mbuf *mbuf;
- char *data;
- }buff;
-};
-
#ifdef LNC_KEEP_STATS
#define LNCSTATS_STRUCT \
struct lnc_stats { \
@@ -186,17 +186,38 @@ struct host_ring_entry {
#define LNCSTATS(X)
#endif
+struct nic_info {
+ int ident; /* Type of card */
+ int ic; /* Type of ic, Am7990, Am79C960 etc. */
+ int mem_mode;
+ int iobase;
+ int mode; /* Mode setting at initialization */
+};
+
typedef struct lnc_softc {
- struct arpcom arpcom; /* see ../../net/if_arp.h */
- struct nic_info nic; /* NIC specific info */
+ struct resource *irqres;
+ int irqrid;
+ struct resource *drqres;
+ int drqrid;
+ struct resource *portres;
+ int portrid;
+ int iobase;
+ bus_space_tag_t lnc_btag;
+ bus_space_handle_t lnc_bhandle;
+ void *intrhand;
+ bus_dma_tag_t dmat;
+ bus_dmamap_t dmamap;
+ 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 */
+ 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;
@@ -204,12 +225,20 @@ typedef struct lnc_softc {
int rap;
int rdp;
int bdp;
-#ifdef DEBUG
+ #ifdef DEBUG
int lnc_debug;
-#endif
+ #endif
LNCSTATS_STRUCT
} lnc_softc_t;
+struct host_ring_entry {
+ struct mds *md;
+ union {
+ struct mbuf *mbuf;
+ char *data;
+ }buff;
+};
+
#define NDESC(len2) (1 << len2)
#define INC_MD_PTR(ptr, no_entries) \
@@ -223,16 +252,7 @@ typedef struct lnc_softc {
#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(lnc_softc_t *sc, u_short port, u_short val)
-{
- outw(sc->rap, port);
- outw(sc->rdp, val);
-}
-
-static __inline u_short
-read_csr(lnc_softc_t *sc, u_short port)
-{
- outw(sc->rap, port);
- return (inw(sc->rdp));
-}
+/* Functional declarations */
+extern int lnc_attach_common __P((device_t));
+extern void lnc_stop __P((struct lnc_softc *));
+extern driver_intr_t lncintr;
OpenPOWER on IntegriCloud