/*
 * arch/ppc/8220_io/fec.h
 *
 * Header file for the mpc8220 on-chip Fast Ethernet Controller driver
 *
 * Author: MontaVista Software, Inc.
 *         source@mvista.com
 *
 * Copyright 2003-2004 MontaVista Software
 *
 * 2003 (c) MontaVista, Software, Inc.  This file is licensed under the terms
 * of the GNU General Public License version 2.  This program is licensed
 * "as is" without any warranty of any kind, whether express or implied.
 */

#ifndef MPC8220_FEC_H
#define MPC8220_FEC_H

#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/mii.h>
#include <asm/mpc8220.h>

/* Tunable constants */
#define MPC8220_FEC_RECV_BUFFER_SIZE	1518	/* max receive packet size */
#define MPC8220_FEC_TBD_NUM   		64	/* max transmit packets */
#define MPC8220_FEC_RBD_NUM  		64	/* max receive packets */

struct mpc8220_fec {
	u32 fec_id;		/* FEC + 0x000 */
	u32 ievent;		/* FEC + 0x004 */
	u32 imask;		/* FEC + 0x008 */

	u32 reserved0[1];	/* FEC + 0x00C */
	u32 reserved0_1[5];
	u32 ecntrl;		/* FEC + 0x024 */

	u32 reserved1[6];	/* FEC + 0x028-03C */
	u32 mii_data;		/* FEC + 0x040 */
	u32 mii_speed;		/* FEC + 0x044 */
	u32 reserved1_1[7];
	u32 mib_control;	/* FEC + 0x064 */

	u32 reserved2_1[7];
	u32 r_cntrl;		/* FEC + 0x084 */
	u32 r_hash;		/* FEC + 0x088 */
	u32 reserved3_2[14];
	u32 x_cntrl;		/* FEC + 0x0C4 */
	u32 reserved4_1[7];
	u32 paddr1;		/* FEC + 0x0E4 */
	u32 paddr2;		/* FEC + 0x0E8 */
	u32 op_pause;		/* FEC + 0x0EC */

	u32 reserved5[4];	/* FEC + 0x0F0-0FC */
	u32 reserved5_1[6];
	u32 iaddr1;		/* FEC + 0x118 */
	u32 iaddr2;		/* FEC + 0x11C */
	u32 gaddr1;		/* FEC + 0x120 */
	u32 gaddr2;		/* FEC + 0x124 */
	u32 reserved5_2[7];
	u32 x_wmrk;		/* FEC + 0x144 */
	u32 reserved6_1[15];
	u32 rfifo_data;		/* FEC + 0x184 */
	u32 rfifo_status;	/* FEC + 0x188 */
	u32 rfifo_cntrl;	/* FEC + 0x18C */
	u32 rfifo_lrf_ptr;	/* FEC + 0x190 */
	u32 rfifo_lwf_ptr;	/* FEC + 0x194 */
	u32 rfifo_alarm;	/* FEC + 0x198 */
	u32 rfifo_rdptr;	/* FEC + 0x19C */
	u32 rfifo_wrptr;	/* FEC + 0x1A0 */
	union {
		u32 longs;	/* FEC + 0x1A4 */
		u8 bytes[4];	/* FEC + 0x1A4 */
	} tfifo_data;
	u32 tfifo_status;	/* FEC + 0x1A8 */
	u32 tfifo_cntrl;	/* FEC + 0x1AC */
	u32 tfifo_lrf_ptr;	/* FEC + 0x1B0 */
	u32 tfifo_lwf_ptr;	/* FEC + 0x1B4 */
	u32 tfifo_alarm;	/* FEC + 0x1B8 */
	u32 tfifo_rdptr;	/* FEC + 0x1BC */
	u32 tfifo_wrptr;	/* FEC + 0x1C0 */

	u32 reset_cntrl;	/* FEC + 0x1C4 */
	u32 xmit_fsm;		/* FEC + 0x1C8 */

	u32 reserved8[3];	/* FEC + 0x1CC-1D4 */
	u32 reserved8_1[10];

