root/usr/src/uts/common/io/afe/afeimpl.h
/*
 * Solaris driver for ethernet cards based on the ADMtek Centaur
 *
 * Copyright (c) 2007 by Garrett D'Amore <garrett@damore.org>.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 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. Neither the name of the author nor the names of any co-contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER 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 COPYRIGHT HOLDER 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.
 */
/*
 * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
 * Use is subject to license terms.
 */

#ifndef _AFEIMPL_H
#define _AFEIMPL_H

#ifdef  _KERNEL

#include        <sys/mac_provider.h>

/*
 * Compile time tunables.
 */
#define AFE_RXRING      128     /* number of rcv buffers */
#define AFE_TXRING      128     /* number of xmt buffers */
#define AFE_TXRECLAIM   8       /* when to reclaim tx buffers (txavail) */
#define AFE_TXRESCHED   120     /* when to resched (txavail) */
#define AFE_WDOGTIMER   5000    /* how often we check for tx hang (in msec) */
#define AFE_HEADROOM    34      /* headroom in packet (should be 2 modulo 4) */

/*
 * Constants, do not change.
 */
#define AFE_BUFSZ       (1664)  /* big enough for a vlan frame */
#define AFE_MCHASH      (64)

typedef struct afe afe_t;
typedef struct afe_card afe_card_t;
typedef struct afe_rxbuf afe_rxbuf_t;
typedef struct afe_txbuf afe_txbuf_t;
typedef struct afe_desc afe_desc_t;

/*
 * Card models.
 */
typedef enum {
        MODEL_CENTAUR = 1,
        MODEL_COMET,
} afe_model_t;

struct afe_card {
        uint16_t        card_venid;     /* PCI vendor id */
        uint16_t        card_devid;     /* PCI device id */
        char            *card_cardname; /* Description of the card */
        afe_model_t     card_model;     /* Card specific flags */
};

/*
 * Device instance structure, one per PCI card.
 */
struct afe {
        dev_info_t              *afe_dip;
        mac_handle_t            afe_mh;
        mii_handle_t            afe_mii;
        afe_card_t              *afe_cardp;
        uint16_t                afe_cachesize;
        uint8_t                 afe_sromwidth;
        int                     afe_flags;
        kmutex_t                afe_xmtlock;
        kmutex_t                afe_intrlock;
        ddi_iblock_cookie_t     afe_icookie;

        /*
         * Register and DMA access.
         */
        uintptr_t               afe_regs;
        ddi_acc_handle_t        afe_regshandle;

        /*
         * Receive descriptors.
         */
        int                     afe_rxhead;
        struct afe_desc         *afe_rxdescp;
        ddi_dma_handle_t        afe_rxdesc_dmah;
        ddi_acc_handle_t        afe_rxdesc_acch;
        uint32_t                afe_rxdesc_paddr;
        struct afe_rxbuf        **afe_rxbufs;

        /*
         * Transmit descriptors.
         */
        int                     afe_txreclaim;
        int                     afe_txsend;
        int                     afe_txavail;
        struct afe_desc         *afe_txdescp;
        ddi_dma_handle_t        afe_txdesc_dmah;
        ddi_acc_handle_t        afe_txdesc_acch;
        uint32_t                afe_txdesc_paddr;
        struct afe_txbuf        **afe_txbufs;
        hrtime_t                afe_txstall_time;
        boolean_t               afe_wantw;

        /*
         * Transceiver stuff.
         */
        int                     afe_phyaddr;
        int                     afe_phyid;
        int                     afe_phyinuse;

        int                     afe_forcefiber;

        /*
         * Address management.
         */
        uchar_t                 afe_curraddr[ETHERADDRL];
        boolean_t               afe_promisc;
        uint16_t                afe_mccount[AFE_MCHASH];
        uint32_t                afe_mctab[AFE_MCHASH / 32];     /* Centaur */

