/*********************************************************************
 *                
 * Filename:      eagle_eye.h
 * Version:       0.1
 * Description:   Device driver for the VLSI VL82C147 PCI IrDA chipset
 * Status:        Experimental.
 * Author:        Dag Brattli <dagb@cs.uit.no>
 * Created at:    Fri May 21 12:18:10 1999
 * Modified at:   Tue Jun 22 09:30:56 1999
 * Modified by:   Dag Brattli <dagb@cs.uit.no>
 * 
 *     Copyright (c) 1999 Dag Brattli, All Rights Reserved.
 *     
 *     This program is free software; you can redistribute it and/or 
 *     modify it under the terms of the GNU General Public License as 
 *     published by the Free Software Foundation; either version 2 of 
 *     the License, or (at your option) any later version.
 * 
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 *     GNU General Public License for more details.
 * 
 *     You should have received a copy of the GNU General Public License 
 *     along with this program; if not, write to the Free Software 
 *     Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
 *     MA 02111-1307 USA
 *     
 ********************************************************************/

#ifndef EAGLE_EYE_H
#define EAGLE_EYE_H

#define CHIP_IO_EXTENT 16

/* PCI Configuration registers */
#define	PCI_INT_LINE        0x3c  /* Interrupt (IRQ) line */
#define	PCI_MSTRPAGE        0x41  /* high 8 bits of all addresses */

/* PCI Miscellaneous Register */
#define PCI_IRMISC          0x42
#define   IRMISC_UART_TST   0x80  /* UART test mode */
#define   IRMISC_IRRAIL	    0x40  /* I/R Rail power voltage level */
#define   IRMISC_IRPD	    0x08  /* Transceiver power down control */
#define   IRMISC_UART_EN    0x04  /* UART address enable */
#define   IRMISC_UART_SEL   0x03  /* UART address select */

/* I/O registers */
#define RING_PTR            0x02  /* (16 bits) */
#define	RING_PTR_RX         0x02  /* (bits 0:6) */
#define	RING_PTR_TX         0x03  /* (bits 8:14) */
#define	RING_BASE           0x04

#define	PROMPT	            0x08
#define	UART_FCR	    0x0d  /* UART FCR, needed to reset Rx FIFO */

#define	IR_REG_CURR_PHYCTL  0x16

#define	MAX_PACKET_LEN	    0x1a
#define	RECV_BYTE_COUNT	    0x1c

/* Interrupt Register */
#define IRINTR		    0x00
#define   IRINTR_ACT_EN     0x80  /* Activity interrupt enable */
#define   IRINTR_ACTIVITY   0x40  /* Activity monitor */
#define   IRINTR_RPKT_EN    0x20  /* Receive packet interrupt enable */
#define   IRINTR_RPKT_INT   0x10  /* Receive packet interrupt */
#define   IRINTR_TPKT_EN    0x08  /* Transmit packet interupt enable */
#define   IRINTR_TPKT_INT   0x04  /* Transmit packet interrupt */
#define   IRINTR_OE_EN	    0x02  /* UART Rx FIFO overrun error intr enable */
#define   IRINTR_OE_INT	    0x01  /* UART receive FIFO ovrn error interrupt */
#define   IRINTR_EN_MASK    0xa8  /* All interrupt enable bits */
#define	  IRINTR_INT_MASK   0x54  /* All interrupt status bits */

/* I/R Configuration Register */
#define	IRCFG               0x10
#define   IRCFG_LOOP	  0x4000  /* Loopback test mode */
#define   IRCFG_ENTX	  0x1000  /* Transmit enable */
#define   IRCFG_ENRX	  0x0800  /* Receive enable */
#define   IRCFG_MASTER	  0x0400  /* Master enable */
#define   IRCFG_RX_ANY	  0x0200  /* Receive any frame */
#define   IRCFG_CRC16	  0x0080  /* 16 bit CRC enable */
#define   IRCFG_FIR	  0x0040  /* FIR mode enable */
#define   IRCFG_MIR	  0x0020  /* MIR mode enable */
#define   IRCFG_SIR	  0x0010  /* SIR mode enable */
#define   IRCFG_SIR_FILT  0x0008  // Enable SIR filter on receiver in SIR mode
#define   IRCFG_SIR_TEST  0x0004  // Enable SIR filter when not in SIR mode
#define   IRCFG_TX_POL	  0x0002  // invert tx output
#define   IRCFG_RX_POL	  0x0001  // invert rx input 

#define   BR_OFFSET         10 /* Offset to baudrate part of NPHYCTL reg */
#define   PW_OFFSET         5  /* Offset to pulse width part of NPHYCTL reg */

/* IR Next Physical Control Register */
#define	NPHYCTL	            0x18
#define   NPHYCTL_2400      ((47 << BR_OFFSET) | (12 << PW_OFFSET))
#define   NPHYCTL_9600	    ((11 << BR_OFFSET) | (12 << PW_OFFSET))
#define   NPHYCTL_19200     (( 5 << BR_OFFSET) | (12 << PW_OFFSET))
#define   NPHYCTL_38400     (( 2 << BR_OFFSET) | (12 << PW_OFFSET))
#define   NPHYCTL_57600     (( 1 << BR_OFFSET) | (12 << PW_OFFSET))
#define   NPHYCTL_115200                         (12 << PW_OFFSET)
#define   NPHYCTL_MIR                            (10 << PW_OFFSET)
#define   NPHYCTL_FIR       15