	u32 rmon_t_drop;	/* FEC + 0x200 */
	u32 rmon_t_packets;	/* FEC + 0x204 */
	u32 rmon_t_bc_pkt;	/* FEC + 0x208 */
	u32 rmon_t_mc_pkt;	/* FEC + 0x20C */
	u32 rmon_t_crc_align;	/* FEC + 0x210 */
	u32 rmon_t_undersize;	/* FEC + 0x214 */
	u32 rmon_t_oversize;	/* FEC + 0x218 */
	u32 rmon_t_frag;	/* FEC + 0x21C */
	u32 rmon_t_jab;		/* FEC + 0x220 */
	u32 rmon_t_col;		/* FEC + 0x224 */
	u32 rmon_t_p64;		/* FEC + 0x228 */
	u32 rmon_t_p65to127;	/* FEC + 0x22C */
	u32 rmon_t_p128to255;	/* FEC + 0x230 */
	u32 rmon_t_p256to511;	/* FEC + 0x234 */
	u32 rmon_t_p512to1023;	/* FEC + 0x238 */
	u32 rmon_t_p1024to2047;	/* FEC + 0x23C */
	u32 rmon_t_p_gte2048;	/* FEC + 0x240 */
	u32 rmon_t_octets;	/* FEC + 0x244 */
	u32 ieee_t_drop;	/* FEC + 0x248 */
	u32 ieee_t_frame_ok;	/* FEC + 0x24C */
	u32 ieee_t_1col;	/* FEC + 0x250 */
	u32 ieee_t_mcol;	/* FEC + 0x254 */
	u32 ieee_t_def;		/* FEC + 0x258 */
	u32 ieee_t_lcol;	/* FEC + 0x25C */
	u32 ieee_t_excol;	/* FEC + 0x260 */
	u32 ieee_t_macerr;	/* FEC + 0x264 */
	u32 ieee_t_cserr;	/* FEC + 0x268 */
	u32 ieee_t_sqe;		/* FEC + 0x26C */
	u32 t_fdxfc;		/* FEC + 0x270 */
	u32 ieee_t_octets_ok;	/* FEC + 0x274 */

	u32 reserved9[2];	/* FEC + 0x278-27C */
	u32 rmon_r_drop;	/* FEC + 0x280 */
	u32 rmon_r_packets;	/* FEC + 0x284 */
	u32 rmon_r_bc_pkt;	/* FEC + 0x288 */
	u32 rmon_r_mc_pkt;	/* FEC + 0x28C */
	u32 rmon_r_crc_align;	/* FEC + 0x290 */
	u32 rmon_r_undersize;	/* FEC + 0x294 */
	u32 rmon_r_oversize;	/* FEC + 0x298 */
	u32 rmon_r_frag;	/* FEC + 0x29C */
	u32 rmon_r_jab;		/* FEC + 0x2A0 */

	u32 rmon_r_resvd_0;	/* FEC + 0x2A4 */

	u32 rmon_r_p64;		/* FEC + 0x2A8 */
	u32 rmon_r_p65to127;	/* FEC + 0x2AC */
	u32 rmon_r_p128to255;	/* FEC + 0x2B0 */
	u32 rmon_r_p256to511;	/* FEC + 0x2B4 */
	u32 rmon_r_p512to1023;	/* FEC + 0x2B8 */
	u32 rmon_r_p1024to2047;	/* FEC + 0x2BC */
	u32 rmon_r_p_gte2048;	/* FEC + 0x2C0 */
	u32 rmon_r_octets;	/* FEC + 0x2C4 */
	u32 ieee_r_drop;	/* FEC + 0x2C8 */
	u32 ieee_r_frame_ok;	/* FEC + 0x2CC */
	u32 ieee_r_crc;		/* FEC + 0x2D0 */
	u32 ieee_r_align;	/* FEC + 0x2D4 */
	u32 r_macerr;		/* FEC + 0x2D8 */
	u32 r_fdxfc;		/* FEC + 0x2DC */
	u32 ieee_r_octets_ok;	/* FEC + 0x2E0 */

