b1.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:17k
- /* $Id: b1.c,v 1.1.4.1 2001/11/20 14:19:34 kai Exp $
- *
- * Common module for AVM B1 cards.
- *
- * 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/kernelcapi.h>
- #include <asm/io.h>
- #include <linux/init.h>
- #include <asm/uaccess.h>
- #include <linux/netdevice.h>
- #include "capilli.h"
- #include "avmcard.h"
- #include "capicmd.h"
- #include "capiutil.h"
- static char *revision = "$Revision: 1.1.4.1 $";
- /* ------------------------------------------------------------- */
- MODULE_DESCRIPTION("CAPI4Linux: Common support for active AVM cards");
- MODULE_AUTHOR("Carsten Paeth");
- MODULE_LICENSE("GPL");
- /* ------------------------------------------------------------- */
- int b1_irq_table[16] =
- {0,
- 0,
- 0,
- 192, /* irq 3 */
- 32, /* irq 4 */
- 160, /* irq 5 */
- 96, /* irq 6 */
- 224, /* irq 7 */
- 0,
- 64, /* irq 9 */
- 80, /* irq 10 */
- 208, /* irq 11 */
- 48, /* irq 12 */
- 0,
- 0,
- 112, /* irq 15 */
- };
- /* ------------------------------------------------------------- */
- int b1_detect(unsigned int base, enum avmcardtype cardtype)
- {
- int onoff, i;
- /*
- * Statusregister 0000 00xx
- */
- if ((inb(base + B1_INSTAT) & 0xfc)
- || (inb(base + B1_OUTSTAT) & 0xfc))
- return 1;
- /*
- * Statusregister 0000 001x
- */
- b1outp(base, B1_INSTAT, 0x2); /* enable irq */
- /* b1outp(base, B1_OUTSTAT, 0x2); */
- if ((inb(base + B1_INSTAT) & 0xfe) != 0x2
- /* || (inb(base + B1_OUTSTAT) & 0xfe) != 0x2 */)
- return 2;
- /*
- * Statusregister 0000 000x
- */
- b1outp(base, B1_INSTAT, 0x0); /* disable irq */
- b1outp(base, B1_OUTSTAT, 0x0);
- if ((inb(base + B1_INSTAT) & 0xfe)
- || (inb(base + B1_OUTSTAT) & 0xfe))
- return 3;
-
- for (onoff = !0, i= 0; i < 10 ; i++) {
- b1_set_test_bit(base, cardtype, onoff);
- if (b1_get_test_bit(base, cardtype) != onoff)
- return 4;
- onoff = !onoff;
- }
- if (cardtype == avm_m1)
- return 0;
- if ((b1_rd_reg(base, B1_STAT1(cardtype)) & 0x0f) != 0x01)
- return 5;
- return 0;
- }
- void b1_getrevision(avmcard *card)
- {
- card->class = inb(card->port + B1_ANALYSE);
- card->revision = inb(card->port + B1_REVISION);
- }
- int b1_load_t4file(avmcard *card, capiloaddatapart * t4file)
- {
- unsigned char buf[256];
- unsigned char *dp;
- int i, left, retval;
- unsigned int base = card->port;
- dp = t4file->data;
- left = t4file->len;
- while (left > sizeof(buf)) {
- if (t4file->user) {
- retval = copy_from_user(buf, dp, sizeof(buf));
- if (retval)
- return -EFAULT;
- } else {
- memcpy(buf, dp, sizeof(buf));
- }
- for (i = 0; i < sizeof(buf); i++)
- if (b1_save_put_byte(base, buf[i]) < 0) {
- printk(KERN_ERR "%s: corrupted firmware file ?n",
- card->name);
- return -EIO;
- }
- left -= sizeof(buf);
- dp += sizeof(buf);
- }
- if (left) {
- if (t4file->user) {
- retval = copy_from_user(buf, dp, left);
- if (retval)
- return -EFAULT;
- } else {
- memcpy(buf, dp, left);
- }
- for (i = 0; i < left; i++)
- if (b1_save_put_byte(base, buf[i]) < 0) {
- printk(KERN_ERR "%s: corrupted firmware file ?n",
- card->name);
- return -EIO;
- }
- }
- return 0;
- }
- int b1_load_config(avmcard *card, capiloaddatapart * config)
- {
- unsigned char buf[256];
- unsigned char *dp;
- unsigned int base = card->port;
- int i, j, left, retval;
- dp = config->data;
- left = config->len;
- if (left) {
- b1_put_byte(base, SEND_CONFIG);
- b1_put_word(base, 1);
- b1_put_byte(base, SEND_CONFIG);
- b1_put_word(base, left);
- }
- while (left > sizeof(buf)) {
- if (config->user) {
- retval = copy_from_user(buf, dp, sizeof(buf));
- if (retval)
- return -EFAULT;
- } else {
- memcpy(buf, dp, sizeof(buf));
- }
- for (i = 0; i < sizeof(buf); ) {
- b1_put_byte(base, SEND_CONFIG);
- for (j=0; j < 4; j++) {
- b1_put_byte(base, buf[i++]);
- }
- }
- left -= sizeof(buf);
- dp += sizeof(buf);
- }
- if (left) {
- if (config->user) {
- retval = copy_from_user(buf, dp, left);
- if (retval)
- return -EFAULT;
- } else {
- memcpy(buf, dp, left);
- }
- for (i = 0; i < left; ) {
- b1_put_byte(base, SEND_CONFIG);
- for (j=0; j < 4; j++) {
- if (i < left)
- b1_put_byte(base, buf[i++]);
- else
- b1_put_byte(base, 0);
- }
- }
- }
- return 0;
- }
- int b1_loaded(avmcard *card)
- {
- unsigned int base = card->port;
- unsigned long stop;
- unsigned char ans;
- unsigned long tout = 2;
- for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
- if (b1_tx_empty(base))
- break;
- }
- if (!b1_tx_empty(base)) {
- printk(KERN_ERR "%s: b1_loaded: tx err, corrupted t4 file ?n",
- card->name);
- return 0;
- }
- b1_put_byte(base, SEND_POLL);
- for (stop = jiffies + tout * HZ; time_before(jiffies, stop);) {
- if (b1_rx_full(base)) {
- if ((ans = b1_get_byte(base)) == RECEIVE_POLL) {
- return 1;
- }
- printk(KERN_ERR "%s: b1_loaded: got 0x%x, firmware not runningn",
- card->name, ans);
- return 0;
- }
- }
- printk(KERN_ERR "%s: b1_loaded: firmware not runningn", card->name);
- return 0;
- }
- /* ------------------------------------------------------------- */
- int b1_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;
- b1_reset(port);
- if ((retval = b1_load_t4file(card, &data->firmware))) {
- b1_reset(port);
- printk(KERN_ERR "%s: failed to load t4file!!n",
- card->name);
- return retval;
- }
- b1_disable_irq(port);
- if (data->configuration.len > 0 && data->configuration.data) {
- if ((retval = b1_load_config(card, &data->configuration))) {
- b1_reset(port);
- printk(KERN_ERR "%s: failed to load config!!n",
- card->name);
- return retval;
- }
- }
- if (!b1_loaded(card)) {
- printk(KERN_ERR "%s: failed to load t4file.n", card->name);
- return -EIO;
- }
- save_flags(flags);
- cli();
- b1_setinterrupt(port, card->irq, card->cardtype);
- b1_put_byte(port, SEND_INIT);
- b1_put_word(port, CAPI_MAXAPPL);
- b1_put_word(port, AVM_NCCI_PER_CHANNEL*2);
- b1_put_word(port, ctrl->cnr - 1);
- restore_flags(flags);
- return 0;
- }
- void b1_reset_ctr(struct capi_ctr *ctrl)
- {
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
- unsigned int port = card->port;
- b1_reset(port);
- b1_reset(port);
- memset(cinfo->version, 0, sizeof(cinfo->version));
- ctrl->reseted(ctrl);
- }
- void b1_register_appl(struct capi_ctr *ctrl,
- __u16 appl,
- capi_register_params *rp)
- {
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
- unsigned int port = card->port;
- unsigned long flags;
- int nconn, want = rp->level3cnt;
- if (want > 0) nconn = want;
- else nconn = ctrl->profile.nbchannel * -want;
- if (nconn == 0) nconn = ctrl->profile.nbchannel;
- save_flags(flags);
- cli();
- b1_put_byte(port, SEND_REGISTER);
- b1_put_word(port, appl);
- b1_put_word(port, 1024 * (nconn+1));
- b1_put_word(port, nconn);
- b1_put_word(port, rp->datablkcnt);
- b1_put_word(port, rp->datablklen);
- restore_flags(flags);
- ctrl->appl_registered(ctrl, appl);
- }
- void b1_release_appl(struct capi_ctr *ctrl, __u16 appl)
- {
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
- unsigned int port = card->port;
- unsigned long flags;
- save_flags(flags);
- cli();
- b1_put_byte(port, SEND_RELEASE);
- b1_put_word(port, appl);
- restore_flags(flags);
- }
- void b1_send_message(struct capi_ctr *ctrl, struct sk_buff *skb)
- {
- avmctrl_info *cinfo = (avmctrl_info *)(ctrl->driverdata);
- avmcard *card = cinfo->card;
- unsigned int port = card->port;
- unsigned long flags;
- __u16 len = CAPIMSG_LEN(skb->data);
- __u8 cmd = CAPIMSG_COMMAND(skb->data);
- __u8 subcmd = CAPIMSG_SUBCOMMAND(skb->data);
- save_flags(flags);
- cli();
- if (CAPICMD(cmd, subcmd) == CAPI_DATA_B3_REQ) {
- __u16 dlen = CAPIMSG_DATALEN(skb->data);
- b1_put_byte(port, SEND_DATA_B3_REQ);
- b1_put_slice(port, skb->data, len);
- b1_put_slice(port, skb->data + len, dlen);
- } else {
- b1_put_byte(port, SEND_MESSAGE);
- b1_put_slice(port, skb->data, len);
- }
- restore_flags(flags);
- dev_kfree_skb_any(skb);
- }
- /* ------------------------------------------------------------- */
- void b1_parse_version(avmctrl_info *cinfo)
- {
- struct capi_ctr *ctrl = cinfo->capi_ctrl;
- avmcard *card = cinfo->card;
- capi_profile *profp;
- __u8 *dversion;
- __u8 flag;
- int i, j;
- for (j = 0; j < AVM_MAXVERSION; j++)
- cinfo->version[j] = "