/*
* NETJet mISDN driver
*
* Author Karsten Keil <keil@isdn4linux.de>
*
* Copyright 2009 by Karsten Keil <keil@isdn4linux.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/delay.h>
#include <linux/mISDNhw.h>
#include <linux/slab.h>
#include "ipac.h"
#include "iohelper.h"
#include "netjet.h"
#include <linux/isdn/hdlc.h>
#define NETJET_REV "2.0"
enum nj_types {
NETJET_S_TJ300,
NETJET_S_TJ320,
ENTERNOW__TJ320,
};
struct tiger_dma {
size_t size;
u32 *start;
int idx;
u32 dmastart;
u32 dmairq;
u32 dmaend;
u32 dmacur;
};
struct tiger_hw;
struct tiger_ch {
struct bchannel bch;
struct tiger_hw *nj;
int idx;
int free;
int lastrx;
u16 rxstate;
u16 txstate;
struct isdnhdlc_vars hsend;
struct isdnhdlc_vars hrecv;
u8 *hsbuf;
u8 *hrbuf;
};
#define TX_INIT 0x0001
#define TX_IDLE 0x0002
#define TX_RUN 0x0004
#define TX_UNDERRUN 0x0100
#define RX_OVERRUN 0x0100
#define LOG_SIZE 64
struct tiger_hw {
struct list_head list;
struct pci_dev *pdev;
char name[MISDN_MAX_IDLEN];
enum nj_types typ;
int irq;
u32 irqcnt;
u32 base;
size_t base_s;
dma_addr_t dma;
void *dma_p;
spinlock_t lock; /* lock HW */
struct isac_hw isac;
struct tiger_dma send;
struct tiger_dma recv;
struct tiger_ch bc[2];
u8 ctrlreg;
u8 dmactrl;
u8 auxd;
u8 last_is0;
u8 irqmask0;
char log[LOG_SIZE];
};
static LIST_HEAD(Cards);
static DEFINE_RWLOCK(card_lock); /* protect Cards */
static u32 debug;
static int nj_cnt;
static void
_set_debug(struct tiger_hw *card)
{
card->isac.dch.debug = debug;
card->bc[0].bch.debug = debug;
card->bc[1].bch.debug = debug;
}
static int
set_debug(const char *val, struct kernel_param *kp)
{
int ret;
struct tiger_hw *card;
ret = param_set_uint(val, kp);
if (!ret) {
read_lock(&card_lock);
list_for_each_entry(card, &Cards, list)
_set_debug(card);
read_unlock(&card_lock);
}
return ret;
}
MODULE_AUTHOR("Karsten Keil");
MODULE_LICENSE("GPL v2");
MODULE_VERSION(NETJET_REV);
module_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(debug, "Netjet debug mask");
static void
nj_disable_hwirq(struct tiger_hw *card)
{
outb(0, card->base + NJ_IRQMASK0);
outb(0, card->base + NJ_IRQMASK1);
}
static u8
ReadISAC_nj(void *p, u8 offset)
{
struct tiger_hw