	u32 reserved10[6];	/* FEC + 0x2E4-2FC */

	u32 reserved11[64];	/* FEC + 0x300-3FF */
};

#define MPC8220_FEC_MIB_DISABLE		0x80000000

#define MPC8220_FEC_IEVENT_HBERR	0x80000000
#define MPC8220_FEC_IEVENT_BABR		0x40000000
#define MPC8220_FEC_IEVENT_BABT		0x20000000
#define MPC8220_FEC_IEVENT_GRA		0x10000000
#define MPC8220_FEC_IEVENT_TFINT	0x08000000
#define MPC8220_FEC_IEVENT_MII		0x00800000
#define MPC8220_FEC_IEVENT_LATE_COL	0x00200000
#define MPC8220_FEC_IEVENT_COL_RETRY_LIM	0x00100000
#define MPC8220_FEC_IEVENT_XFIFO_UN		0x00080000
#define MPC8220_FEC_IEVENT_XFIFO_ERROR	0x00040000
#define MPC8220_FEC_IEVENT_RFIFO_ERROR	0x00020000

#define MPC8220_FEC_ECNTRL_RESET	0x00000001
#define MPC8220_FEC_ECNTRL_ENABLE	0x00000002
/* ECNTRL_OE not defined for Alpine */

#define MPC8220_FEC_RCNTRL_MAX_FL_SHIFT	16
#define MPC8220_FEC_RCNTL_LOOP		0x01
#define MPC8220_FEC_RCNTL_DRT		0x02
#define MPC8220_FEC_RCNTL_MII_MODE	0x04
#define MPC8220_FEC_RCNTL_PROM		0x08
#define MPC8220_FEC_RCNTL_FCE		0x10

#define MPC8220_FEC_TSTATUS_IP              0x80000000	/* Illegal Pointer */
#define MPC8220_FEC_TSTATUS_FRAME0          0x08000000	/* Frame boundary on 31:24 (BE) byte. */
#define MPC8220_FEC_TSTATUS_FRAME1          0x04000000	/* Frame boundary on 23:16 (BE) byte. */
#define MPC8220_FEC_TSTATUS_FRAME2          0x02000000	/* Frame boundary on 15: 8 (BE) byte. */
#define MPC8220_FEC_TSTATUS_FRAME3          0x01000000	/* Frame boundary on  7: 0 (BE) byte. */
#define MPC8220_FEC_TSTATUS_FAE             0x00800000	/* Frame Accept Error. */
#define MPC8220_FEC_TSTATUS_RXW             0x00400000	/* Receive Wait Condition. */
#define MPC8220_FEC_TSTATUS_UF              0x00200000	/* FIFO Underflow */
#define MPC8220_FEC_TSTATUS_OF              0x00100000	/* FIFO Overflow */
#define MPC8220_FEC_TSTATUS_FR              0x00080000	/* Frame Ready. */
#define MPC8220_FEC_TSTATUS_FULL            0x00040000	/* Full Alarm. */
#define MPC8220_FEC_TSTATUS_ALARM           0x00020000	/* Alarm. */
#define MPC8220_FEC_TSTATUS_EMPTY           0x00010000	/* Empty. */

#define MPC8220_FEC_TCNTL_WCTL              0x40000000	/* Write Control. */
#define MPC8220_FEC_TCNTL_WFR               0x20000000	/* Write Frame. */
#define MPC8220_FEC_TCNTL_FRAME             0x08000000	/* Frame enable mode. */
#define MPC8220_FEC_TCNTL_GR                0x07000000	/* Last Transfer Granularity. */
#define MPC8220_FEC_TCNTL_IP_MASK           0x00800000	/* Illegal Pointer Mask. */
#define MPC8220_FEC_TCNTL_FAE_MASK          0x00400000	/* Frame Accept Error Mask. */
#define MPC8220_FEC_TCNTL_RXW_MASK          0x00200000	/* Receive Wait Condition Mask. */
#define MPC8220_FEC_TCNTL_UF_MASK           0x00100000	/* Underflow Mask. */
#define MPC8220_FEC_TCNTL_OF_MASK           0x00080000	/* Overflow Mask. */

