📄 t1isa.c
字号:
/* $Id: t1isa.c,v 1.1.2.3 2004/02/10 01:07:12 keil Exp $ * * Module for AVM T1 HEMA-card. * * 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. * */#include <linux/module.h>#include <linux/kernel.h>#include <linux/skbuff.h>#include <linux/delay.h>#include <linux/mm.h>#include <linux/interrupt.h>#include <linux/ioport.h>#include <linux/capi.h>#include <linux/netdevice.h>#include <linux/kernelcapi.h>#include <linux/init.h>#include <linux/pci.h>#include <asm/io.h>#include <linux/isdn/capicmd.h>#include <linux/isdn/capiutil.h>#include <linux/isdn/capilli.h>#include "avmcard.h"/* ------------------------------------------------------------- */static char *revision = "$Revision: 1.1.2.3 $";/* ------------------------------------------------------------- */MODULE_DESCRIPTION("CAPI4Linux: Driver for AVM T1 HEMA ISA card");MODULE_AUTHOR("Carsten Paeth");MODULE_LICENSE("GPL");/* ------------------------------------------------------------- */static int hema_irq_table[16] ={0, 0, 0, 0x80, /* irq 3 */ 0, 0x90, /* irq 5 */ 0, 0xA0, /* irq 7 */ 0, 0xB0, /* irq 9 */ 0xC0, /* irq 10 */ 0xD0, /* irq 11 */ 0xE0, /* irq 12 */ 0, 0, 0xF0, /* irq 15 */};static int t1_detectandinit(unsigned int base, unsigned irq, int cardnr){ unsigned char cregs[8]; unsigned char reverse_cardnr; unsigned char dummy; int i; reverse_cardnr = ((cardnr & 0x01) << 3) | ((cardnr & 0x02) << 1) | ((cardnr & 0x04) >> 1) | ((cardnr & 0x08) >> 3); cregs[0] = (HEMA_VERSION_ID << 4) | (reverse_cardnr & 0xf); cregs[1] = 0x00; /* fast & slow link connected to CON1 */ cregs[2] = 0x05; /* fast link 20MBit, slow link 20 MBit */ cregs[3] = 0; cregs[4] = 0x11; /* zero wait state */ cregs[5] = hema_irq_table[irq & 0xf]; cregs[6] = 0; cregs[7] = 0; /* * no one else should use the ISA bus in this moment, * but no function there to prevent this :-( * save_flags(flags); cli(); */ /* board reset */ t1outp(base, T1_RESETBOARD, 0xf); mdelay(100); dummy = t1inp(base, T1_FASTLINK+T1_OUTSTAT); /* first read */ /* write config */ dummy = (base >> 4) & 0xff; for (i=1;i<=0xf;i++) t1outp(base, i, dummy); t1outp(base, HEMA_PAL_ID & 0xf, dummy); t1outp(base, HEMA_PAL_ID >> 4, cregs[0]); for(i=1;i<7;i++) t1outp(base, 0, cregs[i]); t1outp(base, ((base >> 4)) & 0x3, cregs[7]); /* restore_flags(flags); */ mdelay(100); t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0); mdelay(10); t1outp(base, T1_FASTLINK+T1_RESETLINK, 1); t1outp(base, T1_SLOWLINK+T1_RESETLINK, 1); mdelay(100); t1outp(base, T1_FASTLINK+T1_RESETLINK, 0); t1outp(base, T1_SLOWLINK+T1_RESETLINK, 0); mdelay(10); t1outp(base, T1_FASTLINK+T1_ANALYSE, 0); mdelay(5); t1outp(base, T1_SLOWLINK+T1_ANALYSE, 0); if (t1inp(base, T1_FASTLINK+T1_OUTSTAT) != 0x1) /* tx empty */ return 1; if (t1inp(base, T1_FASTLINK+T1_INSTAT) != 0x0) /* rx empty */ return 2; if (t1inp(base, T1_FASTLINK+T1_IRQENABLE) != 0x0) return 3; if ((t1inp(base, T1_FASTLINK+T1_FIFOSTAT) & 0xf0) != 0x70) return 4; if ((t1inp(base, T1_FASTLINK+T1_IRQMASTER) & 0x0e) != 0) return 5; if ((t1inp(base, T1_FASTLINK+T1_IDENT) & 0x7d) != 1) return 6; if (t1inp(base, T1_SLOWLINK+T1_OUTSTAT) != 0x1) /* tx empty */ return 7; if ((t1inp(base, T1_SLOWLINK+T1_IRQMASTER) & 0x0e) != 0) return 8; if ((t1inp(base, T1_SLOWLINK+T1_IDENT) & 0x7d) != 0) return 9; return 0;}static irqreturn_t t1isa_interrupt(int interrupt, void *devptr, struct pt_regs *regs){ avmcard *card = devptr; avmctrl_info *cinfo = &card->ctrlinfo[0]; struct capi_ctr *ctrl = &cinfo->capi_ctrl; unsigned char b1cmd; struct sk_buff *skb; unsigned ApplId; unsigned MsgLen; unsigned DataB3Len; unsigned NCCI; unsigned WindowSize; unsigned long flags; spin_lock_irqsave(&card->lock, flags); while (b1_rx_full(card->port)) { b1cmd = b1_get_byte(card->port); switch (b1cmd) { case RECEIVE_DATA_B3_IND: ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); DataB3Len = t1_get_slice(card->port, card->databuf); spin_unlock_irqrestore(&card->lock, flags); if (MsgLen < 30) { /* not CAPI 64Bit */ memset(card->msgbuf+MsgLen, 0, 30-MsgLen); MsgLen = 30; CAPIMSG_SETLEN(card->msgbuf, 30); } if (!(skb = alloc_skb(DataB3Len+MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); memcpy(skb_put(skb, DataB3Len), card->databuf, DataB3Len); capi_ctr_handle_message(ctrl, ApplId, skb); } break; case RECEIVE_MESSAGE: ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); spin_unlock_irqrestore(&card->lock, flags); if (!(skb = alloc_skb(MsgLen, GFP_ATOMIC))) { printk(KERN_ERR "%s: incoming packet dropped\n", card->name); } else { memcpy(skb_put(skb, MsgLen), card->msgbuf, MsgLen); if (CAPIMSG_CMD(skb->data) == CAPI_DATA_B3) capilib_data_b3_conf(&cinfo->ncci_head, ApplId, CAPIMSG_NCCI(skb->data), CAPIMSG_MSGID(skb->data)); capi_ctr_handle_message(ctrl, ApplId, skb); } break; case RECEIVE_NEW_NCCI: ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); WindowSize = b1_get_word(card->port); spin_unlock_irqrestore(&card->lock, flags); capilib_new_ncci(&cinfo->ncci_head, ApplId, NCCI, WindowSize); break; case RECEIVE_FREE_NCCI: ApplId = b1_get_word(card->port); NCCI = b1_get_word(card->port); spin_unlock_irqrestore(&card->lock, flags); if (NCCI != 0xffffffff) capilib_free_ncci(&cinfo->ncci_head, ApplId, NCCI); break; case RECEIVE_START: b1_put_byte(card->port, SEND_POLLACK); spin_unlock_irqrestore(&card->lock, flags); capi_ctr_resume_output(ctrl); break; case RECEIVE_STOP: spin_unlock_irqrestore(&card->lock, flags); capi_ctr_suspend_output(ctrl); break; case RECEIVE_INIT: cinfo->versionlen = t1_get_slice(card->port, cinfo->versionbuf); spin_unlock_irqrestore(&card->lock, flags); b1_parse_version(cinfo); printk(KERN_INFO "%s: %s-card (%s) now active\n", card->name, cinfo->version[VER_CARDTYPE], cinfo->version[VER_DRIVER]); capi_ctr_ready(ctrl); break; case RECEIVE_TASK_READY: ApplId = (unsigned) b1_get_word(card->port); MsgLen = t1_get_slice(card->port, card->msgbuf); spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' || card->msgbuf[MsgLen-1] == '\r')) { card->msgbuf[MsgLen-1] = 0; MsgLen--; } printk(KERN_INFO "%s: task %d \"%s\" ready.\n", card->name, ApplId, card->msgbuf); break; case RECEIVE_DEBUGMSG: MsgLen = t1_get_slice(card->port, card->msgbuf); spin_unlock_irqrestore(&card->lock, flags); card->msgbuf[MsgLen] = 0; while ( MsgLen > 0 && ( card->msgbuf[MsgLen-1] == '\n' || card->msgbuf[MsgLen-1] == '\r')) { card->msgbuf[MsgLen-1] = 0; MsgLen--; } printk(KERN_INFO "%s: DEBUG: %s\n", card->name, card->msgbuf); break; case 0xff: spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: card reseted ?\n", card->name); return IRQ_HANDLED; default: spin_unlock_irqrestore(&card->lock, flags); printk(KERN_ERR "%s: b1_interrupt: 0x%x ???\n", card->name, b1cmd); return IRQ_NONE; } } return IRQ_HANDLED;}/* ------------------------------------------------------------- */static int t1isa_load_firmware(struct capi_ctr *ctrl, capiloaddata *data){ avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata); avmcard *card = cinfo->card; unsigned int port = card->port; unsigned long flags; int retval; t1_disable_irq(port); b1_reset(port); if ((retval = b1_load_t4file(card, &data->firmware))) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -