mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
![Alexey Dobriyan](/assets/img/avatar_default.png)
Convert code away from ->read_proc/->write_proc interfaces. Switch to
proc_create()/proc_create_data() which make addition of proc entries
reliable wrt NULL ->proc_fops, NULL ->data and so on.
Problem with ->read_proc et al is described here commit
786d7e1612
"Fix rmmod/read/write races in
/proc entries"
[akpm@linux-foundation.org: CONFIG_PROC_FS=n build fix]
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Tilman Schmidt <tilman@imap.cc>
Signed-off-by: Karsten Keil <keil@b1-systems.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
581 lines
14 KiB
C
581 lines
14 KiB
C
/* $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_ */
|