#define MPC8220_FEC_FIFO_RST_SW             0x02000000	/* Software Reset */
#define MPC8220_FEC_FIFO_RST_CTL            0x01000000	/* Reset Control */

#define MPC8220_FEC_RFIFO_CNTRL_WCTL        0x40000000	/* Write Control */
#define MPC8220_FEC_RFIFO_CNTRL_WFR         0x20000000	/* Write Frame */
#define MPC8220_FEC_RFIFO_CNTRL_FRAME       0x08000000	/* Frame Mode Enable */
#define MPC8220_FEC_RFIFO_CNTRL_GR_MASK     0x7	/* Last Transfer Granularity */
#define MPC8220_FEC_RFIFO_CNTRL_GR_SHIFT    24
#define MPC8220_FEC_RFIFO_CNTRL_GR_SET(x)   (((x) & MPC8220_FEC_TFIFO_CNTRL_GR_MASK) << MPC8220_FEC_TFIFO_CNTRL_GR_SHIFT)
#define MPC8220_FEC_RFIFO_CNTRL_GR_GET(x)   (((x) >> MPC8220_FEC_TFIFO_CNTRL_GR_SHIFT) & MPC8220_FEC_TFIFO_CNTRL_GR_MASK)
#define MPC8220_FEC_RFIFO_CNTRL_IP_MASK     0x00800000	/* Illegal Pointer Mask */
#define MPC8220_FEC_RFIFO_CNTRL_FAE_MASK    0x00400000	/* Frame Accept Error */
#define MPC8220_FEC_RFIFO_CNTRL_RXW_MASK    0x00200000	/* Receive Wait Condition Mask */
#define MPC8220_FEC_RFIFO_CNTRL_UF_MASK     0x00100000	/* FIFO Underflow Mask */
#define MPC8220_FEC_RFIFO_CNTRL_OF_MASK     0x00080000	/* FIFO Overflow Mask */

/* The bits in a receive frame status word */
#define MPC_FEC_RFSW_L                   0x08000000
#define MPC_FEC_RFSW_M                   0x01000000
#define MPC_FEC_RFSW_BC                  0x00800000
#define MPC_FEC_RFSW_MC                  0x00400000
#define MPC_FEC_RFSW_LG                  0x00200000
#define MPC_FEC_RFSW_NO                  0x00100000
#define MPC_FEC_RFSW_CR                  0x00040000
#define MPC_FEC_RFSW_OV                  0x00020000
#define MPC_FEC_RFSW_TR                  0x00010000
#define MPC_FEC_RFSW_FRAME_MASK          0x7ff
#define MPC_FEC_RFSW_GET_FRAME_LENGTH(x) ((x) & MPC_FEC_RFSW_FRAME_MASK)
#define MPC_FEC_RFSW_VALID_PACKET(x)    ((x) & (MPC_FEC_RFSW_L) \
					&& !((x) & (MPC_FEC_RFSW_LG | MPC_FEC_RFSW_NO \
					     | MPC_FEC_RFSW_CR | MPC_FEC_RFSW_OV \
					     | MPC_FEC_RFSW_TR )))
