Home | History | Annotate | Line # | Download | only in dev
if_smap.c revision 1.17.4.2
      1  1.17.4.2  tls /*	$NetBSD: if_smap.c,v 1.17.4.2 2014/08/20 00:03:17 tls Exp $	*/
      2  1.17.4.2  tls 
      3  1.17.4.2  tls /*-
      4  1.17.4.2  tls  * Copyright (c) 2001 The NetBSD Foundation, Inc.
      5  1.17.4.2  tls  * All rights reserved.
      6  1.17.4.2  tls  *
      7  1.17.4.2  tls  * This code is derived from software contributed to The NetBSD Foundation
      8  1.17.4.2  tls  * by UCHIYAMA Yasushi.
      9  1.17.4.2  tls  *
     10  1.17.4.2  tls  * Redistribution and use in source and binary forms, with or without
     11  1.17.4.2  tls  * modification, are permitted provided that the following conditions
     12  1.17.4.2  tls  * are met:
     13  1.17.4.2  tls  * 1. Redistributions of source code must retain the above copyright
     14  1.17.4.2  tls  *    notice, this list of conditions and the following disclaimer.
     15  1.17.4.2  tls  * 2. Redistributions in binary form must reproduce the above copyright
     16  1.17.4.2  tls  *    notice, this list of conditions and the following disclaimer in the
     17  1.17.4.2  tls  *    documentation and/or other materials provided with the distribution.
     18  1.17.4.2  tls  *
     19  1.17.4.2  tls  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     20  1.17.4.2  tls  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     21  1.17.4.2  tls  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     22  1.17.4.2  tls  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     23  1.17.4.2  tls  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     24  1.17.4.2  tls  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     25  1.17.4.2  tls  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     26  1.17.4.2  tls  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     27  1.17.4.2  tls  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     28  1.17.4.2  tls  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     29  1.17.4.2  tls  * POSSIBILITY OF SUCH DAMAGE.
     30  1.17.4.2  tls  */
     31  1.17.4.2  tls 
     32  1.17.4.2  tls #include <sys/cdefs.h>
     33  1.17.4.2  tls __KERNEL_RCSID(0, "$NetBSD: if_smap.c,v 1.17.4.2 2014/08/20 00:03:17 tls Exp $");
     34  1.17.4.2  tls 
     35  1.17.4.2  tls #include "debug_playstation2.h"
     36  1.17.4.2  tls 
     37  1.17.4.2  tls #include "rnd.h"
     38  1.17.4.2  tls 
     39  1.17.4.2  tls #include <sys/param.h>
     40  1.17.4.2  tls #include <sys/systm.h>
     41  1.17.4.2  tls 
     42  1.17.4.2  tls #include <sys/syslog.h>
     43  1.17.4.2  tls #include <sys/mbuf.h>
     44  1.17.4.2  tls #include <sys/ioctl.h>
     45  1.17.4.2  tls #include <sys/socket.h>
     46  1.17.4.2  tls 
     47  1.17.4.2  tls #include <playstation2/ee/eevar.h>
     48  1.17.4.2  tls 
     49  1.17.4.2  tls #if NRND > 0
     50  1.17.4.2  tls #include <sys/rnd.h>
     51  1.17.4.2  tls #endif
     52  1.17.4.2  tls 
     53  1.17.4.2  tls #include <net/if.h>
     54  1.17.4.2  tls #include <net/if_dl.h>
     55  1.17.4.2  tls #include <net/if_types.h>
     56  1.17.4.2  tls 
     57  1.17.4.2  tls #include <net/if_ether.h>
     58  1.17.4.2  tls #include <net/if_media.h>
     59  1.17.4.2  tls 
     60  1.17.4.2  tls #include <dev/mii/mii.h>
     61  1.17.4.2  tls #include <dev/mii/miivar.h>
     62  1.17.4.2  tls 
     63  1.17.4.2  tls #include <netinet/in.h>
     64  1.17.4.2  tls #include <netinet/in_systm.h>
     65  1.17.4.2  tls #include <netinet/in_var.h>
     66  1.17.4.2  tls #include <netinet/ip.h>
     67  1.17.4.2  tls #include <netinet/if_inarp.h>
     68  1.17.4.2  tls 
     69  1.17.4.2  tls #include <net/bpf.h>
     70  1.17.4.2  tls #include <net/bpfdesc.h>
     71  1.17.4.2  tls 
     72  1.17.4.2  tls #include <playstation2/dev/spdvar.h>
     73  1.17.4.2  tls #include <playstation2/dev/spdreg.h>
     74  1.17.4.2  tls #include <playstation2/dev/emac3var.h>
     75  1.17.4.2  tls #include <playstation2/dev/if_smapreg.h>
     76  1.17.4.2  tls 
     77  1.17.4.2  tls #ifdef SMAP_DEBUG
     78  1.17.4.2  tls #include <playstation2/ee/gsvar.h>
     79  1.17.4.2  tls int	smap_debug = 0;
     80  1.17.4.2  tls #define	DPRINTF(fmt, args...)						\
     81  1.17.4.2  tls 	if (smap_debug)							\
     82  1.17.4.2  tls 		printf("%s: " fmt, __func__ , ##args)
     83  1.17.4.2  tls #define	DPRINTFN(n, arg)						\
     84  1.17.4.2  tls 	if (smap_debug > (n))						\
     85  1.17.4.2  tls 		printf("%s: " fmt, __func__ , ##args)
     86  1.17.4.2  tls #define STATIC
     87  1.17.4.2  tls struct smap_softc *__sc;
     88  1.17.4.2  tls void __smap_status(int);
     89  1.17.4.2  tls void __smap_lock_check(const char *, int);
     90  1.17.4.2  tls #define FUNC_ENTER()	__smap_lock_check(__func__, 1)
     91  1.17.4.2  tls #define FUNC_EXIT()	__smap_lock_check(__func__, 0)
     92  1.17.4.2  tls #else
     93  1.17.4.2  tls #define	DPRINTF(arg...)		((void)0)
     94  1.17.4.2  tls #define DPRINTFN(n, arg...)	((void)0)
     95  1.17.4.2  tls #define STATIC			static
     96  1.17.4.2  tls #define FUNC_ENTER()		((void)0)
     97  1.17.4.2  tls #define FUNC_EXIT()		((void)0)
     98  1.17.4.2  tls #endif
     99  1.17.4.2  tls 
    100  1.17.4.2  tls struct smap_softc {
    101  1.17.4.2  tls 	struct emac3_softc emac3;
    102  1.17.4.2  tls 	struct ethercom ethercom;
    103  1.17.4.2  tls 
    104  1.17.4.2  tls 	u_int32_t *tx_buf;
    105  1.17.4.2  tls 	u_int32_t *rx_buf;
    106  1.17.4.2  tls 	struct smap_desc *tx_desc;
    107  1.17.4.2  tls 	struct smap_desc *rx_desc;
    108  1.17.4.2  tls 
    109  1.17.4.2  tls #define	SMAP_FIFO_ALIGN		4
    110  1.17.4.2  tls 	int tx_buf_freesize;	/* buffer usage */
    111  1.17.4.2  tls 	int tx_desc_cnt;	/* descriptor usage */
    112  1.17.4.2  tls 	u_int16_t tx_fifo_ptr;
    113  1.17.4.2  tls 	int tx_done_index, tx_start_index;
    114  1.17.4.2  tls 	int rx_done_index;
    115  1.17.4.2  tls 
    116  1.17.4.2  tls #if NRND > 0
    117  1.17.4.2  tls 	rndsource_element_t rnd_source;
    118  1.17.4.2  tls #endif
    119  1.17.4.2  tls };
    120  1.17.4.2  tls 
    121  1.17.4.2  tls #define DEVNAME		(sc->emac3.dev.dv_xname)
    122  1.17.4.2  tls #define ROUND4(x)	(((x) + 3) & ~3)
    123  1.17.4.2  tls #define ROUND16(x)	(((x) + 15) & ~15)
    124  1.17.4.2  tls 
    125  1.17.4.2  tls STATIC int smap_match(struct device *, struct cfdata *, void *);
    126  1.17.4.2  tls STATIC void smap_attach(struct device *, struct device *, void *);
    127  1.17.4.2  tls 
    128  1.17.4.2  tls CFATTACH_DECL(smap, sizeof (struct smap_softc),
    129  1.17.4.2  tls     smap_match, smap_attach, NULL, NULL);
    130  1.17.4.2  tls 
    131  1.17.4.2  tls STATIC int smap_intr(void *);
    132  1.17.4.2  tls STATIC void smap_rxeof(void *);
    133  1.17.4.2  tls STATIC void smap_txeof(void *);
    134  1.17.4.2  tls STATIC void smap_start(struct ifnet *);
    135  1.17.4.2  tls STATIC void smap_watchdog(struct ifnet *);
    136  1.17.4.2  tls STATIC int smap_ioctl(struct ifnet *, u_long, void *);
    137  1.17.4.2  tls STATIC int smap_init(struct ifnet *);
    138  1.17.4.2  tls STATIC void smap_stop(struct ifnet *, int);
    139  1.17.4.2  tls 
    140  1.17.4.2  tls STATIC int smap_get_eaddr(struct smap_softc *, u_int8_t *);
    141  1.17.4.2  tls STATIC int smap_fifo_init(struct smap_softc *);
    142  1.17.4.2  tls STATIC int smap_fifo_reset(bus_addr_t);
    143  1.17.4.2  tls STATIC void smap_desc_init(struct smap_softc *);
    144  1.17.4.2  tls 
    145  1.17.4.2  tls int
    146  1.17.4.2  tls smap_match(struct device *parent, struct cfdata *cf, void *aux)
    147  1.17.4.2  tls {
    148  1.17.4.2  tls 	struct spd_attach_args *spa = aux;
    149  1.17.4.2  tls 
    150  1.17.4.2  tls 	if (spa->spa_slot != SPD_NIC)
    151  1.17.4.2  tls 		return (0);
    152  1.17.4.2  tls 
    153  1.17.4.2  tls 	return (1);
    154  1.17.4.2  tls }
    155  1.17.4.2  tls 
    156  1.17.4.2  tls void
    157  1.17.4.2  tls smap_attach(struct device *parent, struct device *self, void *aux)
    158  1.17.4.2  tls {
    159  1.17.4.2  tls 	struct spd_attach_args *spa = aux;
    160  1.17.4.2  tls 	struct smap_softc *sc = (void *)self;
    161  1.17.4.2  tls 	struct emac3_softc *emac3 = &sc->emac3;
    162  1.17.4.2  tls 	struct ifnet *ifp = &sc->ethercom.ec_if;
    163  1.17.4.2  tls 	struct mii_data *mii = &emac3->mii;
    164  1.17.4.2  tls 	void *txbuf, *rxbuf;
    165  1.17.4.2  tls 	u_int16_t r;
    166  1.17.4.2  tls 
    167  1.17.4.2  tls #ifdef SMAP_DEBUG
    168  1.17.4.2  tls 	__sc = sc;
    169  1.17.4.2  tls #endif
    170  1.17.4.2  tls 
    171  1.17.4.2  tls 	printf(": %s\n", spa->spa_product_name);
    172  1.17.4.2  tls 
    173  1.17.4.2  tls 	/* SPD EEPROM */
    174  1.17.4.2  tls 	if (smap_get_eaddr(sc, emac3->eaddr) != 0)
    175  1.17.4.2  tls 		return;
    176  1.17.4.2  tls 
    177  1.17.4.2  tls 	printf("%s: Ethernet address %s\n", DEVNAME,
    178  1.17.4.2  tls 	    ether_sprintf(emac3->eaddr));
    179  1.17.4.2  tls 
    180  1.17.4.2  tls 	/* disable interrupts */
    181  1.17.4.2  tls 	r = _reg_read_2(SPD_INTR_ENABLE_REG16);
    182  1.17.4.2  tls 	r &= ~(SPD_INTR_RXEND | SPD_INTR_TXEND | SPD_INTR_RXDNV |
    183  1.17.4.2  tls 	    SPD_INTR_EMAC3);
    184  1.17.4.2  tls 	_reg_write_2(SPD_INTR_ENABLE_REG16, r);
    185  1.17.4.2  tls 	emac3_intr_disable();
    186  1.17.4.2  tls 
    187  1.17.4.2  tls 	/* clear pending interrupts */
    188  1.17.4.2  tls 	_reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND |
    189  1.17.4.2  tls 	    SPD_INTR_RXDNV);
    190  1.17.4.2  tls 	emac3_intr_clear();
    191  1.17.4.2  tls 
    192  1.17.4.2  tls 	/* buffer descriptor mode */
    193  1.17.4.2  tls 	_reg_write_1(SMAP_DESC_MODE_REG8, 0);
    194  1.17.4.2  tls 
    195  1.17.4.2  tls 	if (smap_fifo_init(sc) != 0)
    196  1.17.4.2  tls 		return;
    197  1.17.4.2  tls 
    198  1.17.4.2  tls 	if (emac3_init(&sc->emac3) != 0)
    199  1.17.4.2  tls 		return;
    200  1.17.4.2  tls 	emac3_intr_disable();
    201  1.17.4.2  tls 	emac3_disable();
    202  1.17.4.2  tls 
    203  1.17.4.2  tls 	smap_desc_init(sc);
    204  1.17.4.2  tls 
    205  1.17.4.2  tls 	/* allocate temporary buffer */
    206  1.17.4.2  tls 	txbuf = malloc(ETHER_MAX_LEN - ETHER_CRC_LEN + SMAP_FIFO_ALIGN + 16,
    207  1.17.4.2  tls 	    M_DEVBUF, M_NOWAIT);
    208  1.17.4.2  tls 	if (txbuf == NULL) {
    209  1.17.4.2  tls 		printf("%s: no memory.\n", DEVNAME);
    210  1.17.4.2  tls 		return;
    211  1.17.4.2  tls 	}
    212  1.17.4.2  tls 
    213  1.17.4.2  tls 	rxbuf = malloc(ETHER_MAX_LEN + SMAP_FIFO_ALIGN + 16,
    214  1.17.4.2  tls 	    M_DEVBUF, M_NOWAIT);
    215  1.17.4.2  tls 	if (rxbuf == NULL) {
    216  1.17.4.2  tls 		printf("%s: no memory.\n", DEVNAME);
    217  1.17.4.2  tls 		free(txbuf, M_DEVBUF);
    218  1.17.4.2  tls 		return;
    219  1.17.4.2  tls 	}
    220  1.17.4.2  tls 
    221  1.17.4.2  tls 	sc->tx_buf = (u_int32_t *)ROUND16((vaddr_t)txbuf);
    222  1.17.4.2  tls 	sc->rx_buf = (u_int32_t *)ROUND16((vaddr_t)rxbuf);
    223  1.17.4.2  tls 
    224  1.17.4.2  tls 	/*
    225  1.17.4.2  tls 	 * setup MI layer
    226  1.17.4.2  tls 	 */
    227  1.17.4.2  tls 	strcpy(ifp->if_xname, DEVNAME);
    228  1.17.4.2  tls 	ifp->if_softc	= sc;
    229  1.17.4.2  tls 	ifp->if_start	= smap_start;
    230  1.17.4.2  tls 	ifp->if_ioctl	= smap_ioctl;
    231  1.17.4.2  tls 	ifp->if_init	= smap_init;
    232  1.17.4.2  tls 	ifp->if_stop	= smap_stop;
    233  1.17.4.2  tls 	ifp->if_watchdog= smap_watchdog;
    234  1.17.4.2  tls 	ifp->if_flags	= IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS |
    235  1.17.4.2  tls 	    IFF_MULTICAST;
    236  1.17.4.2  tls 	IFQ_SET_READY(&ifp->if_snd);
    237  1.17.4.2  tls 
    238  1.17.4.2  tls 	/* ifmedia setup. */
    239  1.17.4.2  tls 	mii->mii_ifp		= ifp;
    240  1.17.4.2  tls 	mii->mii_readreg	= emac3_phy_readreg;
    241  1.17.4.2  tls 	mii->mii_writereg	= emac3_phy_writereg;
    242  1.17.4.2  tls 	mii->mii_statchg	= emac3_phy_statchg;
    243  1.17.4.2  tls 	sc->ethercom.ec_mii = mii;
    244  1.17.4.2  tls 	ifmedia_init(&mii->mii_media, 0, ether_mediachange, ether_mediastatus);
    245  1.17.4.2  tls 	mii_attach(&emac3->dev, mii, 0xffffffff, MII_PHY_ANY,
    246  1.17.4.2  tls 	    MII_OFFSET_ANY, 0);
    247  1.17.4.2  tls 
    248  1.17.4.2  tls 	/* Choose a default media. */
    249  1.17.4.2  tls 	if (LIST_FIRST(&mii->mii_phys) == NULL) {
    250  1.17.4.2  tls 		ifmedia_add(&mii->mii_media, IFM_ETHER|IFM_NONE, 0, NULL);
    251  1.17.4.2  tls 		ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_NONE);
    252  1.17.4.2  tls 	} else {
    253  1.17.4.2  tls 		ifmedia_set(&mii->mii_media, IFM_ETHER|IFM_AUTO);
    254  1.17.4.2  tls 	}
    255  1.17.4.2  tls 
    256  1.17.4.2  tls 	if_attach(ifp);
    257  1.17.4.2  tls 	ether_ifattach(ifp, emac3->eaddr);
    258  1.17.4.2  tls 
    259  1.17.4.2  tls 	spd_intr_establish(SPD_NIC, smap_intr, sc);
    260  1.17.4.2  tls 
    261  1.17.4.2  tls #if NRND > 0
    262  1.17.4.2  tls 	rnd_attach_source(&sc->rnd_source, DEVNAME,
    263  1.17.4.2  tls 	    RND_TYPE_NET, RND_FLAG_DEFAULT);
    264  1.17.4.2  tls #endif
    265  1.17.4.2  tls }
    266  1.17.4.2  tls 
    267  1.17.4.2  tls int
    268  1.17.4.2  tls smap_ioctl(struct ifnet *ifp, u_long command, void *data)
    269  1.17.4.2  tls {
    270  1.17.4.2  tls 	struct smap_softc *sc = ifp->if_softc;
    271  1.17.4.2  tls 	struct ifreq *ifr = (struct ifreq *) data;
    272  1.17.4.2  tls 	int error, s;
    273  1.17.4.2  tls 
    274  1.17.4.2  tls 	s = splnet();
    275  1.17.4.2  tls 
    276  1.17.4.2  tls 	error = ether_ioctl(ifp, command, data);
    277  1.17.4.2  tls 
    278  1.17.4.2  tls 	if (error == ENETRESET) {
    279  1.17.4.2  tls 		if (ifp->if_flags & IFF_RUNNING)
    280  1.17.4.2  tls 			emac3_setmulti(&sc->emac3, &sc->ethercom);
    281  1.17.4.2  tls 		error = 0;
    282  1.17.4.2  tls 	}
    283  1.17.4.2  tls 
    284  1.17.4.2  tls 	splx(s);
    285  1.17.4.2  tls 
    286  1.17.4.2  tls 	return (error);
    287  1.17.4.2  tls }
    288  1.17.4.2  tls 
    289  1.17.4.2  tls int
    290  1.17.4.2  tls smap_intr(void *arg)
    291  1.17.4.2  tls {
    292  1.17.4.2  tls 	struct smap_softc *sc = arg;
    293  1.17.4.2  tls 	struct ifnet *ifp;
    294  1.17.4.2  tls 	u_int16_t cause, disable, r;
    295  1.17.4.2  tls 
    296  1.17.4.2  tls 	cause = _reg_read_2(SPD_INTR_STATUS_REG16) &
    297  1.17.4.2  tls 	    _reg_read_2(SPD_INTR_ENABLE_REG16);
    298  1.17.4.2  tls 
    299  1.17.4.2  tls 	disable = cause & (SPD_INTR_RXDNV | SPD_INTR_TXDNV);
    300  1.17.4.2  tls 	if (disable) {
    301  1.17.4.2  tls 		r = _reg_read_2(SPD_INTR_ENABLE_REG16);
    302  1.17.4.2  tls 		r &= ~disable;
    303  1.17.4.2  tls 		_reg_write_2(SPD_INTR_ENABLE_REG16, r);
    304  1.17.4.2  tls 
    305  1.17.4.2  tls 		printf("%s: invalid descriptor. (%c%c)\n", DEVNAME,
    306  1.17.4.2  tls 		    disable & SPD_INTR_RXDNV ? 'R' : '_',
    307  1.17.4.2  tls 		    disable & SPD_INTR_TXDNV ? 'T' : '_');
    308  1.17.4.2  tls 
    309  1.17.4.2  tls 		if (disable & SPD_INTR_RXDNV)
    310  1.17.4.2  tls 			smap_rxeof(arg);
    311  1.17.4.2  tls 
    312  1.17.4.2  tls 		_reg_write_2(SPD_INTR_CLEAR_REG16, disable);
    313  1.17.4.2  tls 	}
    314  1.17.4.2  tls 
    315  1.17.4.2  tls 	if (cause & SPD_INTR_TXEND) {
    316  1.17.4.2  tls 		_reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_TXEND);
    317  1.17.4.2  tls 		if (_reg_read_1(SMAP_RXFIFO_FRAME_REG8) > 0)
    318  1.17.4.2  tls 			cause |= SPD_INTR_RXEND;
    319  1.17.4.2  tls 		smap_txeof(arg);
    320  1.17.4.2  tls 	}
    321  1.17.4.2  tls 
    322  1.17.4.2  tls 	if (cause & SPD_INTR_RXEND) {
    323  1.17.4.2  tls 		_reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND);
    324  1.17.4.2  tls 		smap_rxeof(arg);
    325  1.17.4.2  tls 		if (sc->tx_desc_cnt > 0 &&
    326  1.17.4.2  tls 		    sc->tx_desc_cnt > _reg_read_1(SMAP_TXFIFO_FRAME_REG8))
    327  1.17.4.2  tls 			smap_txeof(arg);
    328  1.17.4.2  tls 	}
    329  1.17.4.2  tls 
    330  1.17.4.2  tls 	if (cause & SPD_INTR_EMAC3)
    331  1.17.4.2  tls 		emac3_intr(arg);
    332  1.17.4.2  tls 
    333  1.17.4.2  tls 	/* if transmission is pending, start here */
    334  1.17.4.2  tls 	ifp = &sc->ethercom.ec_if;
    335  1.17.4.2  tls 	if (IFQ_IS_EMPTY(&ifp->if_snd) == 0)
    336  1.17.4.2  tls 		smap_start(ifp);
    337  1.17.4.2  tls #if NRND > 0
    338  1.17.4.2  tls 	rnd_add_uint32(&sc->rnd_source, cause | sc->tx_fifo_ptr << 16);
    339  1.17.4.2  tls #endif
    340  1.17.4.2  tls 
    341  1.17.4.2  tls 	return (1);
    342  1.17.4.2  tls }
    343  1.17.4.2  tls 
    344  1.17.4.2  tls void
    345  1.17.4.2  tls smap_rxeof(void *arg)
    346  1.17.4.2  tls {
    347  1.17.4.2  tls 	struct smap_softc *sc = arg;
    348  1.17.4.2  tls 	struct smap_desc *d;
    349  1.17.4.2  tls 	struct ifnet *ifp = &sc->ethercom.ec_if;
    350  1.17.4.2  tls 	struct mbuf *m;
    351  1.17.4.2  tls 	u_int16_t r16, stat;
    352  1.17.4.2  tls 	u_int32_t *p;
    353  1.17.4.2  tls 	int i, j, sz, rxsz, cnt;
    354  1.17.4.2  tls 
    355  1.17.4.2  tls 	FUNC_ENTER();
    356  1.17.4.2  tls 
    357  1.17.4.2  tls 	i = sc->rx_done_index;
    358  1.17.4.2  tls 
    359  1.17.4.2  tls 	for (cnt = 0;; cnt++, i = (i + 1) & 0x3f) {
    360  1.17.4.2  tls 		m = NULL;
    361  1.17.4.2  tls 		d = &sc->rx_desc[i];
    362  1.17.4.2  tls 		stat = d->stat;
    363  1.17.4.2  tls 
    364  1.17.4.2  tls 		if ((stat & SMAP_RXDESC_EMPTY) != 0) {
    365  1.17.4.2  tls 			break;
    366  1.17.4.2  tls 		} else if (stat & 0x7fff) {
    367  1.17.4.2  tls 			ifp->if_ierrors++;
    368  1.17.4.2  tls 			goto next_packet;
    369  1.17.4.2  tls 		}
    370  1.17.4.2  tls 
    371  1.17.4.2  tls 		sz = d->sz;
    372  1.17.4.2  tls 		rxsz = ROUND4(sz);
    373  1.17.4.2  tls 
    374  1.17.4.2  tls 		KDASSERT(sz >= ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN);
    375  1.17.4.2  tls 		KDASSERT(sz <= ETHER_MAX_LEN);
    376  1.17.4.2  tls 
    377  1.17.4.2  tls 		/* load data from FIFO */
    378  1.17.4.2  tls 		_reg_write_2(SMAP_RXFIFO_PTR_REG16, d->ptr & 0x3ffc);
    379  1.17.4.2  tls 		p = sc->rx_buf;
    380  1.17.4.2  tls 		for (j = 0; j < rxsz; j += sizeof(u_int32_t)) {
    381  1.17.4.2  tls 			*p++ = _reg_read_4(SMAP_RXFIFO_DATA_REG);
    382  1.17.4.2  tls 		}
    383  1.17.4.2  tls 
    384  1.17.4.2  tls 		/* put to mbuf */
    385  1.17.4.2  tls 		MGETHDR(m, M_DONTWAIT, MT_DATA);
    386  1.17.4.2  tls 		if (m == NULL) {
    387  1.17.4.2  tls 			printf("%s: unable to allocate Rx mbuf\n", DEVNAME);
    388  1.17.4.2  tls 			ifp->if_ierrors++;
    389  1.17.4.2  tls 			goto next_packet;
    390  1.17.4.2  tls 		}
    391  1.17.4.2  tls 
    392  1.17.4.2  tls 		if (sz > (MHLEN - 2)) {
    393  1.17.4.2  tls 			MCLGET(m, M_DONTWAIT);
    394  1.17.4.2  tls 			if ((m->m_flags & M_EXT) == 0) {
    395  1.17.4.2  tls 				printf("%s: unable to allocate Rx cluster\n",
    396  1.17.4.2  tls 				    DEVNAME);
    397  1.17.4.2  tls 				m_freem(m);
    398  1.17.4.2  tls 				m = NULL;
    399  1.17.4.2  tls 				ifp->if_ierrors++;
    400  1.17.4.2  tls 				goto next_packet;
    401  1.17.4.2  tls 			}
    402  1.17.4.2  tls 		}
    403  1.17.4.2  tls 
    404  1.17.4.2  tls 		m->m_data += 2; /* for alignment */
    405  1.17.4.2  tls 		m->m_pkthdr.rcvif = ifp;
    406  1.17.4.2  tls 		m->m_pkthdr.len = m->m_len = sz;
    407  1.17.4.2  tls 		memcpy(mtod(m, void *), (void *)sc->rx_buf, sz);
    408  1.17.4.2  tls 
    409  1.17.4.2  tls 	next_packet:
    410  1.17.4.2  tls 		ifp->if_ipackets++;
    411  1.17.4.2  tls 
    412  1.17.4.2  tls 		_reg_write_1(SMAP_RXFIFO_FRAME_DEC_REG8, 1);
    413  1.17.4.2  tls 
    414  1.17.4.2  tls 		/* free descriptor */
    415  1.17.4.2  tls 		d->sz	= 0;
    416  1.17.4.2  tls 		d->ptr	= 0;
    417  1.17.4.2  tls 		d->stat	= SMAP_RXDESC_EMPTY;
    418  1.17.4.2  tls 		_wbflush();
    419  1.17.4.2  tls 
    420  1.17.4.2  tls 		if (m != NULL) {
    421  1.17.4.2  tls 			if (ifp->if_bpf)
    422  1.17.4.2  tls 				bpf_mtap(ifp->if_bpf, m);
    423  1.17.4.2  tls 			(*ifp->if_input)(ifp, m);
    424  1.17.4.2  tls 		}
    425  1.17.4.2  tls 	}
    426  1.17.4.2  tls 	sc->rx_done_index = i;
    427  1.17.4.2  tls 
    428  1.17.4.2  tls 	r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
    429  1.17.4.2  tls 	if (((r16 & SPD_INTR_RXDNV) == 0) && cnt > 0) {
    430  1.17.4.2  tls 		r16  |= SPD_INTR_RXDNV;
    431  1.17.4.2  tls 		_reg_write_2(SPD_INTR_ENABLE_REG16, r16);
    432  1.17.4.2  tls 	}
    433  1.17.4.2  tls 
    434  1.17.4.2  tls 	FUNC_EXIT();
    435  1.17.4.2  tls }
    436  1.17.4.2  tls 
    437  1.17.4.2  tls void
    438  1.17.4.2  tls smap_txeof(void *arg)
    439  1.17.4.2  tls {
    440  1.17.4.2  tls 	struct smap_softc *sc = arg;
    441  1.17.4.2  tls 	struct ifnet *ifp = &sc->ethercom.ec_if;
    442  1.17.4.2  tls 	struct smap_desc *d;
    443  1.17.4.2  tls 	int i;
    444  1.17.4.2  tls 
    445  1.17.4.2  tls 	FUNC_ENTER();
    446  1.17.4.2  tls 
    447  1.17.4.2  tls 	/* clear the timeout timer. */
    448  1.17.4.2  tls 	ifp->if_timer = 0;
    449  1.17.4.2  tls 
    450  1.17.4.2  tls 	/* garbage collect */
    451  1.17.4.2  tls 	for (i = sc->tx_done_index;; i = (i + 1) & 0x3f) {
    452  1.17.4.2  tls 		u_int16_t stat;
    453  1.17.4.2  tls 
    454  1.17.4.2  tls 		d = &sc->tx_desc[i];
    455  1.17.4.2  tls 		stat = d->stat;
    456  1.17.4.2  tls 		if (stat & SMAP_TXDESC_READY) {
    457  1.17.4.2  tls 			/* all descriptor processed. */
    458  1.17.4.2  tls 			break;
    459  1.17.4.2  tls 		} else if (stat & 0x7fff) {
    460  1.17.4.2  tls 			if (stat & (SMAP_TXDESC_ECOLL | SMAP_TXDESC_LCOLL |
    461  1.17.4.2  tls 			    SMAP_TXDESC_MCOLL | SMAP_TXDESC_SCOLL))
    462  1.17.4.2  tls 				ifp->if_collisions++;
    463  1.17.4.2  tls 			else
    464  1.17.4.2  tls 				ifp->if_oerrors++;
    465  1.17.4.2  tls 		} else {
    466  1.17.4.2  tls 			ifp->if_opackets++;
    467  1.17.4.2  tls 		}
    468  1.17.4.2  tls 
    469  1.17.4.2  tls 		if (sc->tx_desc_cnt == 0)
    470  1.17.4.2  tls 			break;
    471  1.17.4.2  tls 
    472  1.17.4.2  tls 		sc->tx_buf_freesize += ROUND4(d->sz);
    473  1.17.4.2  tls 		sc->tx_desc_cnt--;
    474  1.17.4.2  tls 
    475  1.17.4.2  tls 		d->sz = 0;
    476  1.17.4.2  tls 		d->ptr = 0;
    477  1.17.4.2  tls 		d->stat = 0;
    478  1.17.4.2  tls 		_wbflush();
    479  1.17.4.2  tls 	}
    480  1.17.4.2  tls 	sc->tx_done_index = i;
    481  1.17.4.2  tls 
    482  1.17.4.2  tls 	/* OK to start transmit */
    483  1.17.4.2  tls 	ifp->if_flags &= ~IFF_OACTIVE;
    484  1.17.4.2  tls 
    485  1.17.4.2  tls 	FUNC_EXIT();
    486  1.17.4.2  tls }
    487  1.17.4.2  tls 
    488  1.17.4.2  tls void
    489  1.17.4.2  tls smap_start(struct ifnet *ifp)
    490  1.17.4.2  tls {
    491  1.17.4.2  tls 	struct smap_softc *sc = ifp->if_softc;
    492  1.17.4.2  tls 	struct smap_desc *d;
    493  1.17.4.2  tls 	struct mbuf *m0, *m;
    494  1.17.4.2  tls 	u_int8_t *p, *q;
    495  1.17.4.2  tls 	u_int32_t *r;
    496  1.17.4.2  tls 	int i, sz, pktsz;
    497  1.17.4.2  tls 	u_int16_t fifop;
    498  1.17.4.2  tls 	u_int16_t r16;
    499  1.17.4.2  tls 
    500  1.17.4.2  tls 	KDASSERT(ifp->if_flags & IFF_RUNNING);
    501  1.17.4.2  tls 	FUNC_ENTER();
    502  1.17.4.2  tls 
    503  1.17.4.2  tls 	while (1) {
    504  1.17.4.2  tls 		IFQ_POLL(&ifp->if_snd, m0);
    505  1.17.4.2  tls 		if (m0 == NULL)
    506  1.17.4.2  tls 			goto end;
    507  1.17.4.2  tls 
    508  1.17.4.2  tls 		pktsz = m0->m_pkthdr.len;
    509  1.17.4.2  tls 		KDASSERT(pktsz <= ETHER_MAX_LEN - ETHER_CRC_LEN);
    510  1.17.4.2  tls 		sz = ROUND4(pktsz);
    511  1.17.4.2  tls 
    512  1.17.4.2  tls 		if (sz > sc->tx_buf_freesize ||
    513  1.17.4.2  tls 		    sc->tx_desc_cnt >= SMAP_DESC_MAX ||
    514  1.17.4.2  tls 		    emac3_tx_done() != 0) {
    515  1.17.4.2  tls 			ifp->if_flags |= IFF_OACTIVE;
    516  1.17.4.2  tls 			goto end;
    517  1.17.4.2  tls 		}
    518  1.17.4.2  tls 
    519  1.17.4.2  tls 		IFQ_DEQUEUE(&ifp->if_snd, m0);
    520  1.17.4.2  tls 		KDASSERT(m0 != NULL);
    521  1.17.4.2  tls 		if (ifp->if_bpf)
    522  1.17.4.2  tls 			bpf_mtap(ifp->if_bpf, m0);
    523  1.17.4.2  tls 
    524  1.17.4.2  tls 		p = (u_int8_t *)sc->tx_buf;
    525  1.17.4.2  tls 		q = p + sz;
    526  1.17.4.2  tls 		/* copy to temporary buffer area */
    527  1.17.4.2  tls 		for (m = m0; m != 0; m = m->m_next) {
    528  1.17.4.2  tls 			memcpy(p, mtod(m, void *), m->m_len);
    529  1.17.4.2  tls 			p += m->m_len;
    530  1.17.4.2  tls 		}
    531  1.17.4.2  tls 		m_freem(m0);
    532  1.17.4.2  tls 
    533  1.17.4.2  tls 		/* zero padding area */
    534  1.17.4.2  tls 		for (; p < q; p++)
    535  1.17.4.2  tls 			*p = 0;
    536  1.17.4.2  tls 
    537  1.17.4.2  tls 		/* put to FIFO */
    538  1.17.4.2  tls 		fifop = sc->tx_fifo_ptr;
    539  1.17.4.2  tls 		KDASSERT((fifop & 3) == 0);
    540  1.17.4.2  tls 		_reg_write_2(SMAP_TXFIFO_PTR_REG16, fifop);
    541  1.17.4.2  tls 		sc->tx_fifo_ptr = (fifop + sz) & 0xfff;
    542  1.17.4.2  tls 
    543  1.17.4.2  tls 		r = sc->tx_buf;
    544  1.17.4.2  tls 		for (i = 0; i < sz; i += sizeof(u_int32_t))
    545  1.17.4.2  tls 			*(volatile u_int32_t *)SMAP_TXFIFO_DATA_REG = *r++;
    546  1.17.4.2  tls 		_wbflush();
    547  1.17.4.2  tls 
    548  1.17.4.2  tls 		/* put FIFO to EMAC3 */
    549  1.17.4.2  tls 		d = &sc->tx_desc[sc->tx_start_index];
    550  1.17.4.2  tls 		KDASSERT((d->stat & SMAP_TXDESC_READY) == 0);
    551  1.17.4.2  tls 
    552  1.17.4.2  tls 		d->sz = pktsz;
    553  1.17.4.2  tls 		d->ptr = fifop + SMAP_TXBUF_BASE;
    554  1.17.4.2  tls 		d->stat = SMAP_TXDESC_READY | SMAP_TXDESC_GENFCS |
    555  1.17.4.2  tls 		    SMAP_TXDESC_GENPAD;
    556  1.17.4.2  tls 		_wbflush();
    557  1.17.4.2  tls 
    558  1.17.4.2  tls 		sc->tx_buf_freesize -= sz;
    559  1.17.4.2  tls 		sc->tx_desc_cnt++;
    560  1.17.4.2  tls 		sc->tx_start_index = (sc->tx_start_index + 1) & 0x3f;
    561  1.17.4.2  tls 		_reg_write_1(SMAP_TXFIFO_FRAME_INC_REG8, 1);
    562  1.17.4.2  tls 
    563  1.17.4.2  tls 		emac3_tx_kick();
    564  1.17.4.2  tls 		r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
    565  1.17.4.2  tls 		if ((r16 & SPD_INTR_TXDNV) == 0) {
    566  1.17.4.2  tls 			r16 |= SPD_INTR_TXDNV;
    567  1.17.4.2  tls 			_reg_write_2(SPD_INTR_ENABLE_REG16, r16);
    568  1.17.4.2  tls 		}
    569  1.17.4.2  tls 	}
    570  1.17.4.2  tls  end:
    571  1.17.4.2  tls 	/* set watchdog timer */
    572  1.17.4.2  tls 	ifp->if_timer = 5;
    573  1.17.4.2  tls 
    574  1.17.4.2  tls 	FUNC_EXIT();
    575  1.17.4.2  tls }
    576  1.17.4.2  tls 
    577  1.17.4.2  tls void
    578  1.17.4.2  tls smap_watchdog(struct ifnet *ifp)
    579  1.17.4.2  tls {
    580  1.17.4.2  tls 	struct smap_softc *sc = ifp->if_softc;
    581  1.17.4.2  tls 
    582  1.17.4.2  tls 	printf("%s: watchdog timeout\n",DEVNAME);
    583  1.17.4.2  tls 	sc->ethercom.ec_if.if_oerrors++;
    584  1.17.4.2  tls 
    585  1.17.4.2  tls 	smap_fifo_init(sc);
    586  1.17.4.2  tls 	smap_desc_init(sc);
    587  1.17.4.2  tls 	emac3_reset(&sc->emac3);
    588  1.17.4.2  tls }
    589  1.17.4.2  tls 
    590  1.17.4.2  tls int
    591  1.17.4.2  tls smap_init(struct ifnet *ifp)
    592  1.17.4.2  tls {
    593  1.17.4.2  tls 	struct smap_softc *sc = ifp->if_softc;
    594  1.17.4.2  tls 	u_int16_t r16;
    595  1.17.4.2  tls 	int rc;
    596  1.17.4.2  tls 
    597  1.17.4.2  tls 	smap_fifo_init(sc);
    598  1.17.4.2  tls 	emac3_reset(&sc->emac3);
    599  1.17.4.2  tls 	smap_desc_init(sc);
    600  1.17.4.2  tls 
    601  1.17.4.2  tls 	_reg_write_2(SPD_INTR_CLEAR_REG16, SPD_INTR_RXEND | SPD_INTR_TXEND |
    602  1.17.4.2  tls 	    SPD_INTR_RXDNV);
    603  1.17.4.2  tls 	emac3_intr_clear();
    604  1.17.4.2  tls 
    605  1.17.4.2  tls 	r16 = _reg_read_2(SPD_INTR_ENABLE_REG16);
    606  1.17.4.2  tls 	r16 |=  SPD_INTR_EMAC3 | SPD_INTR_RXEND | SPD_INTR_TXEND |
    607  1.17.4.2  tls 	    SPD_INTR_RXDNV;
    608  1.17.4.2  tls 	_reg_write_2(SPD_INTR_ENABLE_REG16, r16);
    609  1.17.4.2  tls 	emac3_intr_enable();
    610  1.17.4.2  tls 
    611  1.17.4.2  tls 	emac3_enable();
    612  1.17.4.2  tls 
    613  1.17.4.2  tls 	/* Program the multicast filter, if necessary. */
    614  1.17.4.2  tls 	emac3_setmulti(&sc->emac3, &sc->ethercom);
    615  1.17.4.2  tls 
    616  1.17.4.2  tls 	/* Set current media. */
    617  1.17.4.2  tls 	if ((rc = mii_mediachg(&sc->emac3.mii)) == ENXIO)
    618  1.17.4.2  tls 		rc = 0;
    619  1.17.4.2  tls 	else if (rc != 0)
    620  1.17.4.2  tls 		return rc;
    621  1.17.4.2  tls 
    622  1.17.4.2  tls 	ifp->if_flags |= IFF_RUNNING;
    623  1.17.4.2  tls 
    624  1.17.4.2  tls 	return (0);
    625  1.17.4.2  tls }
    626  1.17.4.2  tls 
    627  1.17.4.2  tls void
    628  1.17.4.2  tls smap_stop(struct ifnet *ifp, int disable)
    629  1.17.4.2  tls {
    630  1.17.4.2  tls 	struct smap_softc *sc = ifp->if_softc;
    631  1.17.4.2  tls 
    632  1.17.4.2  tls 	mii_down(&sc->emac3.mii);
    633  1.17.4.2  tls 
    634  1.17.4.2  tls 	ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
    635  1.17.4.2  tls 
    636  1.17.4.2  tls 	if (disable)
    637  1.17.4.2  tls 		emac3_disable();
    638  1.17.4.2  tls }
    639  1.17.4.2  tls 
    640  1.17.4.2  tls /*
    641  1.17.4.2  tls  * FIFO
    642  1.17.4.2  tls  */
    643  1.17.4.2  tls int
    644  1.17.4.2  tls smap_fifo_init(struct smap_softc *sc)
    645  1.17.4.2  tls {
    646  1.17.4.2  tls 
    647  1.17.4.2  tls 	if (smap_fifo_reset(SMAP_TXFIFO_CTRL_REG8) != 0)
    648  1.17.4.2  tls 		goto error;
    649  1.17.4.2  tls 
    650  1.17.4.2  tls 	if (smap_fifo_reset(SMAP_RXFIFO_CTRL_REG8) != 0)
    651  1.17.4.2  tls 		goto error;
    652  1.17.4.2  tls 
    653  1.17.4.2  tls 	return (0);
    654  1.17.4.2  tls error:
    655  1.17.4.2  tls 	printf("%s: FIFO reset not complete.\n", DEVNAME);
    656  1.17.4.2  tls 
    657  1.17.4.2  tls 	return (1);
    658  1.17.4.2  tls }
    659  1.17.4.2  tls 
    660  1.17.4.2  tls int
    661  1.17.4.2  tls smap_fifo_reset(bus_addr_t a)
    662  1.17.4.2  tls {
    663  1.17.4.2  tls 	int retry = 10000;
    664  1.17.4.2  tls 
    665  1.17.4.2  tls 	_reg_write_1(a, SMAP_FIFO_RESET);
    666  1.17.4.2  tls 
    667  1.17.4.2  tls 	while ((_reg_read_1(a) & SMAP_FIFO_RESET) && --retry > 0)
    668  1.17.4.2  tls 		;
    669  1.17.4.2  tls 
    670  1.17.4.2  tls 	return (retry == 0);
    671  1.17.4.2  tls }
    672  1.17.4.2  tls 
    673  1.17.4.2  tls /*
    674  1.17.4.2  tls  * Buffer descriptor
    675  1.17.4.2  tls  */
    676  1.17.4.2  tls void
    677  1.17.4.2  tls smap_desc_init(struct smap_softc *sc)
    678  1.17.4.2  tls {
    679  1.17.4.2  tls 	struct smap_desc *d;
    680  1.17.4.2  tls 	int i;
    681  1.17.4.2  tls 
    682  1.17.4.2  tls 	sc->tx_desc = (void *)SMAP_TXDESC_BASE;
    683  1.17.4.2  tls 	sc->rx_desc = (void *)SMAP_RXDESC_BASE;
    684  1.17.4.2  tls 
    685  1.17.4.2  tls 	sc->tx_buf_freesize = SMAP_TXBUF_SIZE;
    686  1.17.4.2  tls 	sc->tx_fifo_ptr = 0;
    687  1.17.4.2  tls 	sc->tx_start_index = 0;
    688  1.17.4.2  tls 	sc->tx_done_index = 0;
    689  1.17.4.2  tls 	sc->rx_done_index = 0;
    690  1.17.4.2  tls 
    691  1.17.4.2  tls 	/* intialize entry */
    692  1.17.4.2  tls 	d = sc->tx_desc;
    693  1.17.4.2  tls 	for (i = 0; i < SMAP_DESC_MAX; i++, d++) {
    694  1.17.4.2  tls 		d->stat = 0;
    695  1.17.4.2  tls 		d->__reserved = 0;
    696  1.17.4.2  tls 		d->sz = 0;
    697  1.17.4.2  tls 		d->ptr = 0;
    698  1.17.4.2  tls 	}
    699  1.17.4.2  tls 
    700  1.17.4.2  tls 	d = sc->rx_desc;
    701  1.17.4.2  tls 	for (i = 0; i < SMAP_DESC_MAX; i++, d++) {
    702  1.17.4.2  tls 		d->stat = SMAP_RXDESC_EMPTY;
    703  1.17.4.2  tls 		d->__reserved = 0;
    704  1.17.4.2  tls 		d->sz = 0;
    705  1.17.4.2  tls 		d->ptr = 0;
    706  1.17.4.2  tls 	}
    707  1.17.4.2  tls 	_wbflush();
    708  1.17.4.2  tls }
    709  1.17.4.2  tls 
    710  1.17.4.2  tls 
    711  1.17.4.2  tls /*
    712  1.17.4.2  tls  * EEPROM
    713  1.17.4.2  tls  */
    714  1.17.4.2  tls int
    715  1.17.4.2  tls smap_get_eaddr(struct smap_softc *sc, u_int8_t *eaddr)
    716  1.17.4.2  tls {
    717  1.17.4.2  tls 	u_int16_t checksum, *p = (u_int16_t *)eaddr;
    718  1.17.4.2  tls 
    719  1.17.4.2  tls 	spd_eeprom_read(0, p, 3);
    720  1.17.4.2  tls 	spd_eeprom_read(3, &checksum, 1);
    721  1.17.4.2  tls 
    722  1.17.4.2  tls 	if (checksum != (u_int16_t)(p[0] + p[1] + p[2])) {
    723  1.17.4.2  tls 		printf("%s: Ethernet address checksum error.(%s)\n",
    724  1.17.4.2  tls 		    DEVNAME, ether_sprintf(eaddr));
    725  1.17.4.2  tls 		return (1);
    726  1.17.4.2  tls 	}
    727  1.17.4.2  tls 
    728  1.17.4.2  tls 	return (0);
    729  1.17.4.2  tls }
    730  1.17.4.2  tls 
    731  1.17.4.2  tls #ifdef SMAP_DEBUG
    732  1.17.4.2  tls #include <mips/locore.h>
    733  1.17.4.2  tls void
    734  1.17.4.2  tls __smap_lock_check(const char *func, int enter)
    735  1.17.4.2  tls {
    736  1.17.4.2  tls 	static int cnt;
    737  1.17.4.2  tls 	static const char *last;
    738  1.17.4.2  tls 
    739  1.17.4.2  tls 	cnt += enter ? 1 : -1;
    740  1.17.4.2  tls 
    741  1.17.4.2  tls 	if (cnt < 0 || cnt > 1)
    742  1.17.4.2  tls 		panic("%s cnt=%d last=%s", func, cnt, last);
    743  1.17.4.2  tls 
    744  1.17.4.2  tls 	last = func;
    745  1.17.4.2  tls }
    746  1.17.4.2  tls 
    747  1.17.4.2  tls void
    748  1.17.4.2  tls __smap_status(int msg)
    749  1.17.4.2  tls {
    750  1.17.4.2  tls 	static int cnt;
    751  1.17.4.2  tls 	__gsfb_print(1, "%d: tx=%d rx=%d txcnt=%d free=%d cnt=%d\n", msg,
    752  1.17.4.2  tls 	    _reg_read_1(SMAP_TXFIFO_FRAME_REG8),
    753  1.17.4.2  tls 	    _reg_read_1(SMAP_RXFIFO_FRAME_REG8), __sc->tx_desc_cnt,
    754  1.17.4.2  tls 	    __sc->tx_buf_freesize, cnt++);
    755  1.17.4.2  tls }
    756  1.17.4.2  tls #endif /* SMAP_DEBUG */
    757