        /*
         * Kstats.
         */
        kstat_t                 *afe_intrstat;
        uint64_t                afe_ipackets;
        uint64_t                afe_opackets;
        uint64_t                afe_rbytes;
        uint64_t                afe_obytes;
        uint64_t                afe_brdcstxmt;
        uint64_t                afe_multixmt;
        uint64_t                afe_brdcstrcv;
        uint64_t                afe_multircv;
        unsigned                afe_norcvbuf;
        unsigned                afe_errrcv;
        unsigned                afe_errxmt;
        unsigned                afe_missed;
        unsigned                afe_underflow;
        unsigned                afe_overflow;
        unsigned                afe_align_errors;
        unsigned                afe_fcs_errors;
        unsigned                afe_carrier_errors;
        unsigned                afe_collisions;
        unsigned                afe_ex_collisions;
        unsigned                afe_tx_late_collisions;
        unsigned                afe_defer_xmts;
        unsigned                afe_first_collisions;
        unsigned                afe_multi_collisions;
        unsigned                afe_sqe_errors;
        unsigned                afe_macxmt_errors;
        unsigned                afe_macrcv_errors;
        unsigned                afe_toolong_errors;
        unsigned                afe_runt;
        unsigned                afe_jabber;
};

struct afe_rxbuf {
        caddr_t                 rxb_buf;
        ddi_dma_handle_t        rxb_dmah;
        ddi_acc_handle_t        rxb_acch;
        uint32_t                rxb_paddr;
};

struct afe_txbuf {
        caddr_t                 txb_buf;
        uint32_t                txb_paddr;
        ddi_dma_handle_t        txb_dmah;
        ddi_acc_handle_t        txb_acch;
};

/*
 * Descriptor.  We use rings rather than chains.
 */
struct afe_desc {
        unsigned        desc_status;
        unsigned        desc_control;
        unsigned        desc_buffer1;
        unsigned        desc_buffer2;
};

#define PUTTXDESC(afep, member, val)    \
        ddi_put32(afep->afe_txdesc_acch, &member, val)

#define PUTRXDESC(afep, member, val)    \
        ddi_put32(afep->afe_rxdesc_acch, &member, val)

#define GETTXDESC(afep, member) \
        ddi_get32(afep->afe_txdesc_acch, &member)

#define GETRXDESC(afep, member) \
        ddi_get32(afep->afe_rxdesc_acch, &member)

/*
 * Receive descriptor fields.
 */
#define RXSTAT_OWN              0x80000000U     /* ownership */
#define RXSTAT_RXLEN            0x3FFF0000U     /* frame length, incl. crc */
#define RXSTAT_RXERR            0x00008000U     /* error summary */
#define RXSTAT_DESCERR          0x00004000U     /* descriptor error */
#define RXSTAT_RXTYPE           0x00003000U     /* data type */
#define RXSTAT_RUNT             0x00000800U     /* runt frame */
#define RXSTAT_GROUP            0x00000400U     /* multicast/brdcast frame */
#define RXSTAT_FIRST            0x00000200U     /* first descriptor */
#define RXSTAT_LAST             0x00000100U     /* last descriptor */
#define RXSTAT_TOOLONG          0x00000080U     /* frame too long */
#define RXSTAT_COLLSEEN         0x00000040U     /* late collision seen */
#define RXSTAT_FRTYPE           0x00000020U     /* frame type */
#define RXSTAT_WATCHDOG         0x00000010U     /* receive watchdog */
#define RXSTAT_DRIBBLE          0x00000004U     /* dribbling bit */
#define RXSTAT_CRCERR           0x00000002U     /* crc error */
#define RXSTAT_OFLOW            0x00000001U     /* fifo overflow */
#define RXSTAT_ERRS             (RXSTAT_DESCERR | RXSTAT_RUNT | \
                                RXSTAT_COLLSEEN | RXSTAT_DRIBBLE | \
                                RXSTAT_CRCERR | RXSTAT_OFLOW)
#define RXLENGTH(x)             ((x & RXSTAT_RXLEN) >> 16)

#define RXCTL_ENDRING           0x02000000U     /* end of ring */
#define RXCTL_CHAIN             0x01000000U     /* chained descriptors */
#define RXCTL_BUFLEN2           0x003FF800U     /* buffer 2 length */
#define RXCTL_BUFLEN1           0x000007FFU     /* buffer 1 length */