#define MPC8220_FEC_TFIFO_CNTRL_WCTL        0x40000000	/* Write Control */
#define MPC8220_FEC_TFIFO_CNTRL_WFR         0x20000000	/* Write Frame */
#define MPC8220_FEC_TFIFO_CNTRL_FRAME       0x08000000	/* Frame Mode Enable */
#define MPC8220_FEC_TFIFO_CNTRL_GR_MASK     0x7	/* Last Transfer Granularity */
#define MPC8220_FEC_TFIFO_CNTRL_GR_SHIFT    24
#define MPC8220_FEC_TFIFO_CNTRL_GR_SET(x)   (((x) & MPC8220_FEC_TFIFO_CNTRL_GR_MASK) << MPC8220_FEC_TFIFO_CNTRL_GR_SHIFT)
#define MPC8220_FEC_TFIFO_CNTRL_GR_GET(x)   (((x) >> MPC8220_FEC_TFIFO_CNTRL_GR_SHIFT) & MPC8220_FEC_TFIFO_CNTRL_GR_MASK)
#define MPC8220_FEC_TFIFO_CNTRL_IP_MASK     0x00800000	/* Illegal Pointer Mask */
#define MPC8220_FEC_TFIFO_CNTRL_FAE_MASK    0x00400000	/* Frame Accept Error */
#define MPC8220_FEC_TFIFO_CNTRL_RXW_MASK    0x00200000	/* Receive Wait Condition Mask */
#define MPC8220_FEC_TFIFO_CNTRL_UF_MASK     0x00100000	/* FIFO Underflow Mask */
#define MPC8220_FEC_TFIFO_CNTRL_OF_MASK     0x00080000	/* FIFO Overflow Mask */

/* These are the same bits for either ievent or imask registers. */
#define MPC8220_FEC_INT_HBE                 0x80000000	/* Heart beat. */
#define MPC8220_FEC_INT_BABR                0x40000000	/* Babble receive error. */
#define MPC8220_FEC_INT_BABT                0x20000000	/* Babble transmit error. */
#define MPC8220_FEC_INT_GRA                 0x10000000	/* Graceful stop. */
#define MPC8220_FEC_INT_TF                  0x08000000	/* Transmit frame. */
#define MPC8220_FEC_INT_TB                  0x04000000	/* Transmit buffer. */
#define MPC8220_FEC_INT_RF                  0x02000000	/* Receive frame. */
#define MPC8220_FEC_INT_RB                  0x01000000	/* Receive buffer */
#define MPC8220_FEC_INT_MII                 0x00800000	/* MII. */
#define MPC8220_FEC_INT_EBERR               0x00400000	/* Ethernet controller bur error. */
#define MPC8220_FEC_INT_LC                  0x00200000	/* Late collision. */
#define MPC8220_FEC_INT_CRL                 0x00100000	/* Collision retry limit. */
#define MPC8220_FEC_INT_XFUN                0x00080000	/* Xmit FIFO underrun. */
#define MPC8220_FEC_INT_XFERR               0x00040000	/* Xmit FIFO error. */
#define MPC8220_FEC_INT_RFERR               0x00020000	/* Receive FIFO error. */

/* PHY state machine actions: */
#define	PHY_OP_CONTINUE		0
#define PHY_OP_READ		0x2
#define PHY_OP_WRITE		0x1

/* PHY state machine return codes */
#define	PHY_RET_WAIT		0
#define PHY_RET_COMPLETE	1

/* Receive & Transmit Buffer Descriptor definitions */
struct mpc8220_fec_bd {
	u16 status;
	u16 length;
	u32 data;
};

/* Receive data buffer format */
struct mpc8220_rbuf {
	u8 data[MPC8220_FEC_RECV_BUFFER_SIZE];
};

struct sdma_queue {
	struct mpc8220_fec_bd *bd_base;
	u32 *private_base;
	u16 last_index;
	u16 in_index;
	u16 out_index;
};

/* Mux 0b00 values */
#define DMA_REQ_M00_FEC1RX  16
#define DMA_REQ_M00_FEC1TX  17
#define DMA_REQ_M00_FEC2RX  30
#define DMA_REQ_M00_FEC2TX  31

struct bufferDesc {
	int *buf;
	int size;
};

struct mpc8220_packet_set {
	MCD_bufDescFec data;
	MCD_bufDescFec frame;
};

struct mpc8220_packet_pair {
	struct bufferDesc b;	/* small buffer for the frame word */
	struct sk_buff *skb;	/* skb for the packet data */
	int skb_size;		/* amount of data requested in skb */
	struct mpc8220_packet_set *pair;	/* ptr to first of two bufDesc that make a ring */
};