/* I/R Enable Register */
#define	IRENABLE	    0x15
#define   IRENABLE_IREN	    0x80  /* I/R enable */
#define   IRENABLE_CFGER    0x40  /* Configuration error (ro) */
#define   IRENABLE_FIR_ON   0x20  /* FIR on (ro) */
#define   IRENABLE_MIR_ON   0x10  /* MIR on (ro) */
#define   IRENABLE_SIR_ON   0x08  /* SIR on (ro) */
#define   IRENABLE_TX_EN    0x04  /* Transmit enable status (ro) */
#define   IRENABLE_RX_EN    0x02  /* Receive enable status (ro) */
#define   IRENABLE_CRC16    0x01  /* 16 bit CRC enabled (ro) */

#define	  IRENABLE_MASK	    0xc6  /* Read mask */

/* Ring Size Register */
#define	RING_SIZE	    0x07
#define	  RING_SIZE_TX_4    0x00
#define	  RING_SIZE_TX_8    0x10
#define	  RING_SIZE_TX_16   0x30
#define	  RING_SIZE_RX_4    0x00
#define	  RING_SIZE_RX_8    0x01
#define	  RING_SIZE_RX_16   0x03

/* Clock Control Register */
#define	PCI_CLKCTL          0x40
#define   CLK_CTL_CLKSTP    0x80  /* Clock stop */
#define   CLK_CTL_LOCK	    0x40  /* PLL locked status */
#define   CLK_CTL_EXTCLK    0x20  /* External clock */
#define	  CLK_CTL_XCKSEL    0x10  /* External clock select */
#define   CLK_CTL_WAKE	    0x08  /* Wakeup enable */
#define   CLK_CTL_PD	    0x04  /* PLL power down */

/* Tx ring descriptor status byte */
#define	TX_STAT_ACTIVE      0x80  /* Chip owns the buffer */
#define	TX_STAT_DISABLE_CRC 0x40  /* Chip does not send CRC */
#define	TX_STAT_BAD_CRC	    0x20  /* Force a bad CRC */
#define	TX_STAT_PULSE	    0x10  /* Send indication pulse */
#define	TX_STAT_FORCE_UNDR  0x08  /* Force underrun */
#define	TX_STAT_CLR_ENTX    0x04  /* Chip clears ENTX after Tx */
#define	TX_STAT_UNDER_RUN   0x01  /* Underrun occurred on this packet */

/* Rx ring descriptor status byte */
#define	RX_STAT_ACTIVE	    0x80  /* Chip owns the buffer */
#define RX_STAT_PHYERR	    0x40  /* Physical encoding error detected */
#define RX_STAT_CRCERR	    0x20  /* a CRC error occurred on this frame */
#define RX_STAT_LENGTH	    0x10  /* Frame length exceeded buffer length */
#define RX_STAT_OVERRUN	    0x08  /* The receive FIFO was overrun */
#define RX_STAT_SIRBAD	    0x04  /* Detected BOF data BOF (no EOF) */

#define RX_STAT_ANY_ERR	    0x7c  /* All Rx errors fatal to this frame */

#define TX_RING_SIZE           8
#define RX_RING_SIZE           8
#define MAX_FRAME_SIZE      2048 

/* This struct is accessed by the chip, so don't change it. The union is used
 * to make it easier to access the address field. This will however overwrite
 * the status byte, so you must remember to update it after using the addr 
 * field. dB.
 */
struct ring_entry {
	volatile __u16 count;     /* Tx/Rx count (bits 11:0) */
	__u16 unused;
	union {
		__u32 addr; /* Same as below, but will overwrite status */
		struct {
			__u16 addr_low;  /* Buffer address (bits 15:0)  */
			__u8  addr_high; /* Buffer address (bits 23:16) */
			volatile __u8 status; /* Status for this buffer */
		} s;
	} u;
} PACK;

struct eagle_eye_cb {
	struct irda_device idev;    /* IrDA device */
	struct pci_dev    *pdev;    /* PCI device info */
	int base;                   /* IO base address */

	__u8 *ring_mem;   /* Memory chunk used to contain rings */
	__u8 *ring_base;  /* Start of rings inside ring_mem (aligned to 1K) */

	struct ring_entry *tx_ring; /* Start of Tx ring entries */
	struct ring_entry *rx_ring; /* Start of Rx ring entries */

	__u8 *tx_buf[TX_RING_SIZE];
	__u8 *rx_buf[RX_RING_SIZE];
	
	int cur_tx;   /* Next free entry for transmit */
	int cur_rx;   /* Next free entry for receive */
	int dirty_tx; /* The Tx ring entries to be free()ed. */
	int dirty_rx; /* The Rx ring entries to be free()ed. */

	int tx_full;
	struct timeval stamp;
};

#endif /* EAGLE_EYE_H */
