| /* $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); | |
| extern const struct file_operations b1ctl_proc_fops; | |
| 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); | |
| extern const struct file_operations b1dmactl_proc_fops; | |
| #endif /* _AVMCARD_H_ */ |