#define RCV_RING_SIZE 8
#define XMT_RING_SIZE 8

struct mpc8220_rcv_ring {
	unsigned int size;	/* number of entries in ring */
	unsigned int mask;	/* mask to achieve 'n % size' */
	unsigned int idx;	/* index into ring */
	struct mpc8220_packet_pair *ring;
};

struct mpc8220_xmt_packet {
	struct sk_buff *skb;
	int len;
	struct mpc8220_fec *fec;
	int rdy;		/* !0 if packet in *b is ready for transmission.  Can't
				   use the BUF_READY flag since the dma may clear it
				   already */
	MCD_bufDescFec *b;
};

struct mpc8220_xmt_ring {
	unsigned int size;	/* number of entries in ring */
	unsigned int mask;	/* mask to achieve 'n % size' */
	unsigned int head;	/* index into ring */
	unsigned int tail;	/* tail index into ring */
	unsigned int stopped;	/* !0 means xmit stopped */
	struct mpc8220_xmt_packet *ring;
};
struct mii_SMdata {
	int state;
	unsigned char address;
	u16 data;
};

struct mpc8220_fec_priv {
	int link;
	int tx_full;
	int r_tasknum;
	int t_tasknum;
	int r_irq;
	int t_irq;
	u32 last_transmit_time;
	u32 last_receive_time;
	struct mpc8220_fec *fec;
	struct mpc8220_sram_fec *sram;
	struct mpc8220_gpio *gpio;
	struct mpc8220_sdma *sdma;
	struct sdma_queue r_queue;
	struct sk_buff *rskb[MPC8220_FEC_RBD_NUM];
	struct sdma_queue t_queue;
	struct sk_buff *tskb[MPC8220_FEC_TBD_NUM];
	spinlock_t lock;
	int sent_packet;
	unsigned long open_time;
	struct net_device_stats stats;

	struct mii_SMdata phy_data;
	struct timer_list phy_timer;	/* PHY monitoring timer */
	unsigned int miipoll_SMstate;
	wait_queue_head_t phy_queue;
	void (*phy_readCB)(struct net_device *dev);

	/* poll_mii variables */
	int phy_lock;
	unsigned int negotiated;
	unsigned int phy_duplex;
	int phy_carrier;
	unsigned int fec_duplex;
	int netif_carrier;
	spinlock_t mii_irq_lock;

	struct sk_buff *tx_skb;	/* pointer to skb for transmit */
	unsigned long tx_packetlen;	/* length of packet transmitted */
	int xmit_initiator;
	int recv_initiator;
	struct mpc8220_rcv_ring rcvRing;
	struct mpc8220_xmt_ring xmtRing;
	spinlock_t xmtLock;
};

typedef enum {
	SEVENWIRE,		/* 7-wire       */
	MII10,			/* MII 10Mbps   */
	MII100			/* MII 100Mbps  */
} mpc8220_fec_xceiver;

struct mpc8220_sram_fec {
	struct mpc8220_fec_bd *tbd_base;
	struct mpc8220_fec_bd *tbd_next;
	struct mpc8220_fec_bd *rbd_base;
	struct mpc8220_fec_bd *rbd_next;
	u8 reserved[16];
	struct mpc8220_fec_bd tbd[MPC8220_FEC_TBD_NUM];
	struct mpc8220_fec_bd rbd[MPC8220_FEC_RBD_NUM];
};
#define MPC8220_FEC_BD_WRAP    0x2000	/* Last BD in ring */

