text: /* $Id: avmcard.h,v 1.1.4.1.2.1 2001/12/21 15:00:17 kai Exp $
   *
   * Copyright 1999 by Carsten Paeth <calle@calle.de>
   *
   * This software may be used and distributed according to the terms
   * of the GNU General Public License, incorporated herein by reference.
   *
   */
  
  #ifndef _AVMCARD_H_
  #define _AVMCARD_H_
  
  #include <linux/spinlock.h>
  #include <linux/list.h>
  #include <linux/interrupt.h>
  
  #define	AVMB1_PORTLEN		0x1f
  #define AVM_MAXVERSION		8
  #define AVM_NCCI_PER_CHANNEL	4
  
  /*
   * Versions
   */
  
  #define	VER_DRIVER	0
  #define	VER_CARDTYPE	1
  #define	VER_HWID	2
  #define	VER_SERIAL	3
  #define	VER_OPTION	4
  #define	VER_PROTO	5
  #define	VER_PROFILE	6
  #define	VER_CAPI	7
  
  enum avmcardtype {
  	avm_b1isa,
  	avm_b1pci,
  	avm_b1pcmcia,
  	avm_m1,
  	avm_m2,
  	avm_t1isa,
  	avm_t1pci,
  	avm_c4,
  	avm_c2
  };
  
  typedef struct avmcard_dmabuf {
  	long        size;
  	u8       *dmabuf;
  	dma_addr_t  dmaaddr;
  } avmcard_dmabuf;
  
  typedef struct avmcard_dmainfo {
  	u32                recvlen;
  	avmcard_dmabuf       recvbuf;
  
  	avmcard_dmabuf       sendbuf;
  	struct sk_buff_head  send_queue;
  
  	struct pci_dev      *pcidev;
  } avmcard_dmainfo;
  
  typedef	struct avmctrl_info {
  	char cardname[32];
  
  	int versionlen;
  	char versionbuf[1024];
  	char *version[AVM_MAXVERSION];
  
  	char infobuf[128];	/* for function procinfo */
  
  	struct avmcard  *card;
  	struct capi_ctr  capi_ctrl;
  
  	struct list_head ncci_head;
  } avmctrl_info;
  
  typedef struct avmcard {
  	char name[32];
  
  	spinlock_t lock;
  	unsigned int port;
  	unsigned irq;
  	unsigned long membase;
  	enum avmcardtype cardtype;
  	unsigned char revision;
  	unsigned char class;
  	int cardnr; /* for t1isa */
  
  	char msgbuf[128];	/* capimsg msg part */
  	char databuf[2048];	/* capimsg data part */
  
  	void __iomem *mbase;
  	volatile u32 csr;
  	avmcard_dmainfo *dma;
  
  	struct avmctrl_info *ctrlinfo;
  
  	u_int nr_controllers;
  	u_int nlogcontr;
  	struct list_head list;
  } avmcard;
  
  extern int b1_irq_table[16];
  
  /*
   * LLI Messages to the ISDN-ControllerISDN Controller
   */
  
  #define	SEND_POLL		0x72	/*
  					 * after load <- RECEIVE_POLL
  					 */
  #define SEND_INIT		0x11	/*
  					 * first message <- RECEIVE_INIT
  					 * int32 NumApplications  int32
  					 * NumNCCIs int32 BoardNumber
  					 */
  #define SEND_REGISTER		0x12	/*
  					 * register an application int32
  					 * ApplIDId int32 NumMessages
  					 * int32 NumB3Connections int32
  					 * NumB3Blocks int32 B3Size
  					 *
  					 * AnzB3Connection != 0 &&
  					 * AnzB3Blocks >= 1 && B3Size >= 1
  					 */
  #define SEND_RELEASE		0x14	/*
  					 * deregister an application int32
  					 * ApplID
  					 */
  #define SEND_MESSAGE		0x15	/*
  					 * send capi-message int32 length
  					 * capi-data ...
  					 */
  #define SEND_DATA_B3_REQ	0x13	/*
  					 * send capi-data-message int32
  					 * MsgLength capi-data ... int32
  					 * B3Length data ....
  					 */
  
  #define SEND_CONFIG		0x21    /*
  					 */
  
  #define SEND_POLLACK		0x73    /* T1 Watchdog */
  
  /*
   * LLI Messages from the ISDN-ControllerISDN Controller
   */
  
  #define RECEIVE_POLL		0x32	/*
  					 * <- after SEND_POLL
  					 */
  #define RECEIVE_INIT		0x27	/*
  					 * <- after SEND_INIT int32 length
  					 * byte total length b1struct board
  					 * driver revision b1struct card
  					 * type b1struct reserved b1struct
  					 * serial number b1struct driver
  					 * capability b1struct d-channel
  					 * protocol b1struct CAPI-2.0
  					 * profile b1struct capi version
  					 */
  #define RECEIVE_MESSAGE		0x21	/*
  					 * <- after SEND_MESSAGE int32
  					 * AppllID int32 Length capi-data
  					 * ....
  					 */
  #define RECEIVE_DATA_B3_IND	0x22	/*
  					 * received data int32 AppllID
  					 * int32 Length capi-data ...
  					 * int32 B3Length data ...
  					 */
  #define RECEIVE_START		0x23	/*
  					 * Handshake
  					 */
  #define RECEIVE_STOP		0x24	/*
  					 * Handshake
  					 */
  #define RECEIVE_NEW_NCCI	0x25	/*
  					 * int32 AppllID int32 NCCI int32
  					 * WindowSize
  					 */
  #define RECEIVE_FREE_NCCI	0x26	/*
  					 * int32 AppllID int32 NCCI
  					 */
  #define RECEIVE_RELEASE		0x26	/*
  					 * int32 AppllID int32 0xffffffff
  					 */
  #define RECEIVE_TASK_READY	0x31	/*
  					 * int32 tasknr
  					 * int32 Length Taskname ...
  					 */
  #define RECEIVE_DEBUGMSG	0x71	/*
  					 * int32 Length message
  					 *
  					 */
  #define RECEIVE_POLLDWORD	0x75	/* t1pci in dword mode */
  
  #define WRITE_REGISTER		0x00
  #define READ_REGISTER		0x01
  
  /*
   * port offsets
   */
  
  #define B1_READ			0x00
  #define B1_WRITE		0x01
  #define B1_INSTAT		0x02
  #define B1_OUTSTAT		0x03
  #define B1_ANALYSE		0x04
  #define B1_REVISION		0x05
  #define B1_RESET		0x10
  
  
  #define B1_STAT0(cardtype)  ((cardtype) == avm_m1 ? 0x81200000l : 0x80A00000l)
  #define B1_STAT1(cardtype)  (0x80E00000l)
  
  /* ---------------------------------------------------------------- */
  
  static inline unsigned char b1outp(unsigned int base,
  				   unsigned short offset,
  				   unsigned char value)
  {
  	outb(value, base + offset);
  	return inb(base + B1_ANALYSE);
  }
  
  
  static inline int b1_rx_full(unsigned int base)
  {
  	return inb(base + B1_INSTAT) & 0x1;
  }
  
  static inline unsigned char b1_get_byte(unsigned int base)
  {
  	unsigned long stop = jiffies + 1 * HZ;	/* maximum wait time 1 sec */
  	while (!b1_rx_full(base) && time_before(jiffies, stop));
  	if (b1_rx_full(base))
  		return inb(base + B1_READ);
  	printk(KERN_CRIT "b1lli(0x%x): rx not full after 1 second\n", base);
  	return 0;
  }
  
  static inline unsigned int b1_get_word(unsigned int base)
  {
  	unsigned int val = 0;
  	val |= b1_get_byte(base);
  	val |= (b1_get_byte(base) << 8);
  	val |= (b1_get_byte(base) << 16);
  	val |= (b1_get_byte(base) << 24);
  	return val;
  }
  
  static inline int b1_tx_empty(unsigned int base)
  {
  	return inb(base + B1_OUTSTAT) & 0x1;
  }
  
  static inline void b1_put_byte(unsigned int base, unsigned char val)
  {
  	while (!b1_tx_empty(base));
  	b1outp(base, B1_WRITE, val);
  }
  
  static inline int b1_save_put_byte(unsigned int base, unsigned char val)
  {
  	unsigned long stop = jiffies + 2 * HZ;
  	while (!b1_tx_empty(base) && time_before(jiffies, stop));
  	if (!b1_tx_empty(base)) return -1;
  	b1outp(base, B1_WRITE, val);
  	return 0;
  }
  
  static inline void b1_put_word(unsigned int base, unsigned int val)
  {
  	b1_put_byte(base, val & 0xff);
  	b1_put_byte(base, (val >> 8) & 0xff);
  	b1_put_byte(base, (val >> 16) & 0xff);
  	b1_put_byte(base, (val >> 24) & 0xff);
  }
  
  static inline unsigned int b1_get_slice(unsigned int base,
  					unsigned char *dp)
  {
  	unsigned int len, i;
  
  	len = i = b1_get_word(base);
  	while (i-- > 0) *dp++ = b1_get_byte(base);
  	return len;
  }
  
  static inline void b1_put_slice(unsigned int base,
  				unsigned char *dp, unsigned int len)
  {
  	unsigned i = len;
  	b1_put_word(base, i);
  	while (i-- > 0)
  		b1_put_byte(base, *dp++);
  }
  
  static void b1_wr_reg(unsigned int base,
  		      unsigned int reg,
  		      unsigned int value)
  {
  	b1_put_byte(base, WRITE_REGISTER);
  	b1_put_word(base, reg);
  	b1_put_word(base, value);
  }
  
  static inline unsigned int b1_rd_reg(unsigned int base,
  				     unsigned int reg)
  {
  	b1_put_byte(base, READ_REGISTER);
  	b1_put_word(base, reg);
  	return b1_get_word(base);
  
  }
  
  static inline void b1_reset(unsigned int base)
  {
  	b1outp(base, B1_RESET, 0);
  	mdelay(55 * 2);	/* 2 TIC's */
  
  	b1outp(base, B1_RESET, 1);
  	mdelay(55 * 2);	/* 2 TIC's */
  
  	b1outp(base, B1_RESET, 0);
  	mdelay(55 * 2);	/* 2 TIC's */
  }
  
  static inline unsigned char b1_disable_irq(unsigned int base)
  {
  	return b1outp(base, B1_INSTAT, 0x00);
  }
  
  /* ---------------------------------------------------------------- */
  
  static inline void b1_set_test_bit(unsigned int base,
  				   enum avmcardtype cardtype,
  				   int onoff)
  {
  	b1_wr_reg(base, B1_STAT0(cardtype), onoff ? 0x21 : 0x20);
  }
  
  static inline int b1_get_test_bit(unsigned int base,
  				  enum avmcardtype cardtype)
  {
  	return (b1_rd_reg(base, B1_STAT0(cardtype)) & 0x01) != 0;
  }
  
  /* ---------------------------------------------------------------- */
  
  #define T1_FASTLINK		0x00
  #define T1_SLOWLINK		0x08
  
  #define T1_READ			B1_READ
  #define T1_WRITE		B1_WRITE
  #define T1_INSTAT		B1_INSTAT
  #define T1_OUTSTAT		B1_OUTSTAT
  #define T1_IRQENABLE		0x05
  #define T1_FIFOSTAT		0x06
  #define T1_RESETLINK		0x10
  #define T1_ANALYSE		0x11
  #define T1_IRQMASTER		0x12
  #define T1_IDENT		0x17
  #define T1_RESETBOARD		0x1f
  
  #define	T1F_IREADY		0x01
  #define	T1F_IHALF		0x02
  #define	T1F_IFULL		0x04
  #define	T1F_IEMPTY		0x08
  #define	T1F_IFLAGS		0xF0
  
  #define	T1F_OREADY		0x10
  #define	T1F_OHALF		0x20
  #define	T1F_OEMPTY		0x40
  #define	T1F_OFULL		0x80
  #define	T1F_OFLAGS		0xF0
  
  /* there are HEMA cards with 1k and 4k FIFO out */
  #define FIFO_OUTBSIZE		256
  #define FIFO_INPBSIZE		512
  
  #define HEMA_VERSION_ID		0
  #define HEMA_PAL_ID		0
  
  static inline void t1outp(unsigned int base,
  			  unsigned short offset,
  			  unsigned char value)
  {
  	outb(value, base + offset);
  }
  
  static inline unsigned char t1inp(unsigned int base,
  				  unsigned short offset)
  {
  	return inb(base + offset);
  }
  
  static inline int t1_isfastlink(unsigned int base)
  {
  	return (inb(base + T1_IDENT) & ~0x82) == 1;
  }
  
  static inline unsigned char t1_fifostatus(unsigned int base)
  {
  	return inb(base + T1_FIFOSTAT);
  }
  
  static inline unsigned int t1_get_slice(unsigned int base,
  					unsigned char *dp)
  {
  	unsigned int len, i;
  #ifdef FASTLINK_DEBUG
  	unsigned wcnt = 0, bcnt = 0;
  #endif
  
  	len = i = b1_get_word(base);
  	if (t1_isfastlink(base)) {
  		int status;
  		while (i > 0) {
  			status = t1_fifostatus(base) & (T1F_IREADY | T1F_IHALF);
  			if (i >= FIFO_INPBSIZE) status |= T1F_IFULL;
  
  			switch (status) {
  			case T1F_IREADY | T1F_IHALF | T1F_IFULL:
  				insb(base + B1_READ, dp, FIFO_INPBSIZE);
  				dp += FIFO_INPBSIZE;
  				i -= FIFO_INPBSIZE;
  #ifdef FASTLINK_DEBUG
  				wcnt += FIFO_INPBSIZE;
  #endif
  				break;
  			case T1F_IREADY | T1F_IHALF:
  				insb(base + B1_READ, dp, i);
  #ifdef FASTLINK_DEBUG
  				wcnt += i;
  #endif
  				dp += i;
  				i = 0;
  				break;
  			default:
  				*dp++ = b1_get_byte(base);
  				i--;
  #ifdef FASTLINK_DEBUG
  				bcnt++;
  #endif
  				break;
  			}
  		}
  #ifdef FASTLINK_DEBUG
  		if (wcnt)
  			printk(KERN_DEBUG "b1lli(0x%x): get_slice l=%d w=%d b=%d\n",
  			       base, len, wcnt, bcnt);
  #endif
  	} else {
  		while (i-- > 0)
  			*dp++ = b1_get_byte(base);
  	}
  	return len;
  }
  
  static inline void t1_put_slice(unsigned int base,
  				unsigned char *dp, unsigned int len)
  {
  	unsigned i = len;
  	b1_put_word(base, i);
  	if (t1_isfastlink(base)) {
  		int status;
  		while (i > 0) {
  			status = t1_fifostatus(base) & (T1F_OREADY | T1F_OHALF);
  			if (i >= FIFO_OUTBSIZE) status |= T1F_OEMPTY;
  			switch (status) {
  			case T1F_OREADY | T1F_OHALF | T1F_OEMPTY:
  				outsb(base + B1_WRITE, dp, FIFO_OUTBSIZE);
  				dp += FIFO_OUTBSIZE;
  				i -= FIFO_OUTBSIZE;
  				break;
  			case T1F_OREADY | T1F_OHALF:
  				outsb(base + B1_WRITE, dp, i);
  				dp += i;
  				i = 0;
  				break;
  			default:
  				b1_put_byte(base, *dp++);
  				i--;
  				break;
  			}
  		}
  	} else {
  		while (i-- > 0)
  			b1_put_byte(base, *dp++);
  	}
  }
  
  static inline void t1_disable_irq(unsigned int base)
  {
  	t1outp(base, T1_IRQMASTER, 0x00);
  }
  
  static inline void t1_reset(unsigned int base)
  {
  	/* reset T1 Controller */
  	b1_reset(base);
  	/* disable irq on HEMA */
  	t1outp(base, B1_INSTAT, 0x00);
  	t1outp(base, B1_OUTSTAT, 0x00);
  	t1outp(base, T1_IRQMASTER, 0x00);
  	/* reset HEMA board configuration */
  	t1outp(base, T1_RESETBOARD, 0xf);
  }
  
  static inline void b1_setinterrupt(unsigned int base, unsigned irq,
  				   enum avmcardtype cardtype)
  {
  	switch (cardtype) {
  	case avm_t1isa:
  		t1outp(base, B1_INSTAT, 0x00);
  		t1outp(base, B1_INSTAT, 0x02);
  		t1outp(base, T1_IRQMASTER, 0x08);
  		break;
  	case avm_b1isa:
  		b1outp(base, B1_INSTAT, 0x00);
  		b1outp(base, B1_RESET, b1_irq_table[irq]);
  		b1outp(base, B1_INSTAT, 0x02);
  		break;
  	default:
  	case avm_m1:
  	case avm_m2:
  	case avm_b1pci:
  		b1outp(base, B1_INSTAT, 0x00);
  		b1outp(base, B1_RESET, 0xf0);
  		b1outp(base, B1_INSTAT, 0x02);
  		break;
  	case avm_c4:
  	case avm_t1pci:
  		b1outp(base, B1_RESET, 0xf0);
  		break;
  	}
  }
  
  /* b1.c */
  avmcard *b1_alloc_card(int nr_controllers);
  void b1_free_card(avmcard *card);
  int b1_detect(unsigned int base, enum avmcardtype cardtype);
  void b1_getrevision(avmcard *card);
  int b1_load_t4file(avmcard *card, capiloaddatapart *t4file);
  int b1_load_config(avmcard *card, capiloaddatapart *config);
  int b1_loaded(avmcard *card);
  
  int b1_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
  void b1_reset_ctr(struct capi_ctr *ctrl);
  void b1_register_appl(struct capi_ctr *ctrl, u16 appl,
  		      capi_register_params *rp);
  void b1_release_appl(struct capi_ctr *ctrl, u16 appl);
  u16  b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
  void b1_parse_version(avmctrl_info *card);
  irqreturn_t b1_interrupt(int interrupt, void *devptr);
  
  int b1_proc_show(struct seq_file *m, void *v);
  
  avmcard_dmainfo *avmcard_dma_alloc(char *name, struct pci_dev *,
  				   long rsize, long ssize);
  void avmcard_dma_free(avmcard_dmainfo *);
  
  /* b1dma.c */
  int b1pciv4_detect(avmcard *card);
  int t1pci_detect(avmcard *card);
  void b1dma_reset(avmcard *card);
  irqreturn_t b1dma_interrupt(int interrupt, void *devptr);
  
  int b1dma_load_firmware(struct capi_ctr *ctrl, capiloaddata *data);
  void b1dma_reset_ctr(struct capi_ctr *ctrl);
  void b1dma_remove_ctr(struct capi_ctr *ctrl);
  void b1dma_register_appl(struct capi_ctr *ctrl,
  			 u16 appl,
  			 capi_register_params *rp);
  void b1dma_release_appl(struct capi_ctr *ctrl, u16 appl);
  u16  b1dma_send_message(struct capi_ctr *ctrl, struct sk_buff *skb);
  int b1dma_proc_show(struct seq_file *m, void *v);
  
  #endif /* _AVMCARD_H_ */
  