/*
 * Transmit descriptor fields.
 */
#define TXSTAT_OWN              0x80000000U     /* ownership */
#define TXSTAT_URCNT            0x00C00000U     /* underrun count */
#define TXSTAT_TXERR            0x00008000U     /* error summary */
#define TXSTAT_JABBER           0x00004000U     /* jabber timeout */
#define TXSTAT_CARRLOST         0x00000800U     /* lost carrier */
#define TXSTAT_NOCARR           0x00000400U     /* no carrier */
#define TXSTAT_LATECOL          0x00000200U     /* late collision */
#define TXSTAT_EXCOLL           0x00000100U     /* excessive collisions */
#define TXSTAT_SQE              0x00000080U     /* heartbeat failure */
#define TXSTAT_COLLCNT          0x00000078U     /* collision count */
#define TXSTAT_UFLOW            0x00000002U     /* underflow */
#define TXSTAT_DEFER            0x00000001U     /* deferred */
#define TXCOLLCNT(x)            ((x & TXSTAT_COLLCNT) >> 3)
#define TXUFLOWCNT(x)           ((x & TXSTAT_URCNT) >> 22)

#define TXCTL_INTCMPLTE         0x80000000U     /* interrupt completed */
#define TXCTL_LAST              0x40000000U     /* last descriptor */
#define TXCTL_FIRST             0x20000000U     /* first descriptor */
#define TXCTL_NOCRC             0x04000000U     /* disable crc */
#define TXCTL_ENDRING           0x02000000U     /* end of ring */
#define TXCTL_CHAIN             0x01000000U     /* chained descriptors */
#define TXCTL_NOPAD             0x00800000U     /* disable padding */
#define TXCTL_HASHPERF          0x00400000U     /* hash perfect mode */
#define TXCTL_BUFLEN2           0x003FF800U     /* buffer length 2 */
#define TXCTL_BUFLEN1           0x000007FFU     /* buffer length 1 */


/*
 * Interface flags.
 */
#define AFE_RUNNING     0x1     /* chip is initialized */
#define AFE_SUSPENDED   0x2     /* interface is suspended */
#define AFE_HASFIBER    0x4     /* internal phy supports fiber (AFE_PHY_MCR) */

#define AFE_MODEL(afep)         ((afep)->afe_cardp->card_model)


/*
 * Register definitions located in afe.h exported header file.
 */

/*
 * Macros to simplify hardware access.
 */
#define GETCSR(afep, reg)       \
        ddi_get32(afep->afe_regshandle, (uint32_t *)(afep->afe_regs + reg))

#define GETCSR16(afep, reg)     \
        ddi_get16(afep->afe_regshandle, (uint16_t *)(afep->afe_regs + reg))

#define PUTCSR(afep, reg, val)  \
        ddi_put32(afep->afe_regshandle, (uint32_t *)(afep->afe_regs + reg), val)

#define PUTCSR16(afep, reg, val)        \
        ddi_put16(afep->afe_regshandle, (uint16_t *)(afep->afe_regs + reg), val)

#define SETBIT(afep, reg, val)  PUTCSR(afep, reg, GETCSR(afep, reg) | (val))

#define CLRBIT(afep, reg, val)  PUTCSR(afep, reg, GETCSR(afep, reg) & ~(val))

#define SYNCTXDESC(afep, index, who)    \
        (void) ddi_dma_sync(afep->afe_txdesc_dmah, \
            (index * sizeof (afe_desc_t)), sizeof (afe_desc_t), who)

#define SYNCTXBUF(txb, len, who)        \
        (void) ddi_dma_sync(txb->txb_dmah, 0, len, who)

#define SYNCRXDESC(afep, index, who)    \
        (void) ddi_dma_sync(afep->afe_rxdesc_dmah, \
            (index * sizeof (afe_desc_t)), sizeof (afe_desc_t), who)

#define SYNCRXBUF(rxb, len, who)        \
        (void) ddi_dma_sync(rxb->rxb_dmah, 0, len, who)

#endif  /* _KERNEL */

#endif  /* _AFEIMPL_H */