#define MPC8220_FEC_RBD_EMPTY  0x8000	/* Buffer is empty */
#define MPC8220_FEC_RBD_WRAP   0x2000	/* Last BD in ring */
#define MPC8220_FEC_RBD_INT    0x1000	/* Interrupt */
#define MPC8220_FEC_RBD_LAST   0x0800	/* Buffer is last in frame(useless) */
#define MPC8220_FEC_RBD_MISS   0x0100	/* Miss bit for prom mode */
#define MPC8220_FEC_RBD_BC     0x0080	/* Received frame is broadcast frame */
#define MPC8220_FEC_RBD_MC     0x0040	/* Received frame is multicast frame */
#define MPC8220_FEC_RBD_LG     0x0020	/* Frame length violation */
#define MPC8220_FEC_RBD_NO     0x0010	/* Nonoctet align frame */
#define MPC8220_FEC_RBD_SH     0x0008	/* Short frame, FEC does not support */
#define MPC8220_FEC_RBD_CR     0x0004	/* CRC error */
#define MPC8220_FEC_RBD_OV     0x0002	/* Receive FIFO overrun */
#define MPC8220_FEC_RBD_TR     0x0001	/* The receive frame is truncated */

#define MPC8220_FEC_RBD_INIT   (MPC8220_FEC_RBD_INT	| MPC8220_FEC_RBD_EMPTY)
#define MPC8220_FEC_RBD_ERR    (MPC8220_FEC_RBD_LG	| \
				MPC8220_FEC_RBD_NO	| \
				MPC8220_FEC_RBD_CR	| \
				MPC8220_FEC_RBD_OV	| \
				MPC8220_FEC_RBD_TR)

#define MPC8220_FEC_TBD_READY  0x8000	/* Buffer is ready */
#define MPC8220_FEC_TBD_WRAP   0x2000	/* Last BD in ring */
#define MPC8220_FEC_TBD_INT    0x1000	/* Interrupt */
#define MPC8220_FEC_TBD_LAST   0x0800	/* Buffer is last in frame */
#define MPC8220_FEC_TBD_TC     0x0400	/* Transmit the CRC */
#define MPC8220_FEC_TBD_ABC    0x0200	/* Append bad CRC */

#define MPC8220_FEC_TBD_INIT   (MPC8220_FEC_TBD_INT		| \
				MPC8220_FEC_TBD_TC		| \
				MPC8220_FEC_TBD_READY	| \
				MPC8220_FEC_TBD_LAST)

inline void
sdma_init_queue(struct sdma_queue *queue,
		volatile struct mpc8220_fec_bd *bd_base, u32 * private_base,
		u16 length)
{
	queue->bd_base = (struct mpc8220_fec_bd *) bd_base;
	queue->private_base = private_base;
	queue->last_index = length - 1;
	queue->in_index = 0;
	queue->out_index = 0;
}

inline int
sdma_queue_empty(struct sdma_queue *queue)
{
	return queue->in_index == queue->out_index;
}

inline void
sdma_next_in(struct sdma_queue *queue)
{
	if (queue->in_index == queue->last_index)
		queue->in_index = 0;
	else
		queue->in_index++;
}

inline void
sdma_set_in_status(struct sdma_queue *queue, u16 status)
{
	if (queue->in_index == queue->last_index)
		status |= MPC8220_FEC_BD_WRAP;
	out_be16(&queue->bd_base[queue->in_index].status, status);
}

inline void
sdma_set_in_length(struct sdma_queue *queue, u16 length)
{
	out_be16(&queue->bd_base[queue->in_index].length, length);
}

inline void
sdma_set_in_data(struct sdma_queue *queue, u32 data)
{
	out_be32(&queue->bd_base[queue->in_index].data, data);
}

inline void
sdma_set_in_private(struct sdma_queue *queue, u32 private)
{
	queue->private_base[queue->in_index] = private;
}

inline u16
sdma_in_status(struct sdma_queue *queue)
{
	return in_be16(&queue->bd_base[queue->in_index].status);
}

inline u16
sdma_in_length(struct sdma_queue * queue)
{
	return in_be16(&queue->bd_base[queue->in_index].length);
}

inline u32
sdma_in_data(struct sdma_queue * queue)
{
	return in_be32(&queue->bd_base[queue->in_index].data);
}

inline u32
sdma_in_private(struct sdma_queue * queue)
{
	return queue->private_base[queue->in_index];
}

inline void
sdma_next_out(struct sdma_queue *queue)
{
	if (queue->out_index == queue->last_index)
		queue->out_index = 0;
	else
		queue->out_index++;
}

