summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMichael Shalayeff <mickey@cvs.openbsd.org>2003-09-25 22:06:01 +0000
committerMichael Shalayeff <mickey@cvs.openbsd.org>2003-09-25 22:06:01 +0000
commit2b902e0cab4f30211e4161fe57d4ca62ee7b4289 (patch)
tree08f3ba414becd46ffea9f22f5e2543509d3b0092 /sys
parent7afdcc96dd59352c2870eca137c05b56ebc3fa91 (diff)
update fom form@ including support for 891 chips and more
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ic/mtd803.c1030
-rw-r--r--sys/dev/ic/mtd803reg.h282
-rw-r--r--sys/dev/ic/mtd803var.h136
-rw-r--r--sys/dev/ic/mtd8xx.c1103
-rw-r--r--sys/dev/ic/mtd8xxreg.h215
-rw-r--r--sys/dev/ic/mtd8xxvar.h156
-rw-r--r--sys/dev/pci/if_mtd_pci.c27
7 files changed, 1490 insertions, 1459 deletions
diff --git a/sys/dev/ic/mtd803.c b/sys/dev/ic/mtd803.c
deleted file mode 100644
index a17ef055bc4..00000000000
--- a/sys/dev/ic/mtd803.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-/* $OpenBSD: mtd803.c,v 1.2 2003/08/19 04:03:53 mickey Exp $ */
-/* $NetBSD: mtd803.c,v 1.3 2003/07/14 15:47:12 lukem Exp $ */
-
-/*-
- *
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Peter Bex <Peter.Bex@student.kun.nl>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * 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.
- */
-
-/*
- * TODO:
- * - Most importantly, get some bus_dmamap_syncs in the correct places.
- * I don't have access to a computer with PCI other than i386, and i386
- * is just such a machine where dmamap_syncs don't do anything.
- * - Powerhook for when resuming after standby.
- * - Watchdog stuff doesn't work yet, the system crashes.(lockmgr: no context)
- * - There seems to be a CardBus version of the card. (see datasheet)
- * Perhaps a detach function is necessary then? (free buffs, stop rx/tx etc)
- * - When you enable the TXBUN (Tx buffer unavailable) interrupt, it gets
- * raised every time a packet is sent. Strange, since everything works anyway
- */
-
-#include "bpfilter.h"
-
-#include <sys/param.h>
-#include <sys/mbuf.h>
-#include <sys/systm.h>
-#include <sys/device.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/syslog.h>
-
-#include <net/if.h>
-#include <net/if_media.h>
-
-#ifdef INET
-#include <netinet/in.h>
-#include <netinet/if_ether.h>
-#include <netinet/in_systm.h>
-#include <netinet/in_var.h>
-#include <netinet/ip.h>
-#endif
-
-#if NBPFILTER > 0
-#include <net/bpf.h>
-#endif
-
-#include <machine/bus.h>
-
-#include <dev/mii/mii.h>
-#include <dev/mii/miivar.h>
-#include <dev/ic/mtd803reg.h>
-#include <dev/ic/mtd803var.h>
-
-/*
- * Device driver for the MTD803 3-in-1 Fast Ethernet Controller
- * Written by Peter Bex (peter.bex@student.kun.nl)
- *
- * Datasheet at: http://www.myson.com.tw or http://www.century-semi.com
- */
-
-#define MTD_READ_1(sc, reg) \
- bus_space_read_1((sc)->bus_tag, (sc)->bus_handle, (reg))
-#define MTD_WRITE_1(sc, reg, data) \
- bus_space_write_1((sc)->bus_tag, (sc)->bus_handle, (reg), (data))
-
-#define MTD_READ_2(sc, reg) \
- bus_space_read_2((sc)->bus_tag, (sc)->bus_handle, (reg))
-#define MTD_WRITE_2(sc, reg, data) \
- bus_space_write_2((sc)->bus_tag, (sc)->bus_handle, (reg), (data))
-
-#define MTD_READ_4(sc, reg) \
- bus_space_read_4((sc)->bus_tag, (sc)->bus_handle, (reg))
-#define MTD_WRITE_4(sc, reg, data) \
- bus_space_write_4((sc)->bus_tag, (sc)->bus_handle, (reg), (data))
-
-#define MTD_SETBIT(sc, reg, x) \
- MTD_WRITE_4((sc), (reg), MTD_READ_4((sc), (reg)) | (x))
-#define MTD_CLRBIT(sc, reg, x) \
- MTD_WRITE_4((sc), (reg), MTD_READ_4((sc), (reg)) & ~(x))
-
-#define ETHER_CRC32(buf, len) (ether_crc32_be((buf), (len)))
-
-int mtd_mii_readreg __P((struct device *, int, int));
-void mtd_mii_writereg __P((struct device *, int, int, int));
-void mtd_mii_statchg __P((struct device *));
-
-void mtd_start __P((struct ifnet *));
-void mtd_stop __P((struct ifnet *, int));
-int mtd_ioctl __P((struct ifnet *, u_long, caddr_t));
-void mtd_setmulti __P((struct mtd_softc *));
-void mtd_watchdog __P((struct ifnet *));
-int mtd_mediachange __P((struct ifnet *));
-void mtd_mediastatus __P((struct ifnet *, struct ifmediareq *));
-
-int mtd_init __P((struct ifnet *));
-void mtd_reset __P((struct mtd_softc *));
-void mtd_shutdown __P((void *));
-int mtd_init_desc __P((struct mtd_softc *));
-int mtd_put __P((struct mtd_softc *, int, struct mbuf *));
-struct mbuf *mtd_get __P((struct mtd_softc *, int, int));
-
-int mtd_rxirq __P((struct mtd_softc *));
-int mtd_txirq __P((struct mtd_softc *));
-int mtd_bufirq __P((struct mtd_softc *));
-
-
-int
-mtd_config(sc)
- struct mtd_softc *sc;
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- int i;
-
- /* Read station address */
- for (i = 0; i < ETHER_ADDR_LEN; ++i)
- sc->arpcom.ac_enaddr[i] = MTD_READ_1(sc, MTD_PAR0 + i);
- printf(" address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));
-
- if (mtd_init_desc(sc))
- return (1);
-
- /* Initialize ifnet structure */
- ifp->if_softc = sc;
- ifp->if_mtu = ETHERMTU;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
- ifp->if_ioctl = mtd_ioctl;
- ifp->if_output = ether_output;
- ifp->if_start = mtd_start;
- ifp->if_watchdog = mtd_watchdog;
- ifp->if_baudrate = 10000000;
- IFQ_SET_READY(&ifp->if_snd);
- bcopy(sc->dev.dv_xname, ifp->if_xname, IFNAMSIZ);
-
- /* Setup MII interface */
- sc->mii.mii_ifp = ifp;
- sc->mii.mii_readreg = mtd_mii_readreg;
- sc->mii.mii_writereg = mtd_mii_writereg;
- sc->mii.mii_statchg = mtd_mii_statchg;
- ifmedia_init(&sc->mii.mii_media, 0, mtd_mediachange,
- mtd_mediastatus);
- mii_attach(&sc->dev, &sc->mii, 0xffffffff, MII_PHY_ANY,
- MII_OFFSET_ANY, 0);
- if (LIST_FIRST(&sc->mii.mii_phys) == NULL) {
- ifmedia_add(&sc->mii.mii_media, IFM_ETHER | IFM_NONE, 0,
- NULL);
- ifmedia_set(&sc->mii.mii_media, IFM_ETHER | IFM_NONE);
- } else
- ifmedia_set(&sc->mii.mii_media, IFM_ETHER | IFM_AUTO);
-
- /* Attach interface */
- if_attach(ifp);
- ether_ifattach(ifp);
-
- /* Add shutdown hook to reset card when we reboot */
- sc->sd_hook = shutdownhook_establish(mtd_shutdown, sc);
-
- return (0);
-}
-
-
-/*
- * mtd_init
- * Must be called at splnet()
- */
-int
-mtd_init(ifp)
- struct ifnet *ifp;
-{
- struct mtd_softc *sc = ifp->if_softc;
-
- mtd_reset(sc);
-
- /*
- * Set cache alignment and burst length. Don't really know what these
- * mean, so their values are probably suboptimal.
- */
- MTD_WRITE_4(sc, MTD_BCR, MTD_BCR_BLEN16);
-
- MTD_WRITE_4(sc, MTD_RXTXR, MTD_TX_STFWD | MTD_RX_BLEN | MTD_RX_512
- | MTD_TX_FDPLX);
-
- /* Promiscuous mode? */
- if (ifp->if_flags & IFF_PROMISC)
- MTD_SETBIT(sc, MTD_RXTXR, MTD_RX_PROM);
- else
- MTD_CLRBIT(sc, MTD_RXTXR, MTD_RX_PROM);
-
- /* Broadcast mode? */
- if (ifp->if_flags & IFF_BROADCAST)
- MTD_SETBIT(sc, MTD_RXTXR, MTD_RX_ABROAD);
- else
- MTD_CLRBIT(sc, MTD_RXTXR, MTD_RX_ABROAD);
-
- mtd_setmulti(sc);
-
- /* Enable interrupts */
- MTD_WRITE_4(sc, MTD_IMR, MTD_IMR_MASK);
- MTD_WRITE_4(sc, MTD_ISR, MTD_ISR_ENABLE);
-
- /* Set descriptor base addresses */
- MTD_WRITE_4(sc, MTD_TXLBA, htole32(sc->desc_dma_map->dm_segs[0].ds_addr
- + sizeof(struct mtd_desc) * MTD_NUM_RXD));
- MTD_WRITE_4(sc, MTD_RXLBA,
- htole32(sc->desc_dma_map->dm_segs[0].ds_addr));
-
- /* Enable receiver and transmitter */
- MTD_SETBIT(sc, MTD_RXTXR, MTD_RX_ENABLE);
- MTD_SETBIT(sc, MTD_RXTXR, MTD_TX_ENABLE);
-
- /* Interface is running */
- ifp->if_flags |= IFF_RUNNING;
- ifp->if_flags &= ~IFF_OACTIVE;
-
- return 0;
-}
-
-
-int
-mtd_init_desc(sc)
- struct mtd_softc *sc;
-{
- int rseg, err, i;
- bus_dma_segment_t seg;
- bus_size_t size;
-
- /* Allocate memory for descriptors */
- size = (MTD_NUM_RXD + MTD_NUM_TXD) * sizeof(struct mtd_desc);
-
- /* Allocate DMA-safe memory */
- if ((err = bus_dmamem_alloc(sc->dma_tag, size, MTD_DMA_ALIGN,
- 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
- printf("%s: unable to allocate DMA buffer, error = %d\n",
- sc->dev.dv_xname, err);
- return 1;
- }
-
- /* Map memory to kernel addressable space */
- if ((err = bus_dmamem_map(sc->dma_tag, &seg, 1, size,
- (caddr_t *)&sc->desc, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
- printf("%s: unable to map DMA buffer, error = %d\n",
- sc->dev.dv_xname, err);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
- return 1;
- }
-
- /* Create a DMA map */
- if ((err = bus_dmamap_create(sc->dma_tag, size, 1,
- size, 0, BUS_DMA_NOWAIT, &sc->desc_dma_map)) != 0) {
- printf("%s: unable to create DMA map, error = %d\n",
- sc->dev.dv_xname, err);
- bus_dmamem_unmap(sc->dma_tag, (caddr_t)sc->desc, size);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
- return 1;
- }
-
- /* Load the DMA map */
- if ((err = bus_dmamap_load(sc->dma_tag, sc->desc_dma_map, sc->desc,
- size, NULL, BUS_DMA_NOWAIT)) != 0) {
- printf("%s: unable to load DMA map, error = %d\n",
- sc->dev.dv_xname, err);
- bus_dmamap_destroy(sc->dma_tag, sc->desc_dma_map);
- bus_dmamem_unmap(sc->dma_tag, (caddr_t)sc->desc, size);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
- return 1;
- }
-
- /* Allocate memory for the buffers */
- size = MTD_NUM_RXD * MTD_RXBUF_SIZE + MTD_NUM_TXD * MTD_TXBUF_SIZE;
-
- /* Allocate DMA-safe memory */
- if ((err = bus_dmamem_alloc(sc->dma_tag, size, MTD_DMA_ALIGN,
- 0, &seg, 1, &rseg, BUS_DMA_NOWAIT)) != 0) {
- printf("%s: unable to allocate DMA buffer, error = %d\n",
- sc->dev.dv_xname, err);
-
- /* Undo DMA map for descriptors */
- bus_dmamap_unload(sc->dma_tag, sc->desc_dma_map);
- bus_dmamap_destroy(sc->dma_tag, sc->desc_dma_map);
- bus_dmamem_unmap(sc->dma_tag, (caddr_t)sc->desc, size);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
- return 1;
- }
-
- /* Map memory to kernel addressable space */
- if ((err = bus_dmamem_map(sc->dma_tag, &seg, 1, size,
- &sc->buf, BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) {
- printf("%s: unable to map DMA buffer, error = %d\n",
- sc->dev.dv_xname, err);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
-
- /* Undo DMA map for descriptors */
- bus_dmamap_unload(sc->dma_tag, sc->desc_dma_map);
- bus_dmamap_destroy(sc->dma_tag, sc->desc_dma_map);
- bus_dmamem_unmap(sc->dma_tag, (caddr_t)sc->desc, size);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
- return 1;
- }
-
- /* Create a DMA map */
- if ((err = bus_dmamap_create(sc->dma_tag, size, 1,
- size, 0, BUS_DMA_NOWAIT, &sc->buf_dma_map)) != 0) {
- printf("%s: unable to create DMA map, error = %d\n",
- sc->dev.dv_xname, err);
- bus_dmamem_unmap(sc->dma_tag, sc->buf, size);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
-
- /* Undo DMA map for descriptors */
- bus_dmamap_unload(sc->dma_tag, sc->desc_dma_map);
- bus_dmamap_destroy(sc->dma_tag, sc->desc_dma_map);
- bus_dmamem_unmap(sc->dma_tag, (caddr_t)sc->desc, size);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
- return 1;
- }
-
- /* Load the DMA map */
- if ((err = bus_dmamap_load(sc->dma_tag, sc->buf_dma_map, sc->buf,
- size, NULL, BUS_DMA_NOWAIT)) != 0) {
- printf("%s: unable to load DMA map, error = %d\n",
- sc->dev.dv_xname, err);
- bus_dmamap_destroy(sc->dma_tag, sc->buf_dma_map);
- bus_dmamem_unmap(sc->dma_tag, sc->buf, size);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
-
- /* Undo DMA map for descriptors */
- bus_dmamap_unload(sc->dma_tag, sc->desc_dma_map);
- bus_dmamap_destroy(sc->dma_tag, sc->desc_dma_map);
- bus_dmamem_unmap(sc->dma_tag, (caddr_t)sc->desc, size);
- bus_dmamem_free(sc->dma_tag, &seg, rseg);
- return 1;
- }
-
- /* Descriptors are stored as a circular linked list */
- /* Fill in rx descriptors */
- for (i = 0; i < MTD_NUM_RXD; ++i) {
- sc->desc[i].stat = MTD_RXD_OWNER;
- if (i == MTD_NUM_RXD - 1) { /* Last descriptor */
- /* Link back to first rx descriptor */
- sc->desc[i].next =
- htole32(sc->desc_dma_map->dm_segs[0].ds_addr);
- } else {
- /* Link forward to next rx descriptor */
- sc->desc[i].next =
- htole32(sc->desc_dma_map->dm_segs[0].ds_addr
- + (i + 1) * sizeof(struct mtd_desc));
- }
- sc->desc[i].conf = MTD_RXBUF_SIZE & MTD_RXD_CONF_BUFS;
- /* Set buffer's address */
- sc->desc[i].data = htole32(sc->buf_dma_map->dm_segs[0].ds_addr
- + i * MTD_RXBUF_SIZE);
- }
-
- /* Fill in tx descriptors */
- for (/* i = MTD_NUM_RXD */; i < (MTD_NUM_TXD + MTD_NUM_RXD); ++i) {
- sc->desc[i].stat = 0; /* At least, NOT MTD_TXD_OWNER! */
- if (i == (MTD_NUM_RXD + MTD_NUM_TXD - 1)) { /* Last descr */
- /* Link back to first tx descriptor */
- sc->desc[i].next =
- htole32(sc->desc_dma_map->dm_segs[0].ds_addr
- +MTD_NUM_RXD * sizeof(struct mtd_desc));
- } else {
- /* Link forward to next tx descriptor */
- sc->desc[i].next =
- htole32(sc->desc_dma_map->dm_segs[0].ds_addr
- + (i + 1) * sizeof(struct mtd_desc));
- }
- /* sc->desc[i].conf = MTD_TXBUF_SIZE & MTD_TXD_CONF_BUFS; */
- /* Set buffer's address */
- sc->desc[i].data = htole32(sc->buf_dma_map->dm_segs[0].ds_addr
- + MTD_NUM_RXD * MTD_RXBUF_SIZE
- + (i - MTD_NUM_RXD) * MTD_TXBUF_SIZE);
- }
-
- return 0;
-}
-
-
-void
-mtd_mii_statchg(self)
- struct device *self;
-{
- /*struct mtd_softc *sc = (void *)self;*/
-
- /* Should we do something here? :) */
-}
-
-
-int
-mtd_mii_readreg(self, phy, reg)
- struct device *self;
- int phy, reg;
-{
- struct mtd_softc *sc = (void *)self;
-
- /* XXX */
- if (phy != 0)
- return (0);
-
- return (MTD_READ_2(sc, MTD_PHYBASE + reg * 2));
-}
-
-
-void
-mtd_mii_writereg(self, phy, reg, val)
- struct device *self;
- int phy, reg, val;
-{
- struct mtd_softc *sc = (void *)self;
-
- MTD_WRITE_2(sc, MTD_PHYBASE + reg * 2, val);
-}
-
-
-int
-mtd_put(sc, index, m)
- struct mtd_softc *sc;
- int index;
- struct mbuf *m;
-{
- int len, tlen;
- caddr_t buf = sc->buf + MTD_NUM_RXD * MTD_RXBUF_SIZE
- + index * MTD_TXBUF_SIZE;
- struct mbuf *n;
-
- for (tlen = 0; m != NULL; m = n) {
- len = m->m_len;
- if (len == 0) {
- MFREE(m, n);
- continue;
- } else if (tlen > MTD_TXBUF_SIZE) {
- /* XXX FIXME: No idea what to do here. */
- printf("%s: packet too large!\n",
- sc->dev.dv_xname);
- MFREE(m, n);
- continue;
- }
- memcpy(buf, mtod(m, caddr_t), len);
- buf += len;
- tlen += len;
- MFREE(m, n);
- }
- sc->desc[MTD_NUM_RXD + index].conf = MTD_TXD_CONF_PAD | MTD_TXD_CONF_CRC
- | MTD_TXD_CONF_IRQC
- | ((tlen << MTD_TXD_PKTS_SHIFT) & MTD_TXD_CONF_PKTS)
- | (tlen & MTD_TXD_CONF_BUFS);
-
- return tlen;
-}
-
-
-void
-mtd_start(ifp)
- struct ifnet *ifp;
-{
- struct mtd_softc *sc = ifp->if_softc;
- struct mbuf *m;
- int len;
- int first_tx = sc->cur_tx;
-
- for (;;) {
- IFQ_DEQUEUE(&ifp->if_snd, m);
-
- if (m == NULL)
- break;
-
-#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m);
-#endif
-
- /* Copy mbuf chain into tx buffer */
- len = mtd_put(sc, sc->cur_tx, m);
-
- if (sc->cur_tx != first_tx)
- sc->desc[MTD_NUM_RXD + sc->cur_tx].stat = MTD_TXD_OWNER;
-
- if (++sc->cur_tx >= MTD_NUM_TXD)
- sc->cur_tx = 0;
- }
- /* Mark first & last descriptor */
- sc->desc[MTD_NUM_RXD + first_tx].conf |= MTD_TXD_CONF_FSD;
-
- if (sc->cur_tx == 0) {
- sc->desc[MTD_NUM_RXD + MTD_NUM_TXD - 1].conf |=MTD_TXD_CONF_LSD;
- } else {
- sc->desc[MTD_NUM_RXD + sc->cur_tx - 1].conf |= MTD_TXD_CONF_LSD;
- }
-
- /* Give first descriptor to chip to complete transaction */
- sc->desc[MTD_NUM_RXD + first_tx].stat = MTD_TXD_OWNER;
-
- /* Transmit polling demand */
- MTD_WRITE_4(sc, MTD_TXPDR, MTD_TXPDR_DEMAND);
-
- /* XXX FIXME: Set up a watchdog timer */
- /* ifp->if_timer = 5; */
-}
-
-
-void
-mtd_stop (ifp, disable)
- struct ifnet *ifp;
- int disable;
-{
- struct mtd_softc *sc = ifp->if_softc;
-
- /* Disable transmitter and receiver */
- MTD_CLRBIT(sc, MTD_RXTXR, MTD_TX_ENABLE);
- MTD_CLRBIT(sc, MTD_RXTXR, MTD_RX_ENABLE);
-
- /* Disable interrupts */
- MTD_WRITE_4(sc, MTD_IMR, 0x00000000);
-
- /* Must do more at disable??... */
- if (disable) {
- /* Delete tx and rx descriptor base adresses */
- MTD_WRITE_4(sc, MTD_RXLBA, 0x00000000);
- MTD_WRITE_4(sc, MTD_TXLBA, 0x00000000);
- }
-
- ifp->if_timer = 0;
- ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
-}
-
-
-void
-mtd_watchdog(ifp)
- struct ifnet *ifp;
-{
- struct mtd_softc *sc = ifp->if_softc;
- int s;
-
- log(LOG_ERR, "%s: device timeout\n", sc->dev.dv_xname);
- ++sc->arpcom.ac_if.if_oerrors;
-
- mtd_stop(ifp, 0);
-
- s = splnet();
- mtd_init(ifp);
- splx(s);
-
- return;
-}
-
-
-int
-mtd_ioctl(ifp, cmd, data)
- struct ifnet * ifp;
- u_long cmd;
- caddr_t data;
-{
- struct mtd_softc *sc = ifp->if_softc;
- struct ifreq *ifr = (struct ifreq *)data;
- struct ifaddr *ifa = (struct ifaddr *)data;
- int s, error = 0;
-
- s = splimp();
- if ((error = ether_ioctl(ifp, &sc->arpcom, cmd, data)) > 0) {
- splx(s);
- return (error);
- }
-
- /* Don't do anything special */
- switch(cmd) {
- case SIOCSIFADDR:
- ifp->if_flags |= IFF_UP;
- switch (ifa->ifa_addr->sa_family) {
-#ifdef INET
- case AF_INET:
- mtd_init(ifp);
- arp_ifinit(&sc->arpcom, ifa);
- break;
-#endif /* INET */
- default:
- mtd_init(ifp);
- break;
- }
- break;
- case SIOCSIFMTU:
- if (ifr->ifr_mtu > ETHERMTU || ifr->ifr_mtu < ETHERMIN) {
- error = EINVAL;
- } else if (ifp->if_mtu != ifr->ifr_mtu) {
- ifp->if_mtu = ifr->ifr_mtu;
- }
- break;
- case SIOCSIFFLAGS:
- if (ifp->if_flags & IFF_UP)
- mtd_init(ifp);
- else
- if (ifp->if_flags & IFF_RUNNING)
- /* mtd_stop(ifp) */;
- error = 0;
- break;
- case SIOCADDMULTI:
- case SIOCDELMULTI:
- error = (cmd == SIOCADDMULTI) ?
- ether_addmulti(ifr, &sc->arpcom) :
- ether_delmulti(ifr, &sc->arpcom);
-
- if (error == ENETRESET) {
- /*
- * Multicast list has changed; set the hardware
- * filter accordingly.
- */
- mtd_setmulti(sc);
- error = 0;
- }
- break;
- case SIOCGIFMEDIA:
- case SIOCSIFMEDIA:
- error = ifmedia_ioctl(ifp, ifr, &sc->mii.mii_media, cmd);
- break;
- default:
- error = EINVAL;
- break;
- }
-
- splx(s);
- return error;
-}
-
-
-struct mbuf *
-mtd_get(sc, index, totlen)
- struct mtd_softc *sc;
- int index;
- int totlen;
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- struct mbuf *m, *m0, *newm;
- int len;
- caddr_t buf = sc->buf + index * MTD_RXBUF_SIZE;
-
- MGETHDR(m0, M_DONTWAIT, MT_DATA);
- if (m0 == NULL)
- return NULL;
-
- m0->m_pkthdr.rcvif = ifp;
- m0->m_pkthdr.len = totlen;
- m = m0;
- len = MHLEN;
-
- while (totlen > 0) {
- if (totlen >= MINCLSIZE) {
- MCLGET(m, M_DONTWAIT);
- if (!(m->m_flags & M_EXT)) {
- m_freem(m0);
- return NULL;
- }
- len = MCLBYTES;
- }
-
- if (m == m0) {
- caddr_t newdata = (caddr_t)
- ALIGN(m->m_data + sizeof(struct ether_header)) -
- sizeof(struct ether_header);
- len -= newdata - m->m_data;
- m->m_data = newdata;
- }
-
- m->m_len = len = min(totlen, len);
- memcpy(mtod(m, caddr_t), buf, len);
- buf += len;
-
- totlen -= len;
- if (totlen > 0) {
- MGET(newm, M_DONTWAIT, MT_DATA);
- if (newm == NULL) {
- m_freem(m0);
- return NULL;
- }
- len = MLEN;
- m = m->m_next = newm;
- }
- }
-
- return m0;
-}
-
-
-int
-mtd_rxirq(sc)
- struct mtd_softc *sc;
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- int len;
- struct mbuf *m;
-
- for (; !(sc->desc[sc->cur_rx].stat & MTD_RXD_OWNER);) {
- /* Error summary set? */
- if (sc->desc[sc->cur_rx].stat & MTD_RXD_ERRSUM) {
- printf("%s: received packet with errors\n",
- sc->dev.dv_xname);
- /* Give up packet, since an error occurred */
- sc->desc[sc->cur_rx].stat = MTD_RXD_OWNER;
- sc->desc[sc->cur_rx].conf = MTD_RXBUF_SIZE &
- MTD_RXD_CONF_BUFS;
- ++ifp->if_ierrors;
- if (++sc->cur_rx >= MTD_NUM_RXD)
- sc->cur_rx = 0;
- continue;
- }
- /* Get buffer length */
- len = (sc->desc[sc->cur_rx].stat & MTD_RXD_FLEN)
- >> MTD_RXD_FLEN_SHIFT;
- len -= ETHER_CRC_LEN;
-
- /* Check packet size */
- if (len <= sizeof(struct ether_header)) {
- printf("%s: invalid packet size %d; dropping\n",
- sc->dev.dv_xname, len);
- sc->desc[sc->cur_rx].stat = MTD_RXD_OWNER;
- sc->desc[sc->cur_rx].conf = MTD_RXBUF_SIZE &
- MTD_RXD_CONF_BUFS;
- ++ifp->if_ierrors;
- if (++sc->cur_rx >= MTD_NUM_RXD)
- sc->cur_rx = 0;
- continue;
- }
-
- m = mtd_get(sc, (sc->cur_rx), len);
-
- /* Give descriptor back to card */
- sc->desc[sc->cur_rx].conf = MTD_RXBUF_SIZE & MTD_RXD_CONF_BUFS;
- sc->desc[sc->cur_rx].stat = MTD_RXD_OWNER;
-
- if (++sc->cur_rx >= MTD_NUM_RXD)
- sc->cur_rx = 0;
-
- if (m == NULL) {
- printf("%s: error pulling packet off interface\n",
- sc->dev.dv_xname);
- ++ifp->if_ierrors;
- continue;
- }
-
- ++ifp->if_ipackets;
-
-#if NBPFILTER > 0
- if (ifp->if_bpf)
- bpf_mtap(ifp->if_bpf, m);
-#endif
- /* Pass the packet up */
- ether_input_mbuf(ifp, m);
- }
-
- return 1;
-}
-
-
-int
-mtd_txirq(sc)
- struct mtd_softc *sc;
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
-
- /* Clear timeout */
- ifp->if_timer = 0;
-
- ifp->if_flags &= ~IFF_OACTIVE;
- ++ifp->if_opackets;
-
- /* XXX FIXME If there is some queued, do an mtd_start? */
-
- return 1;
-}
-
-
-int
-mtd_bufirq(sc)
- struct mtd_softc *sc;
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
-
- /* Clear timeout */
- ifp->if_timer = 0;
-
- /* XXX FIXME: Do something here to make sure we get some buffers! */
-
- return 1;
-}
-
-
-int
-mtd_irq_h(args)
- void *args;
-{
- struct mtd_softc *sc = args;
- struct ifnet *ifp = &sc->arpcom.ac_if;
- u_int32_t status;
- int r = 0;
-
- if (!(ifp->if_flags & IFF_RUNNING) ||
- !(sc->dev.dv_flags & DVF_ACTIVE))
- return 0;
-
- /* Disable interrupts */
- MTD_WRITE_4(sc, MTD_IMR, 0x00000000);
-
- for(;;) {
- status = MTD_READ_4(sc, MTD_ISR);
- if (!status) /* We didn't ask for this */
- break;
-
- MTD_WRITE_4(sc, MTD_ISR, status);
-
- /* NOTE: Perhaps we should reset with some of these errors? */
-
- if (status & MTD_ISR_RXBUN) {
-#ifdef MTD_DEBUG
- printf("%s: receive buffer unavailable\n",
- sc->dev.dv_xname);
-#endif
- ++ifp->if_ierrors;
- }
-
- if (status & MTD_ISR_RXERR) {
-#ifdef MTD_DEBUG
- printf("%s: receive error\n", sc->dev.dv_xname);
-#endif
- ++ifp->if_ierrors;
- }
-
- if (status & MTD_ISR_TXBUN) {
-#ifdef MTD_DEBUG
- printf("%s: transmit buffer unavailable\n",
- sc->dev.dv_xname);
-#endif
- ++ifp->if_ierrors;
- }
-
- if ((status & MTD_ISR_PDF)) {
-#ifdef MTD_DEBUG
- printf("%s: parallel detection fault\n",
- sc->dev.dv_xname);
-#endif
- ++ifp->if_ierrors;
- }
-
- if (status & MTD_ISR_FBUSERR) {
-#ifdef MTD_DEBUG
- printf("%s: fatal bus error\n", sc->dev.dv_xname);
-#endif
- ++ifp->if_ierrors;
- }
-
- if (status & MTD_ISR_TARERR) {
-#ifdef MTD_DEBUG
- printf("%s: target error\n", sc->dev.dv_xname);
-#endif
- ++ifp->if_ierrors;
- }
-
- if (status & MTD_ISR_MASTERR) {
-#ifdef MTD_DEBUG
- printf("%s: master error\n", sc->dev.dv_xname);
-#endif
- ++ifp->if_ierrors;
- }
-
- if (status & MTD_ISR_PARERR) {
-#ifdef MTD_DEBUG
- printf("%s: parity error\n", sc->dev.dv_xname);
-#endif
- ++ifp->if_ierrors;
- }
-
- if (status & MTD_ISR_RXIRQ) /* Receive interrupt */
- r |= mtd_rxirq(sc);
-
- if (status & MTD_ISR_TXIRQ) /* Transmit interrupt */
- r |= mtd_txirq(sc);
-
- if (status & MTD_ISR_TXEARLY) /* Transmit early */
- r |= mtd_txirq(sc);
-
- if (status & MTD_ISR_TXBUN) /* Transmit buffer n/a */
- r |= mtd_bufirq(sc);
-
- }
-
- /* Enable interrupts */
- MTD_WRITE_4(sc, MTD_IMR, MTD_IMR_MASK);
-
- return r;
-}
-
-
-void
-mtd_setmulti(sc)
- struct mtd_softc *sc;
-{
- struct ifnet *ifp = &sc->arpcom.ac_if;
- u_int32_t rxtx_stat;
- u_int32_t hash[2] = {0, 0};
- u_int32_t crc;
- struct ether_multi *enm;
- struct ether_multistep step;
- int mcnt = 0;
-
- /* Get old status */
- rxtx_stat = MTD_READ_4(sc, MTD_RXTXR);
-
- if ((ifp->if_flags & IFF_ALLMULTI) || (ifp->if_flags & IFF_PROMISC)) {
- rxtx_stat |= MTD_RX_AMULTI;
- MTD_WRITE_4(sc, MTD_RXTXR, rxtx_stat);
- MTD_WRITE_4(sc, MTD_MAR0, MTD_ALL_ADDR);
- MTD_WRITE_4(sc, MTD_MAR1, MTD_ALL_ADDR);
- return;
- }
-
- ETHER_FIRST_MULTI(step, &sc->arpcom, enm);
- while (enm != NULL) {
- /* We need the 6 most significant bits of the CRC */
- crc = ETHER_CRC32(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
-
- hash[crc >> 5] |= 1 << (crc & 0xf);
-
- ++mcnt;
- ETHER_NEXT_MULTI(step, enm);
- }
-
- /* Accept multicast bit needs to be on? */
- if (mcnt)
- rxtx_stat |= MTD_RX_AMULTI;
- else
- rxtx_stat &= ~MTD_RX_AMULTI;
-
- /* Write out the hash */
- MTD_WRITE_4(sc, MTD_MAR0, hash[0]);
- MTD_WRITE_4(sc, MTD_MAR1, hash[1]);
- MTD_WRITE_4(sc, MTD_RXTXR, rxtx_stat);
-}
-
-
-void
-mtd_reset(sc)
- struct mtd_softc *sc;
-{
- int i;
-
- MTD_SETBIT(sc, MTD_BCR, MTD_BCR_RESET);
-
- /* Reset descriptor status */
- sc->cur_tx = 0;
- sc->cur_rx = 0;
-
- /* Wait until done with reset */
- for (i = 0; i < MTD_TIMEOUT; ++i) {
- DELAY(10);
- if (!(MTD_READ_4(sc, MTD_BCR) & MTD_BCR_RESET))
- break;
- }
-
- if (i == MTD_TIMEOUT) {
- printf("%s: reset timed out\n", sc->dev.dv_xname);
- }
-
- /* Wait a little so chip can stabilize */
- DELAY(1000);
-}
-
-
-int
-mtd_mediachange(ifp)
- struct ifnet *ifp;
-{
- struct mtd_softc *sc = ifp->if_softc;
-
- return (mii_mediachg(&sc->mii));
-}
-
-
-void
-mtd_mediastatus(ifp, ifmr)
- struct ifnet *ifp;
- struct ifmediareq *ifmr;
-{
- struct mtd_softc *sc = ifp->if_softc;
-
- mii_pollstat(&sc->mii);
- ifmr->ifm_active = sc->mii.mii_media_active;
- ifmr->ifm_status = sc->mii.mii_media_status;
-}
-
-
-void
-mtd_shutdown (arg)
- void *arg;
-{
- struct mtd_softc *sc = arg;
- struct ifnet *ifp = &sc->arpcom.ac_if;
-
- mtd_stop(ifp, 1);
-}
-
-struct cfdriver mtd_cd = {
- 0, "mtd", DV_IFNET
-};
diff --git a/sys/dev/ic/mtd803reg.h b/sys/dev/ic/mtd803reg.h
deleted file mode 100644
index 9824e1c8682..00000000000
--- a/sys/dev/ic/mtd803reg.h
+++ /dev/null
@@ -1,282 +0,0 @@
-/* $OpenBSD: mtd803reg.h,v 1.2 2003/08/19 04:03:53 mickey Exp $ */
-/* $NetBSD: mtd803reg.h,v 1.1 2002/11/07 21:56:59 martin Exp $ */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Peter Bex <Peter.Bex@student.kun.nl>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * 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.
- */
-#ifndef __DEV_IC_MTD803REG_H__
-#define __DEV_IC_MTD803REG_H__
-
-#define MTD_PCI_LOIO 0x10
-#define MTD_PCI_LOMEM 0x14
-
-/* Command and Status Register */
-#define MTD_PAR0 0x00 /* Physical address 0-3 */
-#define MTD_PAR1 0x04 /* Physical address 4-5 */
-#define MTD_MAR0 0x08 /* Multicast address 0-3 */
-#define MTD_MAR1 0x0c /* Multicast address 4-7 */
-#define MTD_FAR0 0x10 /* Flowctrl address 0-3 */
-#define MTD_FAR1 0x14 /* Flowctrl address 4-5 */
-#define MTD_RXTXR 0x18 /* Receive-transmit config */
-#define MTD_BCR 0x1c /* Bus command */
-#define MTD_TXPDR 0x20 /* Transmit polling demand */
-#define MTD_RXPDR 0x24 /* Receive polling demand */
-#define MTD_RCWP 0x28 /* Receive word pointer */
-#define MTD_TXLBA 0x2c /* Transmit list base addr */
-#define MTD_RXLBA 0x30 /* Receive list base addr */
-#define MTD_ISR 0x34 /* Interrupt Status Register */
-#define MTD_IMR 0x38 /* Interrupt Mask Register */
-#define MTD_FHLT 0x3c /* Flow ctrl high/low thresh */
-#define MTD_MIIMGT 0x40 /* ROM and MII management */
-#define MTD_TALLY 0x44 /* Tally ctr for CRC & MPA */
-#define MTD_TSR 0x48 /* Tally ctr for TSR */
-#define MTD_PHYBASE 0x4c /* PHY status & control */
-#define MTD_OUI 0x50 /* OUI register */
-#define MTD_LPAR 0x54 /* Link Partner, Advertisment */
-#define MTD_WUECSR 0x5c /* Wake-up Events CSR */
-
-#define MTD_ALL_ADDR 0xffffffff /* Mask all addresses */
-#define MTD_TXPDR_DEMAND 0xffffffff /* Demand transmit polling */
-#define MTD_RXPDR_DEMAND 0xffffffff /* Demand receive polling */
-
-/* PHY registers */
-/* Basic mode control register */
-#define MTD_PHY_BMCR 0x00
-
-/* Bus Command Register */
-#define MTD_BCR_RSRVD1 0xfffffc00 /* Bits [31:10] are reserved */
-#define MTD_BCR_PROG 0x00000200 /* Programming */
-#define MTD_BCR_RLE 0x00000100 /* Read Line command Enable */
-#define MTD_BCR_RME 0x00000080 /* Read Multiple cmd Enable */
-#define MTD_BCR_WIE 0x00000040 /* Write and Inval. cmd Enab. */
-#define MTD_BCR_BLEN1 0x00000000 /* 1 dword burst length */
-#define MTD_BCR_BLEN4 0x00000008 /* 4 dwords burst length */
-#define MTD_BCR_BLEN8 0x00000010 /* 8 dwords burst length */
-#define MTD_BCR_BLEN16 0x00000018 /* 16 dwords burst length */
-#define MTD_BCR_BLEN32 0x00000020 /* 32 dwords burst length */
-#define MTD_BCR_BLEN64 0x00000028 /* 64 dwords burst length */
-#define MTD_BCR_BLEN128 0x00000030 /* 128 dwords burst length */
-#define MTD_BCR_BLEN512 0x00000038 /* 512 dwords burst length */
-#define MTD_BCR_RSVRD0 0x00000006 /* Bits [2:1] are reserved */
-#define MTD_BCR_RESET 0x00000001 /* Software reset */
-
-#define MTD_TIMEOUT 1000 /* Timeout when resetting */
-
-/* Transmit configuration register */
-#define MTD_TX_RUN 0x80000000 /* Transmit running status */
-#define MTD_TX_RSRVD1 0x60000000 /* Bits [14:13] are reserved */
-#define MTD_TX_BACKOPT 0x10000000 /* Optional backoff */
-#define MTD_TX_FASTBACK 0x08000000 /* Fast back-off */
-#define MTD_TX_RSRVD0 0x04000000 /* Bit 10 is reserved */
-#define MTD_TX_ENH 0x02000000 /* Enhanced mode */
-#define MTD_TX_FCTL 0x01000000 /* Transmit fctl packet enable*/
-#define MTD_TX_64 0x00000000 /* 64 bytes */
-#define MTD_TX_32 0x00200000 /* 32 bytes */
-#define MTD_TX_128 0x00400000 /* 128 bytes */
-#define MTD_TX_256 0x00600000 /* 256 bytes */
-#define MTD_TX_512 0x00800000 /* 512 bytes */
-#define MTD_TX_768 0x00a00000 /* 768 bytes */
-#define MTD_TX_1024 0x00c00000 /* 1024 bytes */
-#define MTD_TX_STFWD 0x00e00000 /* Store and forward */
-#define MTD_TX_FDPLX 0x00100000 /* Full duplex mode */
-#define MTD_TX_SPD10 0x00080000 /* Port speed is 10M */
-#define MTD_TX_ENABLE 0x00040000 /* Transmit enable */
-#define MTD_TX_LPBACK 0x00020000 /* Loopback mode bit 1 */
-#define MTD_TX_LPBACKZERO 0x00010000 /* Loopback mode bit 0 */
-
-/* Receive configuration register */
-#define MTD_RX_RUN 0x00008000 /* Receive running status */
-#define MTD_RX_EARLY 0x00004000 /* Early interrupt enable */
-#define MTD_RX_FCTL 0x00002000 /* Receive fctl packet enable */
-#define MTD_RX_FANA 0x00001000 /* Fctl address undefined(n/a)*/
-#define MTD_RX_BLEN 0x00000800 /* Receive burst len enable */
-#define MTD_RX_512 0x00000700 /* 512 words */
-#define MTD_RX_128 0x00000600 /* 128 words */
-#define MTD_RX_64 0x00000500 /* 64 words */
-#define MTD_RX_32 0x00000400 /* 32 words */
-#define MTD_RX_16 0x00000300 /* 16 words */
-#define MTD_RX_8 0x00000200 /* 8 words */
-#define MTD_RX_4 0x00000100 /* 4 words */
-#define MTD_RX_1 0x00000000 /* 1 word */
-#define MTD_RX_PROM 0x00000080 /* Promiscuous mode */
-#define MTD_RX_ABROAD 0x00000040 /* Accept broadcast */
-#define MTD_RX_AMULTI 0x00000020 /* Accept multicast */
-#define MTD_RX_ARP 0x00000008 /* Receive runt packet */
-#define MTD_RX_ALP 0x00000004 /* Receive long packet */
-#define MTD_RX_ERRP 0x00000002 /* Receive error packet */
-#define MTD_RX_ENABLE 0x00000001 /* Receive enable */
-
-/* Interrupt Status Register */
-#define MTD_ISR_RSRVD1 0xfff80000 /* Bits [31:19] are reserved */
-#define MTD_ISR_PDF 0x00040000 /* Parallel Detection Fault */
-#define MTD_ISR_RFCON 0x00020000 /* Receive FCtl xON packet */
-#define MRD_ISR_RFCOFF 0x00010000 /* Receive FCtl xOFF packet */
-#define MTD_ISR_LSC 0x00008000 /* Link Status Change */
-#define MTD_ISR_ANC 0x00004000 /* Autonegotiation complete */
-#define MTD_ISR_FBUSERR 0x00002000 /* Fatal bus error */
-#define MTD_ISR_PARERR 0x00000000 /* Parity error */
-#define MTD_ISR_MASTERR 0x00000800 /* Master error */
-#define MTD_ISR_TARERR 0x00001000 /* Target error */
-#define MTD_ISR_TXUNDER 0x00000400 /* Transmit underflow */
-#define MTD_ISR_RXOVER 0x00000200 /* Receive overflow */
-#define MTD_ISR_TXEARLY 0x00000100 /* Transmit early int */
-#define MTD_ISR_RXEARLY 0x00000080 /* Receive early int */
-#define MTD_ISR_CTROVER 0x00000040 /* Counter overflow */
-#define MTD_ISR_RXBUN 0x00000020 /* Receive buffer n/a */
-#define MTD_ISR_TXBUN 0x00000010 /* Transmit buffer n/a */
-#define MTD_ISR_TXIRQ 0x00000008 /* Transmit interrupt */
-#define MTD_ISR_RXIRQ 0x00000004 /* Receive interrupt */
-#define MTD_ISR_RXERR 0x00000002 /* Receive error */
-#define MTD_ISR_RSRVD0 0x00000001 /* Bit 1 is reserved */
-
-#define MTD_ISR_MASK MTD_ISR_TXIRQ | MTD_ISR_RXIRQ | MTD_ISR_RXBUN \
- | MTD_ISR_RXERR | MTD_ISR_PDF \
- | MTD_ISR_FBUSERR | MTD_ISR_TXUNDER \
- | MTD_ISR_RXOVER | MTD_ISR_PARERR \
- | MTD_ISR_MASTERR | MTD_ISR_TARERR
-
-#define MTD_ISR_ENABLE 0xffffffff /* Enable interrupts */
-
-/* Interrupt Mask Register. Essentially the same as ISR */
-#define MTD_IMR_RSRVD2 0xfff80000 /* Bits [31:19] are reserved */
-#define MTD_IMR_PDF 0x00040000 /* Parallel Detection Fault */
-#define MTD_IMR_RFCON 0x00020000 /* Receive FCtl xON packet */
-#define MRD_IMR_RFCOFF 0x00010000 /* Receive FCtl xOFF packet */
-#define MTD_IMR_LSC 0x00008000 /* Link Status Change */
-#define MTD_IMR_ANC 0x00004000 /* Autonegotiation complete */
-#define MTD_IMR_FBUSERR 0x00002000 /* Fatal bus error */
-#define MTD_IMR_RSRVD1 0x00001800 /* Bits [12:11] are reserved */
-#define MTD_IMR_TXUNDER 0x00000400 /* Transmit underflow */
-#define MTD_IMR_RXOVER 0x00000200 /* Receive overflow */
-#define MTD_IMR_TXEARLY 0x00000100 /* Transmit early int */
-#define MTD_IMR_RXEARLY 0x00000080 /* Receive early int */
-#define MTD_IMR_CTROVER 0x00000040 /* Counter overflow */
-#define MTD_IMR_RXBUN 0x00000020 /* Receive buffer n/a */
-#define MTD_IMR_TXBUN 0x00000010 /* Transmit buffer n/a */
-#define MTD_IMR_TXIRQ 0x00000008 /* Transmit interrupt */
-#define MTD_IMR_RXIRQ 0x00000004 /* Receive interrupt */
-#define MTD_IMR_RXERR 0x00000002 /* Receive error */
-#define MTD_IMR_RSRVD0 0x00000001 /* Bit 1 is reserved */
-
-#define MTD_IMR_MASK MTD_IMR_TXIRQ | MTD_IMR_RXIRQ | MTD_IMR_RXBUN \
- | MTD_IMR_RXERR | MTD_IMR_PDF \
- | MTD_IMR_FBUSERR | MTD_IMR_TXUNDER \
- | MTD_IMR_RXOVER \
-
-/* Tally counters for CRC and MPA */
-#define MTD_TALLY_CRCOVER 0x80000000 /* CRC tally ctr overflow */
-#define MTD_TALLY_NCRCERR 0x7fff0000 /* Number of CRC errors */
-#define MTD_TALLY_MPAOVER 0x00008000 /* MPA tally ctr overflow */
-#define MTD_TALLY_NMPAERR 0x00007fff /* Number of MPA errors */
-
-/* Tally counters for Transmit Status Report */
-#define MTD_TSR_NABORT 0xff000000 /* Number of aborted packets */
-#define MTD_TSR_NLCOL 0x00ff0000 /* Number of late collisions */
-#define MTD_TSR_NRETRY 0x0000ffff /* Number of transm. retries */
-
-/* Wake-Up Events Control and Status Register */
-#define MTD_WUECSR_RSRVD1 0xfffff000 /* Bits [31:12] are reserved */
-#define MTD_WUECSR_FRCWKUP 0x00000800 /* Force Wake Up LAN mode */
-#define MTD_WUECSR_STATCHG 0x00000400 /* Status Change enable */
-#define MTD_WUECSR_AGU 0x00000200 /* Accept Global Unicast */
-#define MTD_WUECSR_WUPOP 0x00000100 /* Wake Up Pin Output Pattern */
-#define MTD_WUECSR_WUPPROP 0x00000080 /* Wake Up Pin Property */
-#define MTD_WUECSR_LCD 0x00000040 /* Link Change Detected */
-#define MTD_WUECSR_MPR 0x00000020 /* Magic Packet Received */
-#define MTD_WUECSR_WUFR 0x00000010 /* Wake Up Frame Received */
-#define MTD_WUECSR_RSRVD0 0x00000008 /* Unspecified! */
-#define MTD_WUECSR_LCE 0x00000004 /* Link Change Enable */
-#define MTD_WUECSR_MPE 0x00000002 /* Magic Packet Enable */
-#define MTD_WUECSR_WUFE 0x00000001 /* Wake Up Frame Enable */
-
-
-/*
- * Note: We should probably move the following info to a new PHY driver.
- * Or maybe remove them anyway, but we might need them someday so leave them
- * here for now.
- */
-/* PHY Control and Status Register */
-#define MTD_PHY_T4 0x80000000 /* T4 operation capability */
-#define MTD_PHY_TXFD 0x40000000 /* 100-TX Full Duplex cap. */
-#define MTD_PHY_TXHD 0x20000000 /* 100-TX Half Duplex cap. */
-#define MTD_PHY_TPFD 0x10000000 /* 10-TP Full Duplex cap. */
-#define MTD_PHY_TPHD 0x08000000 /* 10-TP Half Duplex cap. */
-#define MTD_PHY_RSRVD2 0x07c00000 /* Bits [16:22] are reserved */
-#define MTD_PHY_ANC 0x00200000 /* Autonegotiation complete */
-#define MTD_PHY_RMTFAULT 0x00100000 /* Remote fault */
-#define MTD_PHY_AUTONEG 0x00080000 /* Autonegotiation */
-#define MTD_PHY_LINK 0x00040000 /* Link status */
-#define MTD_PHY_JABBER 0x00020000 /* Jabber detected */
-#define MTD_PHY_EXTREG 0x00010000 /* Extended register exists */
-#define MTD_PHY_RESET 0x00008000 /* Reset PHY registers */
-#define MTD_PHY_LPBACK 0x00004000 /* Loopback select */
-#define MTD_PHY_SPEED 0x00002000 /* Speed select */
-#define MTD_PHY_ANEN 0x00001000 /* Autoneg enable */
-#define MTD_PHY_POWDWN 0x00000800 /* Power-down */
-#define MTD_PHY_RSRVD1 0x00000400 /* Bit 10 is reserved */
-#define MTD_PHY_RESTAN 0x00000200 /* Restart Autoneg */
-#define MTD_PHY_DUPLEX 0x00000100 /* Duplex select */
-#define MTD_PHY_COLTST 0x00000080 /* Collision test enable */
-#define MTD_PHY_RSRVD0 0x0000007f /* Bits [6:0] are reserved */
-
-/* OUI register */
-#define MTD_OUI_HIGH 0xfc000000 /* OUI High register (0x34) */
-#define MTD_OUI_PARTNO 0x02f00000 /* Part number (0x0) */
-#define MTD_OUI_REVISION 0x000f0000 /* Revision number (0x0) */
-#define MTD_OUI_LOW 0x0000ffff /* OUI Low register (0x0302) */
-
-/* Link Partner Ability Register and Advertisment Register */
-#define MTD_LPAR_LP_NEXTPAGE 0x80000000 /* Next page */
-#define MTD_LPAR_LP_ACK 0x40000000 /* Acknowledge */
-#define MTD_LPAR_LP_RMTFAULT 0x20000000 /* Remote fault detected */
-#define MTD_LPAR_RSRVD1 0x1c000000 /* Bits [28:26] are reserved */
-#define MTD_LPAR_LP_T4 0x02000000 /* Capable of T4 operation */
-#define MTD_LPAR_LP_TXFD 0x01000000 /* Cap. of 100-TX Full Duplex */
-#define MTD_LPAR_LP_TXHD 0x00800000 /* Cap. of 100-TX Half Duplex */
-#define MTD_LPAR_LP_TPFD 0x00400000 /* Cap. of 10-TP Full Duplex */
-#define MTD_LPAR_LP_TPHD 0x00200000 /* Cap. of 10-TP Half Duplex */
-#define MTD_LPAR_SELECTOR1 0x001f0000 /* Selector field 1 */
-#define MTD_LPAR_AD_NEXTPAGE 0x00008000 /* Next page */
-#define MTD_LPAR_AD_ACK 0x00004000 /* Acknowledge */
-#define MTD_LPAR_AD_RMTFAULT 0x00002000 /* Remote fault detected */
-#define MTD_LPAR_RSRVD0 0x00001c00 /* Bits [12:10] are reserved */
-#define MTD_LPAR_AD_T4 0x00000200 /* Capable of T4 operation */
-#define MTD_LPAR_AD_TXFD 0x00000100 /* Cap. of 100-TX Full Duplex */
-#define MTD_LPAR_AD_TXHD 0x00000080 /* Cap. of 100-TX Half Duplex */
-#define MTD_LPAR_AD_TPFD 0x00000040 /* Cap. of 10-TP Full Duplex */
-#define MTD_LPAR_AD_TPHD 0x00000020 /* Cap. of 10-TP Half Duplex */
-#define MTD_LPAR_SELECTOR0 0x0000001f /* Selector field 0 */
-
-#endif /* __DEV_IC_MTD803REG_H__ */
diff --git a/sys/dev/ic/mtd803var.h b/sys/dev/ic/mtd803var.h
deleted file mode 100644
index 51c86a778c8..00000000000
--- a/sys/dev/ic/mtd803var.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/* $OpenBSD: mtd803var.h,v 1.2 2003/08/19 04:03:53 mickey Exp $ */
-/* $NetBSD: mtd803var.h,v 1.1 2002/11/07 21:57:00 martin Exp $ */
-
-/*-
- * Copyright (c) 2002 The NetBSD Foundation, Inc.
- * All rights reserved.
- *
- * This code is derived from software contributed to The NetBSD Foundation
- * by Peter Bex <Peter.Bex@student.kun.nl>.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the NetBSD
- * Foundation, Inc. and its contributors.
- * 4. Neither the name of The NetBSD Foundation nor the names of its
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
- * 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.
- */
-
-#ifndef __DEV_IC_MTD803VAR_H__
-#define __DEV_IC_MTD803VAR_H__
-
-#include <dev/mii/miivar.h>
-
-/* Number of Tx and Rx descriptors */
-#define MTD_NUM_TXD 128
-#define MTD_NUM_RXD 128
-/* Tx and Rx buffer size */
-#define MTD_RXBUF_SIZE 768
-#define MTD_TXBUF_SIZE 768
-
-/* DMA mem must be longword (4 bytes) aligned */
-#define MTD_DMA_ALIGN 4
-
-
-/* Descriptor structure */
-struct mtd_desc {
- u_int32_t stat; /* Status field */
- u_int32_t conf; /* Config field */
- u_int32_t data; /* Data buffer start address */
- u_int32_t next; /* Next descriptor address */
-};
-
-/* Softc struct */
-struct mtd_softc {
- struct device dev;
- struct mii_data mii;
- struct arpcom arpcom;
- bus_space_tag_t bus_tag;
- bus_space_handle_t bus_handle;
- void * sd_hook;
- volatile unsigned int cur_tx;
- volatile unsigned int cur_rx;
-
- bus_dma_tag_t dma_tag;
- struct mtd_desc * desc;
- bus_dmamap_t desc_dma_map;
- caddr_t buf;
- bus_dmamap_t buf_dma_map;
-};
-
-
-/* Transmit descriptor layout */
- /* Status register */
-#define MTD_TXD_OWNER 0x80000000 /* Owner bit */
-#define MTD_TXD_RSRVD0 0x7fffc000 /* Bits [30:14] are reserved */
-#define MTD_TXD_ABORT 0x00002000 /* Transmit aborted */
-#define MTD_TXD_CSL 0x00001000 /* Carrier Sense Loss */
-#define MTD_TXD_LCOL 0x00000800 /* Late collision */
-#define MTD_TXD_EXCOL 0x00000400 /* Excessive collisions */
-#define MTD_TXD_DFD 0x00000200 /* Deferred */
-#define MTD_TXD_HBFAIL 0x00000100 /* Heart-beat failure */
-#define MTD_TXD_NRC 0x000000ff /* Collision Retry Count */
- /* Configuration register */
-#define MTD_TXD_CONF_IRQC 0x80000000 /* Interrupt control */
-#define MTD_TXD_CONF_EIRQC 0x40000000 /* Early interrupt control */
-#define MTD_TXD_CONF_LSD 0x20000000 /* Last descriptor */
-#define MTD_TXD_CONF_FSD 0x10000000 /* First descriptor */
-#define MTD_TXD_CONF_CRC 0x08000000 /* CRC append */
-#define MTD_TXD_CONF_PAD 0x04000000 /* Pad control */
-#define MTD_TXD_CONF_RLCOL 0x02000000 /* Retry Late Collision */
-#define MTD_TXD_CONF_RSRVD0 0x01c00000 /* Bits [24:22] are reserved */
-#define MTD_TXD_CONF_PKTS 0x003ff800 /* Packet size */
-#define MTD_TXD_CONF_BUFS 0x000007ff /* Transmit buffer size */
-
-#define MTD_TXD_PKTS_SHIFT 11
-
-/* Receive descriptor layout */
- /* Status register */
-#define MTD_RXD_OWNER 0x80000000 /* Owner bit */
-#define MTD_RXD_RSRVD3 0x70000000 /* Bits [30:28] are reserved */
-#define MTD_RXD_FLEN 0x0fff0000 /* Frame length */
-#define MTD_RXD_RSRVD2 0x00008000 /* Bit 15 is reserved */
-#define MTD_RXD_MAR 0x00004000 /* Multicast Address Received */
-#define MTD_RXD_BAR 0x00002000 /* Broadcast Address Received */
-#define MTD_RXD_PAR 0x00001000 /* Physical Address Received */
-#define MTD_RXD_FSD 0x00000800 /* First Descriptor */
-#define MTD_RXD_LSD 0x00000400 /* Last Descriptor */
-#define MTD_RXD_RSRVD1 0x00000300 /* Bits [9:8] are reserved */
-#define MTD_RXD_ERRSUM 0x00000080 /* Error summary */
-#define MTD_RXD_RUNT 0x00000040 /* Runt packet received */
-#define MTD_RXD_LONG 0x00000020 /* Long packet received */
-#define MTD_RXD_FALERR 0x00000010 /* Frame alignment error */
-#define MTD_RXD_CRC 0x00000008 /* CRC error. See manual :) */
-#define MTD_RXD_RXERR 0x00000004 /* Receive error */
-#define MTD_RXD_RSRVD0 0x00000003 /* Bits [1:0] are reserved */
- /* Configuration register */
-#define MTD_RXD_CONF_RSRVD0 0xfffffc00 /* Bits [31:11] are reserved */
-#define MTD_RXD_CONF_BUFS 0x000003ff /* Receive buffer size */
-
-#define MTD_RXD_FLEN_SHIFT 16
-
-extern int mtd_config __P((struct mtd_softc *));
-extern int mtd_irq_h __P((void *));
-
-#endif /* __DEV_IC_MTD803VAR_H__ */
diff --git a/sys/dev/ic/mtd8xx.c b/sys/dev/ic/mtd8xx.c
new file mode 100644
index 00000000000..dc65aed9c1a
--- /dev/null
+++ b/sys/dev/ic/mtd8xx.c
@@ -0,0 +1,1103 @@
+/* $OpenBSD: mtd8xx.c,v 1.1 2003/09/25 22:05:59 mickey Exp $ */
+
+/*
+ * Copyright (c) 2003 Oleg Safiullin <form@pdp11.org.ru>
+ * 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 unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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.
+ *
+ */
+
+#include "bpfilter.h"
+
+#include <sys/param.h>
+#include <sys/mbuf.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <net/if.h>
+#include <net/if_media.h>
+
+#if NBPFILTER > 0
+#include <net/bpf.h>
+#endif
+
+#ifdef INET
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#endif
+
+#include <machine/bus.h>
+
+#include <dev/mii/mii.h>
+#include <dev/mii/miivar.h>
+
+#include <dev/pci/pcidevs.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/ic/mtd8xxreg.h>
+#include <dev/ic/mtd8xxvar.h>
+
+
+static int mtd_ifmedia_upd(struct ifnet *);
+static void mtd_ifmedia_sts(struct ifnet *, struct ifmediareq *);
+
+static u_int32_t mtd_mii_command(struct mtd_softc *, int, int, int);
+static int mtd_miibus_readreg(struct device *, int, int);
+static void mtd_miibus_writereg(struct device *, int, int, int);
+static void mtd_miibus_statchg(struct device *);
+static void mtd_setmulti(struct mtd_softc *);
+
+static int mtd_encap(struct mtd_softc *, struct mbuf *, u_int32_t *);
+static int mtd_list_rx_init(struct mtd_softc *);
+static void mtd_list_tx_init(struct mtd_softc *);
+static int mtd_newbuf(struct mtd_softc *, int, struct mbuf *);
+
+static void mtd_reset(struct mtd_softc *sc);
+static int mtd_ioctl(struct ifnet *, u_long, caddr_t);
+static void mtd_init(struct ifnet *);
+static void mtd_start(struct ifnet *);
+static void mtd_stop(struct ifnet *);
+static void mtd_watchdog(struct ifnet *);
+
+static void mtd_rxeof(struct mtd_softc *);
+static int mtd_rx_resync(struct mtd_softc *);
+static void mtd_txeof(struct mtd_softc *);
+
+
+void
+mtd_attach(struct mtd_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ u_int32_t enaddr[2];
+ int i;
+
+ /* Reset the adapter. */
+ mtd_reset(sc);
+
+ if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct mtd_list_data),
+ PAGE_SIZE, 0, sc->sc_listseg, 1, &sc->sc_listnseg,
+ BUS_DMA_NOWAIT) != 0) {
+ printf(": can't alloc list mem\n");
+ return;
+ }
+ if (bus_dmamem_map(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg,
+ sizeof(struct mtd_list_data), &sc->sc_listkva,
+ BUS_DMA_NOWAIT) != 0) {
+ printf(": can't map list mem\n");
+ return;
+ }
+ if (bus_dmamap_create(sc->sc_dmat, sizeof(struct mtd_list_data), 1,
+ sizeof(struct mtd_list_data), 0, BUS_DMA_NOWAIT,
+ &sc->sc_listmap) != 0) {
+ printf(": can't alloc list map\n");
+ return;
+ }
+ if (bus_dmamap_load(sc->sc_dmat, sc->sc_listmap, sc->sc_listkva,
+ sizeof(struct mtd_list_data), NULL, BUS_DMA_NOWAIT) != 0) {
+ printf(": can't load list map\n");
+ return;
+ }
+ sc->mtd_ldata = (struct mtd_list_data *)sc->sc_listkva;
+ bzero(sc->mtd_ldata, sizeof(struct mtd_list_data));
+
+ for (i = 0; i < MTD_RX_LIST_CNT; i++) {
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES,
+ 0, BUS_DMA_NOWAIT,
+ &sc->mtd_cdata.mtd_rx_chain[i].sd_map) != 0) {
+ printf(": can't create rx map\n");
+ return;
+ }
+ }
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
+ BUS_DMA_NOWAIT, &sc->sc_rx_sparemap) != 0) {
+ printf(": can't create rx spare map\n");
+ return;
+ }
+
+ for (i = 0; i < MTD_TX_LIST_CNT; i++) {
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+ MTD_TX_LIST_CNT - 5, MCLBYTES, 0, BUS_DMA_NOWAIT,
+ &sc->mtd_cdata.mtd_tx_chain[i].sd_map) != 0) {
+ printf(": can't create tx map\n");
+ return;
+ }
+ }
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, MTD_TX_LIST_CNT - 5,
+ MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_tx_sparemap) != 0) {
+ printf(": can't create tx spare map\n");
+ return;
+ }
+
+
+ /* Get station address. */
+ enaddr[0] = letoh32(CSR_READ_4(MTD_PAR0));
+ enaddr[1] = letoh32(CSR_READ_4(MTD_PAR4));
+ bcopy(enaddr, sc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
+ printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr));
+
+ /* Initialize interface */
+ ifp->if_softc = sc;
+ ifp->if_mtu = ETHERMTU;
+ ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
+ ifp->if_ioctl = mtd_ioctl;
+ ifp->if_output = ether_output;
+ ifp->if_start = mtd_start;
+ ifp->if_watchdog = mtd_watchdog;
+ ifp->if_baudrate = 10000000;
+ IFQ_SET_READY(&ifp->if_snd);
+ bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
+
+ /*
+ * Initialize our media structures and probe the MII.
+ */
+ sc->sc_mii.mii_ifp = ifp;
+ sc->sc_mii.mii_readreg = mtd_miibus_readreg;
+ sc->sc_mii.mii_writereg = mtd_miibus_writereg;
+ sc->sc_mii.mii_statchg = mtd_miibus_statchg;
+ ifmedia_init(&sc->sc_mii.mii_media, 0, mtd_ifmedia_upd,
+ mtd_ifmedia_sts);
+ mii_attach(&sc->sc_dev, &sc->sc_mii, 0xffffffff, MII_PHY_ANY,
+ MII_OFFSET_ANY, 0);
+ if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) {
+ ifmedia_add(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE, 0,
+ NULL);
+ ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_NONE);
+ } else
+ ifmedia_set(&sc->sc_mii.mii_media, IFM_ETHER | IFM_AUTO);
+
+ /*
+ * Attach us everywhere
+ */
+ if_attach(ifp);
+ ether_ifattach(ifp);
+}
+
+
+static int
+mtd_ifmedia_upd(struct ifnet *ifp)
+{
+ struct mtd_softc *sc = ifp->if_softc;
+
+ return (mii_mediachg(&sc->sc_mii));
+}
+
+
+static void
+mtd_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr)
+{
+ struct mtd_softc *sc = ifp->if_softc;
+
+ mii_pollstat(&sc->sc_mii);
+ ifmr->ifm_active = sc->sc_mii.mii_media_active;
+ ifmr->ifm_status = sc->sc_mii.mii_media_status;
+}
+
+
+static u_int32_t
+mtd_mii_command(struct mtd_softc *sc, int opcode, int phy, int reg)
+{
+ u_int32_t miir, mask, data;
+ int i;
+
+ miir = (CSR_READ_4(MTD_MIIMGT) & ~MIIMGT_MASK) | MIIMGT_WRITE |
+ MIIMGT_MDO;
+
+ for (i = 0; i < 32; i++) {
+ miir &= ~MIIMGT_MDC;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ miir |= MIIMGT_MDC;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ }
+
+ data = opcode | (phy << 7) | (reg << 2);
+
+ for (mask = 0; mask; mask >>= 1) {
+ miir &= ~(MIIMGT_MDC | MIIMGT_MDO);
+ if (mask & data)
+ miir |= MIIMGT_MDO;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ miir |= MIIMGT_MDC;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ DELAY(30);
+
+ if (mask == 0x4 && opcode == MII_OPCODE_RD)
+ miir &= ~MIIMGT_WRITE;
+ }
+ return (miir);
+}
+
+
+
+static int
+mtd_miibus_readreg(struct device *self, int phy, int reg)
+{
+ struct mtd_softc *sc = (void *)self;
+
+ if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD803)
+ return (phy ? 0 : (int)CSR_READ_2(MTD_PHYCSR + (reg << 1)));
+ else {
+ u_int32_t miir, mask, data;
+
+ miir = mtd_mii_command(sc, MII_OPCODE_RD, phy, reg);
+ for (mask = 0x8000, data = 0; mask; mask >>= 1) {
+ miir &= ~MIIMGT_MDC;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ miir = CSR_READ_4(MTD_MIIMGT);
+ if (miir & MIIMGT_MDI)
+ data |= mask;
+ miir |= MIIMGT_MDC;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ DELAY(30);
+ }
+ miir &= ~MIIMGT_MDC;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+
+ return ((int)data);
+ }
+}
+
+
+static void
+mtd_miibus_writereg(struct device *self, int phy, int reg, int val)
+{
+ struct mtd_softc *sc = (void *)self;
+
+ if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD803) {
+ if (!phy)
+ CSR_WRITE_2(MTD_PHYCSR + (reg << 1), val);
+ } else {
+ u_int32_t miir, mask;
+
+ miir = mtd_mii_command(sc, MII_OPCODE_WR, phy, reg);
+ for (mask = 0x8000; mask; mask >>= 1) {
+ miir &= ~(MIIMGT_MDC | MIIMGT_MDO);
+ if (mask & (u_int32_t)val)
+ miir |= MIIMGT_MDO;;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ miir |= MIIMGT_MDC;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ DELAY(1);
+ }
+ miir &= ~MIIMGT_MDC;
+ CSR_WRITE_4(MTD_MIIMGT, miir);
+ }
+}
+
+
+static void
+mtd_miibus_statchg(struct device *self)
+{
+ /* NOTHING */
+}
+
+
+void
+mtd_setmulti(struct mtd_softc *sc)
+{
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ u_int32_t rxfilt, crc, hash[2] = { 0, 0 };
+ struct ether_multistep step;
+ struct ether_multi *enm;
+ int mcnt = 0;
+
+ rxfilt = CSR_READ_4(MTD_TCRRCR) & ~RCR_AM;
+ if (ifp->if_flags & (IFF_ALLMULTI | IFF_PROMISC)) {
+ rxfilt |= RCR_AM;
+ CSR_WRITE_4(MTD_TCRRCR, rxfilt);
+ CSR_WRITE_4(MTD_MAR0, 0xffffffff);
+ CSR_WRITE_4(MTD_MAR4, 0xffffffff);
+ return;
+ }
+
+ /* First, zot all the existing hash bits. */
+ CSR_WRITE_4(MTD_MAR0, 0);
+ CSR_WRITE_4(MTD_MAR4, 0);
+
+ /* Now program new ones. */
+ ETHER_FIRST_MULTI(step, &sc->sc_arpcom, enm);
+ while (enm != NULL) {
+ crc = ether_crc32_be(enm->enm_addrlo, ETHER_ADDR_LEN) >> 26;
+ hash[crc >> 5] |= 1 << (crc & 0xf);
+ ++mcnt;
+ ETHER_NEXT_MULTI(step, enm);
+ }
+
+ if (mcnt)
+ rxfilt |= RCR_AM;
+ CSR_WRITE_4(MTD_MAR0, hash[0]);
+ CSR_WRITE_4(MTD_MAR4, hash[1]);
+ CSR_WRITE_4(MTD_TCRRCR, rxfilt);
+}
+
+
+/*
+ * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
+ * pointers to the fragment pointers.
+ */
+int
+mtd_encap(struct mtd_softc *sc, struct mbuf *m_head, u_int32_t *txidx)
+{
+ struct mtd_tx_desc *f = NULL;
+ int frag, cur, cnt = 0, i, total_len = 0;
+ bus_dmamap_t map;
+
+ /*
+ * Start packing the mbufs in this chain into
+ * the fragment pointers. Stop when we run out
+ * of fragments or hit the end of the mbuf chain.
+ */
+ map = sc->sc_tx_sparemap;
+
+ if (bus_dmamap_load_mbuf(sc->sc_dmat, map,
+ m_head, BUS_DMA_NOWAIT) != 0)
+ return (1);
+
+ cur = frag = *txidx;
+
+ for (i = 0; i < map->dm_nsegs; i++) {
+ if ((MTD_TX_LIST_CNT -
+ (sc->mtd_cdata.mtd_tx_cnt + cnt)) < 5) {
+ bus_dmamap_unload(sc->sc_dmat, map);
+ return (1);
+ }
+
+ f = &sc->mtd_ldata->mtd_tx_list[frag];
+ f->td_tcw = htole32(map->dm_segs[i].ds_len);
+ total_len += map->dm_segs[i].ds_len;
+ if (cnt == 0) {
+ f->td_tsw = 0;
+ f->td_tcw |= htole32(TCW_FD | TCW_CRC | TCW_PAD);
+ } else
+ f->td_tsw = htole32(TSW_OWN);
+ f->td_buf = htole32(map->dm_segs[i].ds_addr);
+ cur = frag;
+ frag = (frag + 1) % MTD_TX_LIST_CNT;
+ cnt++;
+ }
+
+ sc->mtd_cdata.mtd_tx_cnt += cnt;
+ sc->mtd_cdata.mtd_tx_chain[cur].sd_mbuf = m_head;
+ sc->sc_tx_sparemap = sc->mtd_cdata.mtd_tx_chain[cur].sd_map;
+ sc->mtd_cdata.mtd_tx_chain[cur].sd_map = map;
+ sc->mtd_ldata->mtd_tx_list[cur].td_tcw |= htole32(TCW_LD | TCW_IC);
+ if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD891)
+ sc->mtd_ldata->mtd_tx_list[cur].td_tcw |=
+ htole32(TCW_EIC | TCW_RTLC);
+
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
+
+ sc->mtd_ldata->mtd_tx_list[*txidx].td_tsw = htole32(TSW_OWN);
+ sc->mtd_ldata->mtd_tx_list[*txidx].td_tcw |=
+ htole32(total_len << TCW_PKTS_SHIFT);
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ offsetof(struct mtd_list_data, mtd_tx_list[0]),
+ sizeof(struct mtd_tx_desc) * MTD_TX_LIST_CNT,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ *txidx = frag;
+
+ return (0);
+}
+
+
+/*
+ * Initialize the transmit descriptors.
+ */
+static void
+mtd_list_tx_init(struct mtd_softc *sc)
+{
+ struct mtd_chain_data *cd;
+ struct mtd_list_data *ld;
+ int i;
+
+ cd = &sc->mtd_cdata;
+ ld = sc->mtd_ldata;
+ for (i = 0; i < MTD_TX_LIST_CNT;) {
+ cd->mtd_tx_chain[i].sd_mbuf = NULL;
+ ld->mtd_tx_list[i].td_tsw = 0;
+ ld->mtd_tx_list[i].td_tcw = 0;
+ ld->mtd_tx_list[i].td_buf = 0;
+ ld->mtd_tx_list[i].td_next = htole32(
+ sc->sc_listmap->dm_segs[0].ds_addr +
+ offsetof(struct mtd_list_data,
+ mtd_tx_list[++i % MTD_TX_LIST_CNT]));
+ }
+
+ cd->mtd_tx_prod = cd->mtd_tx_cons = cd->mtd_tx_cnt = 0;
+}
+
+
+/*
+ * Initialize the RX descriptors and allocate mbufs for them. Note that
+ * we arrange the descriptors in a closed ring, so that the last descriptor
+ * points back to the first.
+ */
+static int
+mtd_list_rx_init(struct mtd_softc *sc)
+{
+ struct mtd_list_data *ld;
+ int i;
+
+ ld = sc->mtd_ldata;
+
+ for (i = 0; i < MTD_RX_LIST_CNT;) {
+ if (mtd_newbuf(sc, i, NULL))
+ return (1);
+ ld->mtd_rx_list[i].rd_next = htole32(
+ sc->sc_listmap->dm_segs[0].ds_addr +
+ offsetof(struct mtd_list_data,
+ mtd_rx_list[++i % MTD_RX_LIST_CNT])
+ );
+ }
+
+ sc->mtd_cdata.mtd_rx_prod = 0;
+
+ return (0);
+}
+
+
+/*
+ * Initialize an RX descriptor and attach an MBUF cluster.
+ */
+static int
+mtd_newbuf(struct mtd_softc *sc, int i, struct mbuf *m)
+{
+ struct mbuf *m_new = NULL;
+ struct mtd_rx_desc *c;
+ bus_dmamap_t map;
+
+ c = &sc->mtd_ldata->mtd_rx_list[i];
+
+ if (m == NULL) {
+ MGETHDR(m_new, M_DONTWAIT, MT_DATA);
+ if (m_new == NULL) {
+ printf("%s: no memory for rx list "
+ "-- packet dropped!\n", sc->sc_dev.dv_xname);
+ return (1);
+ }
+
+ MCLGET(m_new, M_DONTWAIT);
+ if (!(m_new->m_flags & M_EXT)) {
+ printf("%s: no memory for rx list "
+ "-- packet dropped!\n", sc->sc_dev.dv_xname);
+ m_freem(m_new);
+ return (1);
+ }
+ m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+ if (bus_dmamap_load(sc->sc_dmat, sc->sc_rx_sparemap,
+ mtod(m_new, caddr_t), MCLBYTES, NULL,
+ BUS_DMA_NOWAIT) != 0) {
+ printf("%s: rx load failed\n", sc->sc_dev.dv_xname);
+ m_freem(m_new);
+ return (1);
+ }
+ map = sc->mtd_cdata.mtd_rx_chain[i].sd_map;
+ sc->mtd_cdata.mtd_rx_chain[i].sd_map = sc->sc_rx_sparemap;
+ sc->sc_rx_sparemap = map;
+ } else {
+ m_new = m;
+ m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
+ m_new->m_data = m_new->m_ext.ext_buf;
+ }
+
+ m_adj(m_new, sizeof(u_int64_t));
+
+ bus_dmamap_sync(sc->sc_dmat, sc->mtd_cdata.mtd_rx_chain[i].sd_map, 0,
+ sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
+
+ sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf = m_new;
+ c->rd_buf = htole32(
+ sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_segs[0].ds_addr +
+ sizeof(u_int64_t));
+ c->rd_rcw = htole32(MTD_RXLEN);
+ c->rd_rsr = htole32(RSR_OWN);
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ offsetof(struct mtd_list_data, mtd_rx_list[i]),
+ sizeof(struct mtd_rx_desc),
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
+ return (0);
+}
+
+
+static void
+mtd_reset(struct mtd_softc *sc)
+{
+ int i;
+
+ /* Set software reset bit */
+ CSR_WRITE_4(MTD_BCR, BCR_SWR);
+
+ /*
+ * Wait until software reset completed.
+ */
+ for (i = 0; i < MTD_TIMEOUT; ++i) {
+ DELAY(10);
+ if (!(CSR_READ_4(MTD_BCR) & BCR_SWR)) {
+ /*
+ * Wait a little while for the chip to get
+ * its brains in order.
+ */
+ DELAY(1000);
+ return;
+ }
+ }
+
+ /* Reset timed out. */
+ printf("%s: reset never completed!\n", sc->sc_dev.dv_xname);
+}
+
+
+static int
+mtd_ioctl(struct ifnet *ifp, u_long command, caddr_t data)
+{
+ struct mtd_softc *sc = ifp->if_softc;
+ struct ifreq *ifr = (struct ifreq *)data;
+ struct ifaddr *ifa = (struct ifaddr *)data;
+ int s, error;
+
+ s = splimp();
+ if ((error = ether_ioctl(ifp, &sc->sc_arpcom, command, data)) > 0) {
+ splx(s);
+ return (error);
+ }
+
+ switch (command) {
+ case SIOCSIFADDR:
+ ifp->if_flags |= IFF_UP;
+ mtd_init(ifp);
+ switch (ifa->ifa_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ arp_ifinit(&sc->sc_arpcom, ifa);
+ break;
+#endif /* INET */
+ }
+ break;
+ case SIOCSIFMTU:
+ if (ifr->ifr_mtu >= ETHERMIN && ifr->ifr_mtu <= ETHERMTU)
+ ifp->if_mtu = ifr->ifr_mtu;
+ else
+ error = EINVAL;
+ break;
+
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP)
+ mtd_init(ifp);
+ else {
+ if (ifp->if_flags & IFF_RUNNING)
+ mtd_stop(ifp);
+ }
+ error = 0;
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ error = (command == SIOCADDMULTI) ?
+ ether_addmulti(ifr, &sc->sc_arpcom) :
+ ether_delmulti(ifr, &sc->sc_arpcom);
+
+ if (error == ENETRESET) {
+ /*
+ * Multicast list has changed; set the hardware
+ * filter accordingly.
+ */
+ mtd_setmulti(sc);
+ error = 0;
+ }
+ break;
+ case SIOCGIFMEDIA:
+ case SIOCSIFMEDIA:
+ error = ifmedia_ioctl(ifp, ifr, &sc->sc_mii.mii_media, command);
+ break;
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ splx(s);
+ return (error);
+}
+
+
+static void
+mtd_init(struct ifnet *ifp)
+{
+ struct mtd_softc *sc = ifp->if_softc;
+ int s;
+
+ s = splimp();
+
+ /*
+ * Cancel pending I/O and free all RX/TX buffers.
+ */
+ mtd_stop(ifp);
+
+ /*
+ * Set cache alignment and burst length.
+ */
+ CSR_WRITE_4(MTD_BCR, BCR_PBL8);
+ CSR_WRITE_4(MTD_TCRRCR, TCR_TFTSF | RCR_RBLEN | RCR_RPBL512);
+ if (sc->sc_devid == PCI_PRODUCT_MYSON_MTD891) {
+ CSR_SETBIT(MTD_BCR, BCR_PROG);
+ CSR_SETBIT(MTD_TCRRCR, TCR_ENHANCED);
+ }
+
+ if (ifp->if_flags & IFF_PROMISC)
+ CSR_SETBIT(MTD_TCRRCR, RCR_PROM);
+ else
+ CSR_CLRBIT(MTD_TCRRCR, RCR_PROM);
+
+ if (ifp->if_flags & IFF_BROADCAST)
+ CSR_SETBIT(MTD_TCRRCR, RCR_AB);
+ else
+ CSR_CLRBIT(MTD_TCRRCR, RCR_AB);
+
+ mtd_setmulti(sc);
+
+ if (mtd_list_rx_init(sc)) {
+ printf("%s: can't allocate memeory for rx buffers\n",
+ sc->sc_dev.dv_xname);
+ splx(s);
+ return;
+ }
+ mtd_list_tx_init(sc);
+
+ CSR_WRITE_4(MTD_RXLBA, sc->sc_listmap->dm_segs[0].ds_addr +
+ offsetof(struct mtd_list_data, mtd_rx_list[0]));
+ CSR_WRITE_4(MTD_TXLBA, sc->sc_listmap->dm_segs[0].ds_addr +
+ offsetof(struct mtd_list_data, mtd_tx_list[0]));
+
+ /*
+ * Enable interrupts.
+ */
+ CSR_WRITE_4(MTD_IMR, IMR_INTRS);
+ CSR_WRITE_4(MTD_ISR, 0xffffffff);
+
+ /* Enable receiver and transmitter */
+ CSR_SETBIT(MTD_TCRRCR, TCR_TE | RCR_RE);
+ CSR_WRITE_4(MTD_RXPDR, 0xffffffff);
+
+ ifp->if_flags |= IFF_RUNNING;
+ ifp->if_flags &= ~IFF_OACTIVE;
+ splx(s);
+}
+
+
+/*
+ * Main transmit routine. To avoid having to do mbuf copies, we put pointers
+ * to the mbuf data regions directly in the transmit lists. We also save a
+ * copy of the pointers since the transmit list fragment pointers are
+ * physical addresses.
+ */
+static void
+mtd_start(struct ifnet *ifp)
+{
+ struct mtd_softc *sc = ifp->if_softc;
+ struct mbuf *m_head = NULL;
+ int idx;
+
+ if (sc->mtd_cdata.mtd_tx_cnt) {
+ ifp->if_flags |= IFF_OACTIVE;
+ return;
+ }
+
+ idx = sc->mtd_cdata.mtd_tx_prod;
+ while (sc->mtd_cdata.mtd_tx_chain[idx].sd_mbuf == NULL) {
+ IFQ_DEQUEUE(&ifp->if_snd, m_head);
+ if (m_head == NULL)
+ break;
+
+ if (mtd_encap(sc, m_head, &idx)) {
+ ifp->if_flags |= IFF_OACTIVE;
+ break;
+ }
+
+ /*
+ * If there's a BPF listener, bounce a copy of this frame
+ * to him.
+ */
+#if NBPFILTER > 0
+ if (ifp->if_bpf != NULL)
+ bpf_mtap(ifp->if_bpf, m_head);
+#endif
+ }
+
+ if (idx == sc->mtd_cdata.mtd_tx_prod)
+ return;
+
+ /* Transmit */
+ sc->mtd_cdata.mtd_tx_prod = idx;
+ CSR_WRITE_4(MTD_TXPDR, 0xffffffff);
+
+ /*
+ * Set a timeout in case the chip goes out to lunch.
+ */
+ ifp->if_timer = 5;
+}
+
+
+static void
+mtd_stop(struct ifnet *ifp)
+{
+ struct mtd_softc *sc = ifp->if_softc;
+ int i;
+
+ ifp->if_timer = 0;
+ ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+
+ CSR_CLRBIT(MTD_TCRRCR, (RCR_RE | TCR_TE));
+ CSR_WRITE_4(MTD_IMR, 0);
+ CSR_WRITE_4(MTD_TXLBA, 0);
+ CSR_WRITE_4(MTD_RXLBA, 0);
+
+ /*
+ * Free data in the RX lists.
+ */
+ for (i = 0; i < MTD_RX_LIST_CNT; i++) {
+ if (sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_nsegs != 0) {
+ bus_dmamap_t map = sc->mtd_cdata.mtd_rx_chain[i].sd_map;
+
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmat, map);
+ }
+ if (sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf != NULL) {
+ m_freem(sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf);
+ sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf = NULL;
+ }
+ }
+ bzero((char *)&sc->mtd_ldata->mtd_rx_list,
+ sizeof(sc->mtd_ldata->mtd_rx_list));
+
+ /*
+ * Free the TX list buffers.
+ */
+ for (i = 0; i < MTD_TX_LIST_CNT; i++) {
+ if (sc->mtd_cdata.mtd_tx_chain[i].sd_map->dm_nsegs != 0) {
+ bus_dmamap_t map = sc->mtd_cdata.mtd_tx_chain[i].sd_map;
+
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, map);
+ }
+ if (sc->mtd_cdata.mtd_tx_chain[i].sd_mbuf != NULL) {
+ m_freem(sc->mtd_cdata.mtd_tx_chain[i].sd_mbuf);
+ sc->mtd_cdata.mtd_tx_chain[i].sd_mbuf = NULL;
+ }
+ }
+
+ bzero((char *)&sc->mtd_ldata->mtd_tx_list,
+ sizeof(sc->mtd_ldata->mtd_tx_list));
+
+}
+
+
+static void
+mtd_watchdog(struct ifnet *ifp)
+{
+ struct mtd_softc *sc = ifp->if_softc;
+
+ ifp->if_oerrors++;
+ printf("%s: watchdog timeout\n", sc->sc_dev.dv_xname);
+
+ mtd_stop(ifp);
+ mtd_reset(sc);
+ mtd_init(ifp);
+
+ if (!IFQ_IS_EMPTY(&ifp->if_snd))
+ mtd_start(ifp);
+}
+
+
+int
+mtd_intr(void *xsc)
+{
+ struct mtd_softc *sc = xsc;
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ u_int32_t status;
+ int claimed = 0;
+
+ /* Supress unwanted interrupts */
+ if (!(ifp->if_flags & IFF_RUNNING)) {
+ if (CSR_READ_4(MTD_ISR) & ISR_INTRS)
+ mtd_stop(ifp);
+ return (claimed);
+ }
+
+ /* Disable interrupts. */
+ CSR_WRITE_4(MTD_IMR, 0);
+
+ while((status = CSR_READ_4(MTD_ISR)) & ISR_INTRS) {
+ claimed = 1;
+
+ CSR_WRITE_4(MTD_ISR, status);
+
+ /* RX interrupt. */
+ if (status & ISR_RI) {
+ int curpkts = ifp->if_ipackets;
+
+ mtd_rxeof(sc);
+ if (curpkts == ifp->if_ipackets)
+ while(mtd_rx_resync(sc))
+ mtd_rxeof(sc);
+ }
+
+ /* RX error interrupt. */
+ if (status & (ISR_RXERI | ISR_RBU))
+ ifp->if_ierrors++;
+
+ /* TX interrupt. */
+ if (status & (ISR_TI | ISR_ETI | ISR_TBU))
+ mtd_txeof(sc);
+
+ /* Fatal bus error interrupt. */
+ if (status & ISR_FBE) {
+ mtd_reset(sc);
+ mtd_start(ifp);
+ }
+ }
+
+ /* Re-enable interrupts. */
+ CSR_WRITE_4(MTD_IMR, IMR_INTRS);
+
+ if (!IFQ_IS_EMPTY(&ifp->if_snd))
+ mtd_start(ifp);
+
+ return (claimed);
+}
+
+
+/*
+ * A frame has been uploaded: pass the resulting mbuf chain up to
+ * the higher level protocols.
+ */
+static void
+mtd_rxeof(struct mtd_softc *sc)
+{
+ struct mbuf *m;
+ struct ifnet *ifp;
+ struct mtd_rx_desc *cur_rx;
+ int i, total_len = 0;
+ u_int32_t rxstat;
+
+ ifp = &sc->sc_arpcom.ac_if;
+ i = sc->mtd_cdata.mtd_rx_prod;
+
+ while(!(sc->mtd_ldata->mtd_rx_list[i].rd_rsr & htole32(RSR_OWN))) {
+ struct mbuf *m0 = NULL;
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ offsetof(struct mtd_list_data, mtd_rx_list[i]),
+ sizeof(struct mtd_rx_desc),
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ cur_rx = &sc->mtd_ldata->mtd_rx_list[i];
+ rxstat = letoh32(cur_rx->rd_rsr);
+ m = sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf;
+ total_len = RSR_FLNG_GET(rxstat);
+
+ sc->mtd_cdata.mtd_rx_chain[i].sd_mbuf = NULL;
+
+ /*
+ * If an error occurs, update stats, clear the
+ * status word and leave the mbuf cluster in place:
+ * it should simply get re-used next time this descriptor
+ * comes up in the ring.
+ */
+ if (rxstat & RSR_RXER) {
+ ifp->if_ierrors++;
+ mtd_newbuf(sc, i, m);
+ if (rxstat & RSR_CRC) {
+ i = (i + 1) % MTD_RX_LIST_CNT;
+ continue;
+ } else {
+ mtd_init(ifp);
+ return;
+ }
+ }
+
+ /* No errors; receive the packet. */
+ total_len -= ETHER_CRC_LEN;
+
+ bus_dmamap_sync(sc->sc_dmat, sc->mtd_cdata.mtd_rx_chain[i].sd_map,
+ 0, sc->mtd_cdata.mtd_rx_chain[i].sd_map->dm_mapsize,
+ BUS_DMASYNC_POSTREAD);
+
+ m0 = m_devget(mtod(m, char *) - 2, total_len + 2, 0, ifp,
+ NULL);
+ mtd_newbuf(sc, i, m);
+ i = (i + 1) % MTD_RX_LIST_CNT;
+ if (m0 == NULL) {
+ ifp->if_ierrors++;
+ continue;
+ }
+ m_adj(m0, 2);
+ m = m0;
+
+ ifp->if_ipackets++;
+
+#if NBPFILTER > 0
+ if (ifp->if_bpf)
+ bpf_mtap(ifp->if_bpf, m);
+#endif
+ ether_input_mbuf(ifp, m);
+ }
+
+ sc->mtd_cdata.mtd_rx_prod = i;
+}
+
+
+/*
+ * This routine searches the RX ring for dirty descriptors in the
+ * event that the rxeof routine falls out of sync with the chip's
+ * current descriptor pointer. This may happen sometimes as a result
+ * of a "no RX buffer available" condition that happens when the chip
+ * consumes all of the RX buffers before the driver has a chance to
+ * process the RX ring. This routine may need to be called more than
+ * once to bring the driver back in sync with the chip, however we
+ * should still be getting RX DONE interrupts to drive the search
+ * for new packets in the RX ring, so we should catch up eventually.
+ */
+static int
+mtd_rx_resync(sc)
+ struct mtd_softc *sc;
+{
+ int i, pos;
+ struct mtd_rx_desc *cur_rx;
+
+ pos = sc->mtd_cdata.mtd_rx_prod;
+
+ for (i = 0; i < MTD_RX_LIST_CNT; i++) {
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ offsetof(struct mtd_list_data, mtd_rx_list[pos]),
+ sizeof(struct mtd_rx_desc),
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ cur_rx = &sc->mtd_ldata->mtd_rx_list[pos];
+ if (!(cur_rx->rd_rsr & htole32(RSR_OWN)))
+ break;
+ pos = (pos + 1) % MTD_RX_LIST_CNT;
+ }
+
+ /* If the ring really is empty, then just return. */
+ if (i == MTD_RX_LIST_CNT)
+ return (0);
+
+ /* We've fallen behing the chip: catch it. */
+ sc->mtd_cdata.mtd_rx_prod = pos;
+
+ return (EAGAIN);
+}
+
+
+/*
+ * A frame was downloaded to the chip. It's safe for us to clean up
+ * the list buffers.
+ */
+static void
+mtd_txeof(struct mtd_softc *sc)
+{
+ struct mtd_tx_desc *cur_tx = NULL;
+ struct ifnet *ifp = &sc->sc_arpcom.ac_if;
+ int idx;
+
+ /* Clear the timeout timer. */
+ ifp->if_timer = 0;
+
+ /*
+ * Go through our tx list and free mbufs for those
+ * frames that have been transmitted.
+ */
+ idx = sc->mtd_cdata.mtd_tx_cons;
+ while(idx != sc->mtd_cdata.mtd_tx_prod) {
+ u_int32_t txstat;
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ offsetof(struct mtd_list_data, mtd_tx_list[idx]),
+ sizeof(struct mtd_tx_desc),
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
+ cur_tx = &sc->mtd_ldata->mtd_tx_list[idx];
+ txstat = letoh32(cur_tx->td_tsw);
+
+ if (txstat & TSW_OWN || txstat == TSW_UNSENT)
+ break;
+
+ if (!(cur_tx->td_tcw & htole32(TCW_LD))) {
+ sc->mtd_cdata.mtd_tx_cnt--;
+ idx = (idx + 1) % MTD_TX_LIST_CNT;
+ continue;
+ }
+
+ if (CSR_READ_4(MTD_TCRRCR) & TCR_ENHANCED)
+ ifp->if_collisions += TSR_NCR_GET(CSR_READ_4(MTD_TSR));
+ else {
+ if (txstat & TSW_TXERR) {
+ ifp->if_oerrors++;
+ if (txstat & TSW_EC)
+ ifp->if_collisions++;
+ if (txstat & TSW_LC)
+ ifp->if_collisions++;
+ }
+ ifp->if_collisions += TSW_NCR_GET(txstat);
+ }
+
+ ifp->if_opackets++;
+ if (sc->mtd_cdata.mtd_tx_chain[idx].sd_map->dm_nsegs != 0) {
+ bus_dmamap_t map =
+ sc->mtd_cdata.mtd_tx_chain[idx].sd_map;
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, map);
+ }
+ if (sc->mtd_cdata.mtd_tx_chain[idx].sd_mbuf != NULL) {
+ m_freem(sc->mtd_cdata.mtd_tx_chain[idx].sd_mbuf);
+ sc->mtd_cdata.mtd_tx_chain[idx].sd_mbuf = NULL;
+ }
+ sc->mtd_cdata.mtd_tx_cnt--;
+ idx = (idx + 1) % MTD_TX_LIST_CNT;
+ }
+
+ if (cur_tx != NULL) {
+ ifp->if_flags &= ~IFF_OACTIVE;
+ sc->mtd_cdata.mtd_tx_cons = idx;
+ } else
+ if (sc->mtd_ldata->mtd_tx_list[idx].td_tsw ==
+ htole32(TSW_UNSENT)) {
+ sc->mtd_ldata->mtd_tx_list[idx].td_tsw =
+ htole32(TSW_OWN);
+ ifp->if_timer = 5;
+ CSR_WRITE_4(MTD_TXPDR, 0xffffffff);
+ }
+}
+
+struct cfdriver mtd_cd = {
+ 0, "mtd", DV_IFNET
+};
diff --git a/sys/dev/ic/mtd8xxreg.h b/sys/dev/ic/mtd8xxreg.h
new file mode 100644
index 00000000000..ee8ef7ea075
--- /dev/null
+++ b/sys/dev/ic/mtd8xxreg.h
@@ -0,0 +1,215 @@
+/* $OpenBSD: mtd8xxreg.h,v 1.1 2003/09/25 22:05:59 mickey Exp $ */
+
+/*
+ * Copyright (c) 2003 Oleg Safiullin <form@pdp11.org.ru>
+ * 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 unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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.
+ *
+ */
+
+#ifndef __DEV_IC_MTD8XXREG_H__
+#define __DEV_IC_MTD8XXREG_H__
+
+#define MTD_PCI_LOIO 0x10 /* PCI I/O base address register */
+#define MTD_PCI_LOMEM 0x14 /* PCI memory base address register */
+
+#define MTD_TIMEOUT 1000 /* Software reset timeout */
+
+#define MII_OPCODE_RD 0x6000
+#define MII_OPCODE_WR 0x5002
+
+/*
+ * MTD8xx command and status register.
+ */
+#define MTD_PAR0 0x00 /* Physical address register 0*/
+#define MTD_PAR4 0x04 /* Physical address register 4 */
+#define MTD_MAR0 0x08 /* Multicast address register 0 */
+#define MTD_MAR4 0x0C /* Multicast address register 4 */
+#define MTD_TCRRCR 0x18 /* Transmit/receive config */
+#define MTD_BCR 0x1C /* Bus configuration register */
+#define MTD_TXPDR 0x20 /* Transmit poll demand */
+#define MTD_RXPDR 0x24 /* Receive poll demand */
+#define MTD_RXCWP 0x28 /* Receive current word pointer */
+#define MTD_TXLBA 0x2C /* Transmit list base address */
+#define MTD_RXLBA 0x30 /* Receive list base address */
+#define MTD_ISR 0x34 /* Interrupt status register */
+#define MTD_IMR 0x38 /* Interrupt mask register */
+#define MTD_TSR 0x48 /* Tally counter register */
+#define MTD_MIIMGT 0x40 /* MII management register */
+#define MTD_PHYCSR 0x4C /* PHY control status register */
+
+
+/*
+ * Receive configuration register.
+ */
+#define RCR_RXS 0x00008000U /* Receive process is running */
+#define RCR_EIEN 0x00004000U /* Early interrupt enabled */
+#define RCR_RFCEN 0x00002000U /* Receive flow control enabled */
+#define RCR_NDFA 0x00001000U /* Not defined flow control address */
+#define RCR_RBLEN 0x00000800U /* Receive burst length enable */
+#define RCR_RPBL1 0x00000000U /* 1 word */
+#define RCR_RPBL4 0x00000100U /* 4 words */
+#define RCR_RPBL8 0x00000200U /* 8 words */
+#define RCR_RPBL16 0x00000300U /* 16 words */
+#define RCR_RPBL32 0x00000400U /* 32 words */
+#define RCR_RPBL64 0x00000500U /* 64 words */
+#define RCR_RPBL128 0x00000600U /* 128 words */
+#define RCR_RPBL512 0x00000700U /* 512 words */
+#define RCR_PROM 0x00000080U /* Promiscuous mode */
+#define RCR_AB 0x00000040U /* Accept broadcast addresses */
+#define RCR_AM 0x00000020U /* Accept multicast addresses */
+#define RCR_ARP 0x00000008U /* Accept runt packets */
+#define RCR_ALP 0x00000004U /* Accept long packets */
+#define RCR_SEP 0x00000002U /* Accept packets w/ receive errors */
+#define RCR_RE 0x00000001U /* Receive enable */
+
+
+/*
+ * Transmit configuration register.
+ */
+#define TCR_TXS 0x80000000U /* Tx process is running */
+#define TCR_BACKOPT 0x10000000U /* Optional back-off */
+#define TCR_FBACK 0x08000000U /* Fast back-off */
+#define TCR_ENHANCED 0x02000000U /* Enhanced transmit mode */
+#define TCR_TFCEN 0x01000000U /* Ttansmit flow control enable */
+#define TCR_TFT64 0x00000000U /* 64 bytes */
+#define TCR_TFT32 0x00200000U /* 32 bytes */
+#define TCR_TFT128 0x00400000U /* 128 bytes */
+#define TCR_TFT256 0x00600000U /* 256 bytes */
+#define TCR_TFT512 0x00800000U /* 512 bytes */
+#define TCR_TFT768 0x00A00000U /* 768 bytes */
+#define TCR_TFT1024 0x00C00000U /* 1024 bytes */
+#define TCR_TFTSF 0x00E00000U /* Transmit store and forward */
+#define TCR_FD 0x00100000U /* Full-duplex mode */
+#define TCR_PS 0x00080000U /* Port speed is 10Mbit/s */
+#define TCR_TE 0x00040000U /* Transmit enable */
+#define TCR_LB 0x00020000U /* MII loopback on */
+
+
+/*
+ * Bus confiruration register.
+ */
+#define BCR_PROG 0x00000200U /* Programming */
+#define BCR_RLE 0x00000100U /* Read line cmd enable */
+#define BCR_RME 0x00000080U /* Read multiple cmd enable */
+#define BCR_WIE 0x00000040U /* Write and invalidate cmd enable */
+ /* Programmable burst length */
+#define BCR_PBL1 0x00000000U /* 1 dword */
+#define BCR_PBL4 0x00000008U /* 4 dwords */
+#define BCR_PBL8 0x00000010U /* 8 dwords */
+#define BCR_PBL16 0x00000018U /* 16 dwords */
+#define BCR_PBL32 0x00000020U /* 32 dwords */
+#define BCR_PBL64 0x00000028U /* 64 dwords */
+#define BCR_PBL128 0x00000030U /* 128 dwords */
+#define BCR_PBL512 0x00000038U /* 512 dwords */
+#define BCR_SWR 0x00000001U /* Software reset */
+
+
+/*
+ * Interrupt status register.
+ */
+#define ISR_PDF 0x00040000U /* Parallel detection fault */
+#define ISR_RFCON 0x00020000U /* Receive flow control XON */
+#define ISR_RFCOFF 0x00010000U /* Receive flow control XOFF */
+#define ISR_LSC 0x00008000U /* Link status change */
+#define ISR_ANC 0x00004000U /* Auto-negatiation completed */
+#define ISR_FBE 0x00002000U /* Fatal bus error */
+#define ISR_ETMASK 0x00001800U /* Error type mask */
+#define ISR_ET(x) ((x) & ISR_ETMASK)
+#define ISR_ETPARITY 0x00000000U /* Parity error */
+#define ISR_ETMASTER 0x00000800U /* Master abort */
+#define ISR_ETTARGET 0x00001000U /* Target abort */
+#define ISR_TUNF 0x00000400U /* Transmit underflow */
+#define ISR_ROVF 0x00000200U /* Receive overflow */
+#define ISR_ETI 0x00000100U /* Early transfer interrupt */
+#define ISR_ERI 0x00000080U /* Early receive interrupt */
+#define ISR_CNTOVF 0x00000040U /* CRC or MPA tally ounter overflow */
+#define ISR_RBU 0x00000020U /* Receive buffer unavailable */
+#define ISR_TBU 0x00000010U /* Transmit buffer unavailable */
+#define ISR_TI 0x00000008U /* Transmit interrupt */
+#define ISR_RI 0x00000004U /* Receive interrupt */
+#define ISR_RXERI 0x00000002U /* Receive error interrupt */
+
+#define ISR_INTRS (ISR_RBU | ISR_TBU | ISR_TI | ISR_RI | ISR_ETI)
+
+
+/*
+ * Interrupt mask register.
+ */
+#define IMR_MPDF 0x00040000U /* Parallel detection fault */
+#define IMR_MRFCON 0x00020000U /* Receive flow control XON */
+#define IMR_MRFCOFF 0x00010000U /* Receive flow control XOFF */
+#define IMR_MLSC 0x00008000U /* Link status change */
+#define IMR_MANC 0x00004000U /* Auto-negatiation completed */
+#define IMR_MFBE 0x00002000U /* Fatal bus error */
+#define IMR_MTUNF 0x00000400U /* Transmit underflow */
+#define IMR_MROVF 0x00000200U /* Receive overflow */
+#define IMR_METI 0x00000100U /* Early transfer interrupt */
+#define IMR_MERI 0x00000080U /* Early receive interrupt */
+#define IMR_MCNTOVF 0x00000040U /* CRC or MPA tally ounter overflow */
+#define IMR_MRBU 0x00000020U /* Receive buffer unavailable */
+#define IMR_MTBU 0x00000010U /* Transmit buffer unavailable */
+#define IMR_MTI 0x00000008U /* Transmit interrupt */
+#define IMR_MRI 0x00000004U /* Receive interrupt */
+#define IMR_MRXERI 0x00000002U /* Receive error interrupt */
+
+#define IMR_INTRS (IMR_MRBU | IMR_MTBU | IMR_MTI | IMR_MRI | IMR_METI)
+
+/*
+ * Transmit status register.
+ */
+#define TSR_NCR_MASK 0x0000FFFFU
+#define TSR_NCR_SHIFT 0
+#define TSR_NCR_GET(x) (((x) & TSR_NCR_MASK) >> TSR_NCR_SHIFT)
+ /* Retry collisions count */
+
+/*
+ * MII management register.
+ */
+#define MIIMGT_READ 0x00000000U
+#define MIIMGT_WRITE 0x00000008U
+#define MIIMGT_MDO 0x00000004U
+#define MIIMGT_MDI 0x00000002U
+#define MIIMGT_MDC 0x00000001U
+#define MIIMGT_MASK 0x0000000FU
+
+/*
+ * Command and status register space access macros.
+ */
+#define CSR_READ_1(reg) bus_space_read_1(sc->sc_bust, sc->sc_bush, reg)
+#define CSR_WRITE_1(reg, val) \
+ bus_space_write_1(sc->sc_bust, sc->sc_bush, reg, val)
+
+#define CSR_READ_2(reg) bus_space_read_2(sc->sc_bust, sc->sc_bush, reg)
+#define CSR_WRITE_2(reg, vat) \
+ bus_space_write_2(sc->sc_bust, sc->sc_bush, reg, val)
+
+#define CSR_READ_4(reg) bus_space_read_4(sc->sc_bust, sc->sc_bush, reg)
+#define CSR_WRITE_4(reg, val) \
+ bus_space_write_4(sc->sc_bust, sc->sc_bush, reg, val)
+
+#define CSR_SETBIT(reg, val) CSR_WRITE_4(reg, CSR_READ_4(reg) | (val))
+#define CSR_CLRBIT(reg, val) CSR_WRITE_4(reg, CSR_READ_4(reg) & ~(val))
+
+#endif /* __DEV_IC_MTD8XXREG_H__ */
diff --git a/sys/dev/ic/mtd8xxvar.h b/sys/dev/ic/mtd8xxvar.h
new file mode 100644
index 00000000000..959e85c8f3e
--- /dev/null
+++ b/sys/dev/ic/mtd8xxvar.h
@@ -0,0 +1,156 @@
+/* $OpenBSD: mtd8xxvar.h,v 1.1 2003/09/25 22:05:59 mickey Exp $ */
+
+/*
+ * Copyright (c) 2003 Oleg Safiullin <form@pdp11.org.ru>
+ * 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 unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 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.
+ *
+ */
+
+#ifndef __DEV_IC_MTD8XXVAR_H__
+#define __DEV_IC_MTD8XXVAR_H__
+
+#define MTD_RX_LIST_CNT 64
+#define MTD_TX_LIST_CNT 128
+#define MTD_RXLEN 1536
+
+
+/*
+ * Transmit descriptor structure.
+ */
+struct mtd_tx_desc {
+ u_int32_t td_tsw; /* Transmit status word */
+#define TSW_OWN 0x80000000U /* Descriptor owned by NIC */
+#define TSW_TXERR 0x00008000U /* Transmission error */
+#define TSW_ABORT 0x00002000U /* Transmission aborted */
+#define TSW_CSL 0x00001000U /* Carrier sense lost */
+#define TSW_LC 0x00000800U /* Late collision occurs */
+#define TSW_EC 0x00000400U /* Excessive collisions */
+#define TSW_DFR 0x00000200U /* Deffered */
+#define TSW_HF 0x00000100U /* Heart beat failure */
+#define TSW_NCR_MASK 0x000000FFU
+#define TSW_NCR_SHIFT 0
+#define TSW_NCR_GET(x) (((x) & TSW_NCR_MASK) >> TSW_NCR_SHIFT)
+ /* Collision retry count */
+#define TSW_UNSENT 0x00001234U /* Unsent packet magic */
+ u_int32_t td_tcw; /* Transmit configure word */
+#define TCW_IC 0x80000000U /* Interrupt control */
+#define TCW_EIC 0x40000000U /* Early interrupt control */
+#define TCW_LD 0x20000000U /* Last descriptor */
+#define TCW_FD 0x10000000U /* First descriptor */
+#define TCW_CRC 0x08000000U /* Append CRC field to packet */
+#define TCW_PAD 0x04000000U /* Pad zeroes to the end of packet */
+#define TCW_RTLC 0x02000000U /* Retry late collision */
+#define TCW_PKTS_MASK 0x00003FF8U
+#define TCW_PKTS_SHIFT 11
+#define TCW_PKTS_GET(x) (((x) & TCW_PKTS_MASK) >> TCW_PKTS_SHIFT)
+ /* Packet size */
+#define TCW_TBS_MASK 0x000007FFU
+#define TCW_TBS_SHIFT 0
+#define TCW_TBS_GET(x) (((x) & TCW_TBS_MASK) >> TCW_TBS_SHIFT)
+ /* Transmit buffer size */
+ u_int32_t td_buf; /* Transmit buffer address */
+ u_int32_t td_next; /* Next descriptor address */
+};
+
+
+/*
+ * Receive descriptor structure.
+ */
+struct mtd_rx_desc {
+ u_int32_t rd_rsr; /* Receive status register */
+#define RSR_OWN 0x80000000U /* Decriptor owned by NIC */
+#define RSR_FLNG_MASK 0x0FFF0000U
+#define RSR_FLNG_SHIFT 16
+#define RSR_FLNG_GET(x) (((x) & RSR_FLNG_MASK) >> RSR_FLNG_SHIFT)
+ /* Frame length */
+#define RSR_MAR 0x00004000U /* Multicast address received */
+#define RSR_BAR 0x00002000U /* Broadcast address received */
+#define RSR_PHY 0x00001000U /* Physical address received */
+#define RSR_FSD 0x00000800U /* First descriptor */
+#define RSR_LSD 0x00000400U /* Last descriptor */
+#define RSR_ES 0x00000080U /* Error summary */
+#define RSR_RUNT 0x00000040U /* Runt packet received */
+#define RSR_LONG 0x00000020U /* Long packet received */
+#define RSR_FAE 0x00000010U /* Frame alignment error */
+#define RSR_CRC 0x00000008U /* CRC error */
+#define RSR_RXER 0x00000004U /* Receive error */
+ u_int32_t rd_rcw; /* Receive configure word */
+#define RCW_RBS_MASK 0x000007FFU
+#define RCW_RBS_SHIFT 0
+#define RCW_RBS_GET(x) (((x) & RCW_RBS_MASK) >> RCW_RBS_SHIFT)
+ u_int32_t rd_buf; /* Receive buffer address */
+ u_int32_t rd_next; /* Next descriptor address */
+};
+
+
+struct mtd_list_data {
+ struct mtd_rx_desc mtd_rx_list[MTD_RX_LIST_CNT];
+ struct mtd_tx_desc mtd_tx_list[MTD_TX_LIST_CNT];
+};
+
+
+struct mtd_swdesc {
+ bus_dmamap_t sd_map;
+ struct mbuf *sd_mbuf;
+};
+
+
+struct mtd_chain_data {
+ struct mtd_swdesc mtd_rx_chain[MTD_RX_LIST_CNT];
+ struct mtd_swdesc mtd_tx_chain[MTD_TX_LIST_CNT];
+ int mtd_tx_prod;
+ int mtd_tx_cons;
+ int mtd_tx_cnt;
+ int mtd_rx_prod;
+};
+
+
+struct mtd_softc {
+ struct device sc_dev;
+ struct arpcom sc_arpcom;
+ struct mii_data sc_mii;
+ pci_product_id_t sc_devid;
+
+ bus_space_handle_t sc_bush;
+ bus_space_tag_t sc_bust;
+
+ struct mtd_list_data *mtd_ldata;
+ struct mtd_chain_data mtd_cdata;
+
+ bus_dma_tag_t sc_dmat;
+ bus_dmamap_t sc_listmap;
+ bus_dma_segment_t sc_listseg[1];
+ int sc_listnseg;
+ caddr_t sc_listkva;
+ bus_dmamap_t sc_rx_sparemap;
+ bus_dmamap_t sc_tx_sparemap;
+};
+
+__BEGIN_DECLS
+void mtd_attach(struct mtd_softc *);
+int mtd_intr(void *);
+__END_DECLS
+
+#endif /* __DEV_IC_MTD8XXVAR_H__ */
diff --git a/sys/dev/pci/if_mtd_pci.c b/sys/dev/pci/if_mtd_pci.c
index be8e0eb147e..9e66cd9acec 100644
--- a/sys/dev/pci/if_mtd_pci.c
+++ b/sys/dev/pci/if_mtd_pci.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: if_mtd_pci.c,v 1.5 2003/08/19 12:25:52 mickey Exp $ */
+/* $OpenBSD: if_mtd_pci.c,v 1.6 2003/09/25 22:06:00 mickey Exp $ */
/*
- * Copyright (c) 2003 Oleg Safiullin
+ * Copyright (c) 2003 Oleg Safiullin <form@pdp11.org.ru>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -49,20 +49,24 @@
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include <dev/ic/mtd803reg.h>
-#include <dev/ic/mtd803var.h>
+#include <dev/ic/mtd8xxreg.h>
+#include <dev/ic/mtd8xxvar.h>
static int mtd_pci_match(struct device *, void *, void *);
static void mtd_pci_attach(struct device *, struct device *, void *);
+
struct cfattach mtd_pci_ca = {
sizeof(struct mtd_softc), mtd_pci_match, mtd_pci_attach
};
const static struct pci_matchid mtd_pci_devices[] = {
+ { PCI_VENDOR_MYSON, PCI_PRODUCT_MYSON_MTD800 },
{ PCI_VENDOR_MYSON, PCI_PRODUCT_MYSON_MTD803 },
+ { PCI_VENDOR_MYSON, PCI_PRODUCT_MYSON_MTD891 },
};
+
static int
mtd_pci_match(struct device *parent, void *match, void *aux)
{
@@ -70,6 +74,7 @@ mtd_pci_match(struct device *parent, void *match, void *aux)
sizeof(mtd_pci_devices) / sizeof(mtd_pci_devices[0])));
}
+
static void
mtd_pci_attach(struct device *parent, struct device *self, void *aux)
{
@@ -81,13 +86,13 @@ mtd_pci_attach(struct device *parent, struct device *self, void *aux)
#ifndef MTD_USE_IO
if (pci_mapreg_map(pa, MTD_PCI_LOMEM, PCI_MAPREG_TYPE_MEM, 0,
- &sc->bus_tag, &sc->bus_handle, NULL, &iosize, 0)) {
+ &sc->sc_bust, &sc->sc_bush, NULL, &iosize, 0)) {
printf(": can't map mem space\n");
return;
}
#else /* MTD_USE_IO */
if (pci_mapreg_map(pa, MTD_PCI_LOIO, PCI_MAPREG_TYPE_IO, 0,
- &sc->bus_tag, &sc->bus_handle, NULL, &iosize, 0)) {
+ &sc->sc_bust, &sc->sc_bush, NULL, &iosize, 0)) {
printf(": can't map io space\n");
return;
}
@@ -98,22 +103,22 @@ mtd_pci_attach(struct device *parent, struct device *self, void *aux)
*/
if (pci_intr_map(pa, &ih)) {
printf(": couldn't map interrupt\n");
- bus_space_unmap(sc->bus_tag, sc->bus_handle, iosize);
+ bus_space_unmap(sc->sc_bust, sc->sc_bush, iosize);
return;
}
intrstr = pci_intr_string(pa->pa_pc, ih);
- if (pci_intr_establish(pa->pa_pc, ih, IPL_NET, mtd_irq_h, sc,
+ if (pci_intr_establish(pa->pa_pc, ih, IPL_NET, mtd_intr, sc,
self->dv_xname) == NULL) {
printf(": couldn't establish interrupt");
if (intrstr != NULL)
printf(" at %s", intrstr);
printf("\n");
- bus_space_unmap(sc->bus_tag, sc->bus_handle, iosize);
+ bus_space_unmap(sc->sc_bust, sc->sc_bush, iosize);
return;
}
printf(": %s", intrstr);
- sc->dma_tag = pa->pa_dmat;
- mtd_config(sc);
+ sc->sc_dmat = pa->pa_dmat;
+ mtd_attach(sc);
}