inline void
sdma_set_out_status(struct sdma_queue *queue, u16 status)
{
	if (queue->out_index == queue->last_index)
		status |= MPC8220_FEC_BD_WRAP;
	out_be16(&queue->bd_base[queue->out_index].status, status);
}

inline void
sdma_set_out_length(struct sdma_queue *queue, u16 length)
{
	out_be16(&queue->bd_base[queue->out_index].length, length);
}

inline void
sdma_set_out_data(struct sdma_queue *queue, u32 data)
{
	out_be32(&queue->bd_base[queue->out_index].data, data);
}

inline void
sdma_set_out_private(struct sdma_queue *queue, u32 private)
{
	queue->private_base[queue->out_index] = private;
}

inline u16
sdma_out_status(struct sdma_queue *queue)
{
	return in_be16(&queue->bd_base[queue->out_index].status);
}

inline u16
sdma_out_length(struct sdma_queue * queue)
{
	return in_be16(&queue->bd_base[queue->out_index].length);
}

inline u32
sdma_out_data(struct sdma_queue * queue)
{
	return in_be32(&queue->bd_base[queue->out_index].data);
}

inline u32
sdma_out_private(struct sdma_queue * queue)
{
	return queue->private_base[queue->out_index];
}

inline void
sdma_set_in_skb(struct sdma_queue *queue, struct sk_buff *skb)
{
	sdma_set_in_private(queue, (u32) skb);
}

inline void
sdma_set_out_skb(struct sdma_queue *queue, struct sk_buff *skb)
{
	sdma_set_out_private(queue, (u32) skb);
}

inline struct sk_buff *
sdma_in_skb(struct sdma_queue *queue)
{
	return (struct sk_buff *) sdma_in_private(queue);
}

inline struct sk_buff *
sdma_out_skb(struct sdma_queue *queue)
{
	return (struct sk_buff *) sdma_out_private(queue);
}

/* MII-related definitions */
#define MPC8220_FEC_MII_DATA_ST       0x40000000	/* Start frame */
#define MPC8220_FEC_MII_DATA_OP_RD    0x20000000	/* Perform read */
#define MPC8220_FEC_MII_DATA_OP_WR    0x10000000	/* Perform write */
#define MPC8220_FEC_MII_DATA_PA_MSK   0x0f800000	/* PHY Address mask */
#define MPC8220_FEC_MII_DATA_RA_MSK   0x007c0000	/* PHY Register mask */
#define MPC8220_FEC_MII_DATA_TA       0x00020000	/* Turnaround */
#define MPC8220_FEC_MII_DATA_DATAMSK  0x00000fff	/* PHY data mask */

#define MPC8220_FEC_MII_DATA_RA_SHIFT 0x12	/* MII reg addr bits */
#define MPC8220_FEC_MII_DATA_PA_SHIFT 0x17	/* MII PHY addr bits */

const char mpc8220_fec_name[] = "eth0";

struct mibCounters {
	unsigned int byteReceived;
	unsigned int byteSent;
	unsigned int framesReceived;
	unsigned int framesSent;
	unsigned int totalByteReceived;
	unsigned int totalFramesReceived;
	unsigned int broadcastFramesReceived;
	unsigned int multicastFramesReceived;
	unsigned int cRCError;
	unsigned int oversizeFrames;
	unsigned int fragments;
	unsigned int jabber;
	unsigned int collision;
	unsigned int lateCollision;
	unsigned int frames64;
	unsigned int frames65_127;
	unsigned int frames128_255;
	unsigned int frames256_511;
	unsigned int frames512_1023;
	unsigned int frames1024_MaxSize;
	unsigned int macRxError;
	unsigned int droppedFrames;
	unsigned int outMulticastFrames;
	unsigned int outBroadcastFrames;
	unsigned int undersizeFrames;
};

#define MPC8220_FEC_WATCHDOG_TIMEOUT  (40*HZ)

#endif				/* MPC8220_FEC_H */
