1a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil/* 2a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * NETJet mISDN driver 3a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * 4a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * Author Karsten Keil <keil@isdn4linux.de> 5a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * 6a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * Copyright 2009 by Karsten Keil <keil@isdn4linux.de> 7a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * 8a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * This program is free software; you can redistribute it and/or modify 9a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * it under the terms of the GNU General Public License version 2 as 10a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * published by the Free Software Foundation. 11a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * 12a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * This program is distributed in the hope that it will be useful, 13a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * but WITHOUT ANY WARRANTY; without even the implied warranty of 14a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * GNU General Public License for more details. 16a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * 17a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * You should have received a copy of the GNU General Public License 18a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * along with this program; if not, write to the Free Software 19a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 20a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * 21a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil */ 22a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 23a6b7a407865aab9f849dd99a71072b7cd1175116Alexey Dobriyan#include <linux/interrupt.h> 24a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#include <linux/module.h> 25a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#include <linux/pci.h> 26a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#include <linux/delay.h> 27a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#include <linux/mISDNhw.h> 285a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 29a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#include "ipac.h" 30a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#include "iohelper.h" 31a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#include "netjet.h" 32a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#include <linux/isdn/hdlc.h> 33a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 34a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#define NETJET_REV "2.0" 35a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 36a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilenum nj_types { 37a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil NETJET_S_TJ300, 38a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil NETJET_S_TJ320, 39a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ENTERNOW__TJ320, 40a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil}; 41a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 42a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstruct tiger_dma { 43a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil size_t size; 44a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 *start; 45a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int idx; 46a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 dmastart; 47a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 dmairq; 48a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 dmaend; 49a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 dmacur; 50a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil}; 51a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 52a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstruct tiger_hw; 53a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 54a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstruct tiger_ch { 55a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct bchannel bch; 56a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *nj; 57a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int idx; 58a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int free; 59a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int lastrx; 60a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u16 rxstate; 61a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u16 txstate; 62a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct isdnhdlc_vars hsend; 63a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct isdnhdlc_vars hrecv; 64a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 *hsbuf; 65a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 *hrbuf; 66a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil}; 67a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 68a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#define TX_INIT 0x0001 69a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#define TX_IDLE 0x0002 70a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#define TX_RUN 0x0004 71a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#define TX_UNDERRUN 0x0100 72a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#define RX_OVERRUN 0x0100 73a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 74a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil#define LOG_SIZE 64 75a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 76a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstruct tiger_hw { 77a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct list_head list; 78a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct pci_dev *pdev; 79a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil char name[MISDN_MAX_IDLEN]; 80a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil enum nj_types typ; 81a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int irq; 82a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 irqcnt; 83a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 base; 84a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil size_t base_s; 85a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil dma_addr_t dma; 86a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil void *dma_p; 87a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spinlock_t lock; /* lock HW */ 88a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct isac_hw isac; 89a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_dma send; 90a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_dma recv; 91a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_ch bc[2]; 92a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 ctrlreg; 93a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 dmactrl; 94a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 auxd; 95a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 last_is0; 96a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 irqmask0; 97a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil char log[LOG_SIZE]; 98a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil}; 99a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 100a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic LIST_HEAD(Cards); 101a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic DEFINE_RWLOCK(card_lock); /* protect Cards */ 102a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic u32 debug; 103a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int nj_cnt; 104a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 105a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 106a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil_set_debug(struct tiger_hw *card) 107a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 108a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.dch.debug = debug; 109a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[0].bch.debug = debug; 110a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[1].bch.debug = debug; 111a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 112a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 113a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 114a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilset_debug(const char *val, struct kernel_param *kp) 115a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 116a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret; 117a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card; 118a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 119a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = param_set_uint(val, kp); 120a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!ret) { 121a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil read_lock(&card_lock); 122a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil list_for_each_entry(card, &Cards, list) 123a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil _set_debug(card); 124a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil read_unlock(&card_lock); 125a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 126a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 127a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 128a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 129a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilMODULE_AUTHOR("Karsten Keil"); 130a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilMODULE_LICENSE("GPL v2"); 131a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilMODULE_VERSION(NETJET_REV); 132a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilmodule_param_call(debug, set_debug, param_get_uint, &debug, S_IRUGO | S_IWUSR); 133a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilMODULE_PARM_DESC(debug, "Netjet debug mask"); 134a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 135a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 136a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_disable_hwirq(struct tiger_hw *card) 137a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 138a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(0, card->base + NJ_IRQMASK0); 139a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(0, card->base + NJ_IRQMASK1); 140a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 141a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 142a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 143a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic u8 144a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilReadISAC_nj(void *p, u8 offset) 145a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 146a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = p; 147a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 ret; 148a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 149a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->auxd &= 0xfc; 150a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->auxd |= (offset >> 4) & 3; 151a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->auxd, card->base + NJ_AUXDATA); 152a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = inb(card->base + NJ_ISAC_OFF + ((offset & 0x0f) << 2)); 153a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 154a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 155a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 156a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 157a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilWriteISAC_nj(void *p, u8 offset, u8 value) 158a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 159a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = p; 160a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 161a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->auxd &= 0xfc; 162a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->auxd |= (offset >> 4) & 3; 163a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->auxd, card->base + NJ_AUXDATA); 164a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(value, card->base + NJ_ISAC_OFF + ((offset & 0x0f) << 2)); 165a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 166a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 167a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 168a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilReadFiFoISAC_nj(void *p, u8 offset, u8 *data, int size) 169a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 170a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = p; 171a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 172a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->auxd &= 0xfc; 173a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->auxd, card->base + NJ_AUXDATA); 174a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil insb(card->base + NJ_ISAC_OFF, data, size); 175a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 176a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 177a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 178a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilWriteFiFoISAC_nj(void *p, u8 offset, u8 *data, int size) 179a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 180a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = p; 181a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 182a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->auxd &= 0xfc; 183a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->auxd, card->base + NJ_AUXDATA); 184a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outsb(card->base + NJ_ISAC_OFF, data, size); 185a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 186a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 187a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 188a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilfill_mem(struct tiger_ch *bc, u32 idx, u32 cnt, u32 fill) 189a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 190a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bc->bch.hw; 191a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 mask = 0xff, val; 192a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 193a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d fill %02x len %d idx %d/%d\n", card->name, 194a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, fill, cnt, idx, card->send.idx); 195a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->bch.nr & 2) { 196a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill <<= 8; 197a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mask <<= 8; 198a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 199a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mask ^= 0xffffffff; 200a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil while (cnt--) { 201a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val = card->send.start[idx]; 202a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val &= mask; 203a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val |= fill; 204a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.start[idx++] = val; 205a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (idx >= card->send.size) 206a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil idx = 0; 207a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 208a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 209a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 210a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 211a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilmode_tiger(struct tiger_ch *bc, u32 protocol) 212a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 213a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bc->bch.hw; 214a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 215a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d protocol %x-->%x\n", card->name, 216a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, bc->bch.state, protocol); 217a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (protocol) { 218a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case ISDN_P_NONE: 219a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->bch.state == ISDN_P_NONE) 220a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 221a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_mem(bc, 0, card->send.size, 0xff); 222a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.state = protocol; 223a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* only stop dma and interrupts if both channels NULL */ 224a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((card->bc[0].bch.state == ISDN_P_NONE) && 225a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (card->bc[1].bch.state == ISDN_P_NONE)) { 226a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->dmactrl = 0; 227a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->dmactrl, card->base + NJ_DMACTRL); 228a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(0, card->base + NJ_IRQMASK0); 229a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 230a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_clear_bit(FLG_HDLC, &bc->bch.Flags); 231a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_clear_bit(FLG_TRANSPARENT, &bc->bch.Flags); 232a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate = 0; 233a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->rxstate = 0; 234a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->lastrx = -1; 235a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 236a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case ISDN_P_B_RAW: 237a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_set_bit(FLG_TRANSPARENT, &bc->bch.Flags); 238a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.state = protocol; 239a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = 0; 240a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free = card->send.size/2; 241a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->rxstate = 0; 242a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate = TX_INIT | TX_IDLE; 243a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->lastrx = -1; 244a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!card->dmactrl) { 245a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->dmactrl = 1; 246a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->dmactrl, card->base + NJ_DMACTRL); 247a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(0x0f, card->base + NJ_IRQMASK0); 248a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 249a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 250a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case ISDN_P_B_HDLC: 251a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_set_bit(FLG_HDLC, &bc->bch.Flags); 252a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.state = protocol; 253a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = 0; 254a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free = card->send.size/2; 255a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->rxstate = 0; 256a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate = TX_INIT | TX_IDLE; 257a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil isdnhdlc_rcv_init(&bc->hrecv, 0); 258a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil isdnhdlc_out_init(&bc->hsend, 0); 259a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->lastrx = -1; 260a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!card->dmactrl) { 261a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->dmactrl = 1; 262a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->dmactrl, card->base + NJ_DMACTRL); 263a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(0x0f, card->base + NJ_IRQMASK0); 264a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 265a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 266a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil default: 267a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: %s protocol %x not handled\n", card->name, 268a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil __func__, protocol); 269a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENOPROTOOPT; 270a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 271a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmacur = inl(card->base + NJ_DMA_READ_ADR); 272a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.dmacur = inl(card->base + NJ_DMA_WRITE_ADR); 273a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2; 274a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.idx = (card->recv.dmacur - card->recv.dmastart) >> 2; 275a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s ctrl %x irq %02x/%02x idx %d/%d\n", 276a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, __func__, 277a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil inb(card->base + NJ_DMACTRL), 278a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil inb(card->base + NJ_IRQMASK0), 279a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil inb(card->base + NJ_IRQSTAT0), 280a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.idx, 281a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.idx); 282a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 283a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 284a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 285a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 286a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_reset(struct tiger_hw *card) 287a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 288a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(0xff, card->base + NJ_CTRL); /* Reset On */ 289a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mdelay(1); 290a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 291a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* now edge triggered for TJ320 GE 13/07/00 */ 292a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* see comment in IRQ function */ 293a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->typ == NETJET_S_TJ320) /* TJ320 */ 294a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->ctrlreg = 0x40; /* Reset Off and status read clear */ 295a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 296a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->ctrlreg = 0x00; /* Reset Off and status read clear */ 297a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->ctrlreg, card->base + NJ_CTRL); 298a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mdelay(10); 299a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 300a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* configure AUX pins (all output except ISAC IRQ pin) */ 301a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->auxd = 0; 302a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->dmactrl = 0; 303a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(~NJ_ISACIRQ, card->base + NJ_AUXCTRL); 304a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(NJ_ISACIRQ, card->base + NJ_IRQMASK1); 305a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(card->auxd, card->base + NJ_AUXDATA); 306a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 307a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 308a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 309a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilinittiger(struct tiger_hw *card) 310a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 311a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int i; 312a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 313a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->dma_p = pci_alloc_consistent(card->pdev, NJ_DMA_SIZE, 314a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil &card->dma); 315a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!card->dma_p) { 316a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: No DMA memory\n", card->name); 317a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENOMEM; 318a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 319a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((u64)card->dma > 0xffffffff) { 320a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: DMA outside 32 bit\n", card->name); 321a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENOMEM; 322a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 323a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < 2; i++) { 324b42d9165e1e3d92e4e3318642463dbe592a12568Julia Lawall card->bc[i].hsbuf = kmalloc(NJ_DMA_TXSIZE, GFP_ATOMIC); 325a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!card->bc[i].hsbuf) { 326a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: no B%d send buffer\n", card->name, i + 1); 327a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENOMEM; 328a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 329b42d9165e1e3d92e4e3318642463dbe592a12568Julia Lawall card->bc[i].hrbuf = kmalloc(NJ_DMA_RXSIZE, GFP_ATOMIC); 330a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!card->bc[i].hrbuf) { 331a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: no B%d recv buffer\n", card->name, i + 1); 332a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENOMEM; 333a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 334a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 335a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil memset(card->dma_p, 0xff, NJ_DMA_SIZE); 336a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 337a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.start = card->dma_p; 338a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmastart = (u32)card->dma; 339a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmaend = card->send.dmastart + 340a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (4 * (NJ_DMA_TXSIZE - 1)); 341a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmairq = card->send.dmastart + 342a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (4 * ((NJ_DMA_TXSIZE / 2) - 1)); 343a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.size = NJ_DMA_TXSIZE; 344a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 345a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (debug & DEBUG_HW) 346a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("%s: send buffer phy %#x - %#x - %#x virt %p" 347a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil " size %zu u32\n", card->name, 348a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmastart, card->send.dmairq, 349a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmaend, card->send.start, card->send.size); 350a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 351a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outl(card->send.dmastart, card->base + NJ_DMA_READ_START); 352a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outl(card->send.dmairq, card->base + NJ_DMA_READ_IRQ); 353a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outl(card->send.dmaend, card->base + NJ_DMA_READ_END); 354a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 355a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.start = card->dma_p + (NJ_DMA_SIZE / 2); 356a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.dmastart = (u32)card->dma + (NJ_DMA_SIZE / 2); 357a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.dmaend = card->recv.dmastart + 358a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (4 * (NJ_DMA_RXSIZE - 1)); 359a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.dmairq = card->recv.dmastart + 360a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (4 * ((NJ_DMA_RXSIZE / 2) - 1)); 361a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.size = NJ_DMA_RXSIZE; 362a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 363a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (debug & DEBUG_HW) 364a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("%s: recv buffer phy %#x - %#x - %#x virt %p" 365a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil " size %zu u32\n", card->name, 366a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.dmastart, card->recv.dmairq, 367a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.dmaend, card->recv.start, card->recv.size); 368a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 369a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outl(card->recv.dmastart, card->base + NJ_DMA_WRITE_START); 370a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outl(card->recv.dmairq, card->base + NJ_DMA_WRITE_IRQ); 371a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outl(card->recv.dmaend, card->base + NJ_DMA_WRITE_END); 372a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 373a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 374a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 375a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 376a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilread_dma(struct tiger_ch *bc, u32 idx, int cnt) 377a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 378a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bc->bch.hw; 379a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int i, stat; 380a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 val; 381a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 *p, *pn; 382a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 383a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->lastrx == idx) { 384a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->rxstate |= RX_OVERRUN; 385a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d overrun at idx %d\n", card->name, 386a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, idx); 387a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 388a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->lastrx = idx; 389a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!bc->bch.rx_skb) { 390a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen, GFP_ATOMIC); 391a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!bc->bch.rx_skb) { 392a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d receive out of memory\n", 393a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, bc->bch.nr); 394a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 395a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 396a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 397a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 398a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) { 399a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((bc->bch.rx_skb->len + cnt) > bc->bch.maxlen) { 400a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d overrun %d\n", card->name, 401a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, bc->bch.rx_skb->len + cnt); 402a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil skb_trim(bc->bch.rx_skb, 0); 403a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 404a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 405a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = skb_put(bc->bch.rx_skb, cnt); 406a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } else 407a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = bc->hrbuf; 408a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 409a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < cnt; i++) { 410a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val = card->recv.start[idx++]; 411a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->bch.nr & 2) 412a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val >>= 8; 413a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (idx >= card->recv.size) 414a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil idx = 0; 415a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p[i] = val & 0xff; 416a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 417a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pn = bc->hrbuf; 418a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnext_frame: 419a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_HDLC, &bc->bch.Flags)) { 420a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil stat = isdnhdlc_decode(&bc->hrecv, pn, cnt, &i, 421a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.rx_skb->data, bc->bch.maxlen); 422a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (stat > 0) /* valid frame received */ 423a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = skb_put(bc->bch.rx_skb, stat); 424a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else if (stat == -HDLC_CRC_ERROR) 425a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d receive frame CRC error\n", 426a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, bc->bch.nr); 427a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else if (stat == -HDLC_FRAMING_ERROR) 428a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d receive framing error\n", 429a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, bc->bch.nr); 430a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else if (stat == -HDLC_LENGTH_ERROR) 431a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d receive frame too long (> %d)\n", 432a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, bc->bch.nr, bc->bch.maxlen); 433a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } else 434a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil stat = cnt; 435a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 436a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (stat > 0) { 437a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (debug & DEBUG_HW_BFIFO) { 438a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil snprintf(card->log, LOG_SIZE, "B%1d-recv %s %d ", 439a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, card->name, stat); 440a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, 441a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p, stat); 442a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 443a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil recv_Bchannel(&bc->bch, 0); 444a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 445a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_HDLC, &bc->bch.Flags)) { 446a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pn += i; 447a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil cnt -= i; 448a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!bc->bch.rx_skb) { 449a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.rx_skb = mI_alloc_skb(bc->bch.maxlen, 450a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil GFP_ATOMIC); 451a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!bc->bch.rx_skb) { 452a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d receive out of memory\n", 453a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, bc->bch.nr); 454a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 455a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 456a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 457a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (cnt > 0) 458a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto next_frame; 459a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 460a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 461a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 462a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 463a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilrecv_tiger(struct tiger_hw *card, u8 irq_stat) 464a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 465a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 idx; 466a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int cnt = card->recv.size / 2; 467a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 468a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* Note receive is via the WRITE DMA channel */ 469a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->last_is0 &= ~NJ_IRQM0_WR_MASK; 470a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->last_is0 |= (irq_stat & NJ_IRQM0_WR_MASK); 471a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 472a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (irq_stat & NJ_IRQM0_WR_END) 473a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil idx = cnt - 1; 474a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 475a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil idx = card->recv.size - 1; 476a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 477a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_ACTIVE, &card->bc[0].bch.Flags)) 478a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil read_dma(&card->bc[0], idx, cnt); 479a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_ACTIVE, &card->bc[1].bch.Flags)) 480a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil read_dma(&card->bc[1], idx, cnt); 481a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 482a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 483a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil/* sync with current DMA address at start or after exception */ 484a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 485a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilresync(struct tiger_ch *bc, struct tiger_hw *card) 486a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 487a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmacur = inl(card->base | NJ_DMA_READ_ADR); 488a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2; 489a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free > card->send.size / 2) 490a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free = card->send.size / 2; 491a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* currently we simple sync to the next complete free area 492a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * this hast the advantage that we have always maximum time to 493a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * handle TX irq 494a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil */ 495a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->send.idx < ((card->send.size / 2) - 1)) 496a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = (card->recv.size / 2) - 1; 497a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 498a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = card->recv.size - 1; 499a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate = TX_RUN; 500a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s B%1d free %d idx %d/%d\n", card->name, 501a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil __func__, bc->bch.nr, bc->free, bc->idx, card->send.idx); 502a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 503a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 504a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int bc_next_frame(struct tiger_ch *); 505a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 506a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 507a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilfill_hdlc_flag(struct tiger_ch *bc) 508a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 509a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bc->bch.hw; 510a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int count, i; 511a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 m, v; 512a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 *p; 513a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 514a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free == 0) 515a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 516a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s B%1d %d state %x idx %d/%d\n", card->name, 517a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil __func__, bc->bch.nr, bc->free, bc->txstate, 518a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx, card->send.idx); 519a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN)) 520a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil resync(bc, card); 521a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil count = isdnhdlc_encode(&bc->hsend, NULL, 0, &i, 522a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->hsbuf, bc->free); 523a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d hdlc encoded %d flags\n", card->name, 524a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, count); 525a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free -= count; 526a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = bc->hsbuf; 527a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff; 528a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < count; i++) { 529a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->idx >= card->send.size) 530a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = 0; 531a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v = card->send.start[bc->idx]; 532a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v &= m; 533a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8; 534a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.start[bc->idx++] = v; 535a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 536a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (debug & DEBUG_HW_BFIFO) { 537a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ", 538a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, card->name, count); 539a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, p, count); 540a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 541a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 542a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 543a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 544a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilfill_dma(struct tiger_ch *bc) 545a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 546a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bc->bch.hw; 547a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int count, i; 548a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 m, v; 549a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 *p; 550a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 551a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free == 0) 552a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 553a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil count = bc->bch.tx_skb->len - bc->bch.tx_idx; 554a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (count <= 0) 555a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 556a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n", card->name, 557a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil __func__, bc->bch.nr, count, bc->free, bc->bch.tx_idx, 558a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.tx_skb->len, bc->txstate, bc->idx, card->send.idx); 559a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN)) 560a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil resync(bc, card); 561a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = bc->bch.tx_skb->data + bc->bch.tx_idx; 562a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_HDLC, &bc->bch.Flags)) { 563a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil count = isdnhdlc_encode(&bc->hsend, p, count, &i, 564a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->hsbuf, bc->free); 565a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d hdlc encoded %d in %d\n", card->name, 566a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, i, count); 567a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.tx_idx += i; 568a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free -= count; 569a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = bc->hsbuf; 570a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } else { 571a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (count > bc->free) 572a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil count = bc->free; 573a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.tx_idx += count; 574a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free -= count; 575a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 576a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff; 577a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < count; i++) { 578a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->idx >= card->send.size) 579a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = 0; 580a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v = card->send.start[bc->idx]; 581a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v &= m; 582a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8; 583a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.start[bc->idx++] = v; 584a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 585a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (debug & DEBUG_HW_BFIFO) { 586a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ", 587a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, card->name, count); 588a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, p, count); 589a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 590a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free) 591a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc_next_frame(bc); 592a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 593a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 594a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 595a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 596a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilbc_next_frame(struct tiger_ch *bc) 597a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 598a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) 599a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_dma(bc); 600a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else { 601a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->bch.tx_skb) { 602a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* send confirm, on trans, free on hdlc. */ 603a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) 604a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil confirm_Bsend(&bc->bch); 605a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil dev_kfree_skb(bc->bch.tx_skb); 606a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 607a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (get_next_bframe(&bc->bch)) 608a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_dma(bc); 609a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 610a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 611a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 612a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 1; 613a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 614a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 615a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 616a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilsend_tiger_bc(struct tiger_hw *card, struct tiger_ch *bc) 617a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 618a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret; 619a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 620a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free += card->send.size / 2; 621a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free >= card->send.size) { 622a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!(bc->txstate & (TX_UNDERRUN | TX_INIT))) { 623a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d TX underrun state %x\n", card->name, 624a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, bc->txstate); 625a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate |= TX_UNDERRUN; 626a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 627a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free = card->send.size; 628a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 629a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = bc_next_frame(bc); 630a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!ret) { 631a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_HDLC, &bc->bch.Flags)) { 632a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_hdlc_flag(bc); 633a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 634a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 635a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d TX no data free %d idx %d/%d\n", card->name, 636a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, bc->free, bc->idx, card->send.idx); 637a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!(bc->txstate & (TX_IDLE | TX_INIT))) { 638a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_mem(bc, bc->idx, bc->free, 0xff); 639a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free == card->send.size) 640a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate |= TX_IDLE; 641a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 642a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 643a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 644a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 645a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 646a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilsend_tiger(struct tiger_hw *card, u8 irq_stat) 647a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 648a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int i; 649a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 650a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* Note send is via the READ DMA channel */ 651a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((irq_stat & card->last_is0) & NJ_IRQM0_RD_MASK) { 652a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: tiger warn write double dma %x/%x\n", 653a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, irq_stat, card->last_is0); 654a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 655a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } else { 656a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->last_is0 &= ~NJ_IRQM0_RD_MASK; 657a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->last_is0 |= (irq_stat & NJ_IRQM0_RD_MASK); 658a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 659a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < 2; i++) { 660a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_ACTIVE, &card->bc[i].bch.Flags)) 661a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil send_tiger_bc(card, &card->bc[i]); 662a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 663a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 664a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 665a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic irqreturn_t 666a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_irq(int intno, void *dev_id) 667a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 668a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = dev_id; 669a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 val, s1val, s0val; 670a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 671a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock(&card->lock); 672a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val = inb(card->base | NJ_IRQSTAT0); 673a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s1val = inb(card->base | NJ_IRQSTAT1); 674a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((s1val & NJ_ISACIRQ) && (s0val == 0)) { 675a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* shared IRQ */ 676a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock(&card->lock); 677a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return IRQ_NONE; 678a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 679a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: IRQSTAT0 %02x IRQSTAT1 %02x\n", card->name, s0val, s1val); 680a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->irqcnt++; 681a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!(s1val & NJ_ISACIRQ)) { 682a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val = ReadISAC_nj(card, ISAC_ISTA); 683a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (val) 684a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDNisac_irq(&card->isac, val); 685a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 686a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 687a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (s0val) 688a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* write to clear */ 689a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(s0val, card->base | NJ_IRQSTAT0); 690a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 691a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto end; 692a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s1val = s0val; 693a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* set bits in sval to indicate which page is free */ 694a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.dmacur = inl(card->base | NJ_DMA_WRITE_ADR); 695a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.idx = (card->recv.dmacur - card->recv.dmastart) >> 2; 696a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->recv.dmacur < card->recv.dmairq) 697a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val = 0x08; /* the 2nd write area is free */ 698a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 699a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val = 0x04; /* the 1st write area is free */ 700a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 701a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmacur = inl(card->base | NJ_DMA_READ_ADR); 702a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2; 703a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->send.dmacur < card->send.dmairq) 704a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val |= 0x02; /* the 2nd read area is free */ 705a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 706a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val |= 0x01; /* the 1st read area is free */ 707a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 708a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: DMA Status %02x/%02x/%02x %d/%d\n", card->name, 709a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s1val, s0val, card->last_is0, 710a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.idx, card->send.idx); 711a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* test if we have a DMA interrupt */ 712a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (s0val != card->last_is0) { 713a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((s0val & NJ_IRQM0_RD_MASK) != 714a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (card->last_is0 & NJ_IRQM0_RD_MASK)) 715a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* got a write dma int */ 716a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil send_tiger(card, s0val); 717a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((s0val & NJ_IRQM0_WR_MASK) != 718a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (card->last_is0 & NJ_IRQM0_WR_MASK)) 719a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* got a read dma int */ 720a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil recv_tiger(card, s0val); 721a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 722a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilend: 723a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock(&card->lock); 724a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return IRQ_HANDLED; 725a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 726a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 727a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 728a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb) 729a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 730a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret = -EINVAL; 731a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct bchannel *bch = container_of(ch, struct bchannel, ch); 732a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch); 733a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bch->hw; 734a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct mISDNhead *hh = mISDN_HEAD_P(skb); 735a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 id; 736a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 737a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 738a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (hh->prim) { 739a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case PH_DATA_REQ: 740a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 741a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = bchannel_senddata(bch, skb); 742a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (ret > 0) { /* direct TX */ 743a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil id = hh->id; /* skb can be freed */ 744a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_dma(bc); 745a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = 0; 746a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 747a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!test_bit(FLG_TRANSPARENT, &bch->Flags)) 748a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil queue_ch_frame(ch, PH_DATA_CNF, id, NULL); 749a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } else 750a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 751a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 752a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case PH_ACTIVATE_REQ: 753a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 754a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) 755a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = mode_tiger(bc, ch->protocol); 756a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 757a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = 0; 758a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 759a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!ret) 760a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, 761a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil NULL, GFP_KERNEL); 762a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 763a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case PH_DEACTIVATE_REQ: 764a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 765a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDN_clear_bchannel(bch); 766a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(bc, ISDN_P_NONE); 767a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 768a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, 769a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil NULL, GFP_KERNEL); 770a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = 0; 771a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 772a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 773a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!ret) 774a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil dev_kfree_skb(skb); 775a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 776a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 777a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 778a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 779a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilchannel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq) 780a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 781a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret = 0; 782a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bc->bch.hw; 783a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 784a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (cq->op) { 785a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case MISDN_CTRL_GETOP: 786a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil cq->op = 0; 787a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 788a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* Nothing implemented yet */ 789a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case MISDN_CTRL_FILL_EMPTY: 790a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil default: 791a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op); 792a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = -EINVAL; 793a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 794a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 795a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 796a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 797a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 798a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 799a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) 800a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 801a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct bchannel *bch = container_of(ch, struct bchannel, ch); 802a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch); 803a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bch->hw; 804a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret = -EINVAL; 805a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 806a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 807a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg); 808a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (cmd) { 809a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case CLOSE_CHANNEL: 810a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_clear_bit(FLG_OPEN, &bch->Flags); 811a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_ACTIVE, &bch->Flags)) { 812a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 813a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDN_freebchannel(bch); 814a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_clear_bit(FLG_TX_BUSY, &bch->Flags); 815a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_clear_bit(FLG_ACTIVE, &bch->Flags); 816a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(bc, ISDN_P_NONE); 817a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 818a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 819a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ch->protocol = ISDN_P_NONE; 820a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ch->peer = NULL; 821a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil module_put(THIS_MODULE); 822a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = 0; 823a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 824a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case CONTROL_CHANNEL: 825a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = channel_bctrl(bc, arg); 826a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 827a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil default: 828a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: %s unknown prim(%x)\n", card->name, __func__, cmd); 829a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 830a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 831a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 832a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 833a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 834a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilchannel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq) 835a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 836a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret = 0; 837a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 838a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (cq->op) { 839a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case MISDN_CTRL_GETOP: 840a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil cq->op = MISDN_CTRL_LOOP; 841a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 842a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case MISDN_CTRL_LOOP: 843a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */ 844a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (cq->channel < 0 || cq->channel > 3) { 845a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = -EINVAL; 846a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 847a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 848a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = card->isac.ctrl(&card->isac, HW_TESTLOOP, cq->channel); 849a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 850a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil default: 851a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op); 852a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = -EINVAL; 853a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 854a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 855a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 856a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 857a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 858a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 859a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilopen_bchannel(struct tiger_hw *card, struct channel_req *rq) 860a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 861a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct bchannel *bch; 862a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 863a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (rq->adr.channel > 2) 864a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EINVAL; 865a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (rq->protocol == ISDN_P_NONE) 866a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EINVAL; 867a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bch = &card->bc[rq->adr.channel - 1].bch; 868a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_and_set_bit(FLG_OPEN, &bch->Flags)) 869a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EBUSY; /* b-channel can be only open once */ 870a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); 871a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bch->ch.protocol = rq->protocol; 872a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil rq->ch = &bch->ch; 873a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 874a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 875a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 876a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil/* 877a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * device control function 878a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil */ 879a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 880a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg) 881a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 882a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); 883a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct dchannel *dch = container_of(dev, struct dchannel, dev); 884a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = dch->hw; 885a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct channel_req *rq; 886a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int err = 0; 887a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 888a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg); 889a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (cmd) { 890a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case OPEN_CHANNEL: 891a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil rq = arg; 892a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (rq->protocol == ISDN_P_TE_S0) 893a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = card->isac.open(&card->isac, rq); 894a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 895a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = open_bchannel(card, rq); 896a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) 897a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 898a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!try_module_get(THIS_MODULE)) 899a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: cannot get module\n", card->name); 900a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 901a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case CLOSE_CHANNEL: 902a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: dev(%d) close from %p\n", card->name, dch->dev.id, 903a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil __builtin_return_address(0)); 904a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil module_put(THIS_MODULE); 905a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 906a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case CONTROL_CHANNEL: 907a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = channel_ctrl(card, arg); 908a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 909a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil default: 910a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s unknown command %x\n", 911a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, __func__, cmd); 912a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EINVAL; 913a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 914a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 915a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 916a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 917a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 918a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_init_card(struct tiger_hw *card) 919a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 920a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 921a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret; 922a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 923a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 924a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_disable_hwirq(card); 925a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 926a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 927a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->irq = card->pdev->irq; 928a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (request_irq(card->irq, nj_irq, IRQF_SHARED, card->name, card)) { 929a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: couldn't get interrupt %d\n", 930a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, card->irq); 931a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->irq = -1; 932a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EIO; 933a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 934a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 935a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 936a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_reset(card); 937a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = card->isac.init(&card->isac); 938a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (ret) 939a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto error; 940a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = inittiger(card); 941a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (ret) 942a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto error; 943a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(&card->bc[0], ISDN_P_NONE); 944a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(&card->bc[1], ISDN_P_NONE); 945a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilerror: 946a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 947a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 948a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 949a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 950a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 951a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 952a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_release(struct tiger_hw *card) 953a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 954a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 955a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int i; 956a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 957a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->base_s) { 958a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 959a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_disable_hwirq(card); 960a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(&card->bc[0], ISDN_P_NONE); 961a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(&card->bc[1], ISDN_P_NONE); 962a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.release(&card->isac); 963a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 964a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil release_region(card->base, card->base_s); 965a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base_s = 0; 966a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 967a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->irq > 0) 968a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil free_irq(card->irq, card); 969a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->isac.dch.dev.dev.class) 970a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDN_unregister_device(&card->isac.dch.dev); 971a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 972a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < 2; i++) { 973a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDN_freebchannel(&card->bc[i].bch); 974a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil kfree(card->bc[i].hsbuf); 975a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil kfree(card->bc[i].hrbuf); 976a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 977a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->dma_p) 978a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_free_consistent(card->pdev, NJ_DMA_SIZE, 979a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->dma_p, card->dma); 980a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil write_lock_irqsave(&card_lock, flags); 981a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil list_del(&card->list); 982a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil write_unlock_irqrestore(&card_lock, flags); 983a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_clear_master(card->pdev); 984a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_disable_device(card->pdev); 985a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_set_drvdata(card->pdev, NULL); 986a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil kfree(card); 987a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 988a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 989a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 990a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 991a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_setup(struct tiger_hw *card) 992a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 993a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base = pci_resource_start(card->pdev, 0); 994a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base_s = pci_resource_len(card->pdev, 0); 995a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!request_region(card->base, card->base_s, card->name)) { 996a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: NETjet config port %#x-%#x already in use\n", 997a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, card->base, 998a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (u32)(card->base + card->base_s - 1)); 999a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base_s = 0; 1000a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EIO; 1001a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1002a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ASSIGN_FUNC(nj, ISAC, card->isac); 1003a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 1004a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1005a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1006a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1007a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int __devinit 1008a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilsetup_instance(struct tiger_hw *card) 1009a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1010a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int i, err; 1011a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 1012a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1013a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil snprintf(card->name, MISDN_MAX_IDLEN - 1, "netjet.%d", nj_cnt + 1); 1014a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil write_lock_irqsave(&card_lock, flags); 1015a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil list_add_tail(&card->list, &Cards); 1016a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil write_unlock_irqrestore(&card_lock, flags); 1017a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1018a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil _set_debug(card); 1019a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.name = card->name; 1020a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_init(&card->lock); 1021a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.hwlock = &card->lock; 1022a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDNisac_init(&card->isac, card); 1023a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1024a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | 1025a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); 1026a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.dch.dev.D.ctrl = nj_dctrl; 1027a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < 2; i++) { 1028a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.nr = i + 1; 1029a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil set_channelmap(i + 1, card->isac.dch.dev.channelmap); 1030a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM); 1031a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.hw = card; 1032a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.ch.send = nj_l2l1B; 1033a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.ch.ctrl = nj_bctrl; 1034a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.ch.nr = i + 1; 1035a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil list_add(&card->bc[i].bch.ch.list, 1036a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil &card->isac.dch.dev.bchannels); 1037a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.hw = card; 1038a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1039a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = nj_setup(card); 1040a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) 1041a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto error; 1042a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = mISDN_register_device(&card->isac.dch.dev, &card->pdev->dev, 1043a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name); 1044a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) 1045a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto error; 1046a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = nj_init_card(card); 1047a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!err) { 1048a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_cnt++; 1049a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("Netjet %d cards installed\n", nj_cnt); 1050a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 1051a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1052a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilerror: 1053a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_release(card); 1054a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1055a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1056a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1057a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int __devinit 1058a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 1059a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1060a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int err = -ENOMEM; 1061a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int cfg; 1062a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card; 1063a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1064a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (pdev->subsystem_vendor == 0x8086 && 1065a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pdev->subsystem_device == 0x0003) { 1066a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("Netjet: Digium X100P/X101P not handled\n"); 1067a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENODEV; 1068a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1069a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1070a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (pdev->subsystem_vendor == 0x55 && 1071a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pdev->subsystem_device == 0x02) { 1072a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("Netjet: Enter!Now not handled yet\n"); 1073a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENODEV; 1074a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1075a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1076367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava if (pdev->subsystem_vendor == 0xb100 && 1077367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava pdev->subsystem_device == 0x0003 ) { 1078367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava pr_notice("Netjet: Digium TDM400P not handled yet\n"); 1079367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava return -ENODEV; 1080367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava } 1081367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava 1082a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card = kzalloc(sizeof(struct tiger_hw), GFP_ATOMIC); 1083a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!card) { 1084a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("No kmem for Netjet\n"); 1085a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1086a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1087a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1088a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->pdev = pdev; 1089a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1090a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = pci_enable_device(pdev); 1091a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) { 1092a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil kfree(card); 1093a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1094a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1095a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1096a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil printk(KERN_INFO "nj_probe(mISDN): found adapter at %s\n", 1097a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_name(pdev)); 1098a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1099a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_set_master(pdev); 1100a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1101a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* the TJ300 and TJ320 must be detected, the IRQ handling is different 1102a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * unfortunately the chips use the same device ID, but the TJ320 has 1103a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * the bit20 in status PCI cfg register set 1104a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil */ 1105a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_read_config_dword(pdev, 0x04, &cfg); 1106a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (cfg & 0x00100000) 1107a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->typ = NETJET_S_TJ320; 1108a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 1109a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->typ = NETJET_S_TJ300; 1110a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1111a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base = pci_resource_start(pdev, 0); 1112a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->irq = pdev->irq; 1113a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_set_drvdata(pdev, card); 1114a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = setup_instance(card); 1115a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) 1116a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_set_drvdata(pdev, NULL); 1117a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1118a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1119a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1120a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1121a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1122a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void __devexit nj_remove(struct pci_dev *pdev) 1123a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1124a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = pci_get_drvdata(pdev); 1125a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1126a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card) 1127a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_release(card); 1128a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 1129a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s drvdata already removed\n", __func__); 1130a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1131a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1132a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil/* We cannot select cards with PCI_SUB... IDs, since here are cards with 1133a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * SUB IDs set to PCI_ANY_ID, so we need to match all and reject 1134a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * known other cards which not work with this driver - see probe function */ 1135a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic struct pci_device_id nj_pci_ids[] __devinitdata = { 1136a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, 1137a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1138a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil { } 1139a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil}; 1140a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilMODULE_DEVICE_TABLE(pci, nj_pci_ids); 1141a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1142a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic struct pci_driver nj_driver = { 1143a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil .name = "netjet", 1144a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil .probe = nj_probe, 1145a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil .remove = __devexit_p(nj_remove), 1146a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil .id_table = nj_pci_ids, 1147a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil}; 1148a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1149a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int __init nj_init(void) 1150a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1151a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int err; 1152a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1153a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("Netjet PCI driver Rev. %s\n", NETJET_REV); 1154a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = pci_register_driver(&nj_driver); 1155a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1156a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1157a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1158a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void __exit nj_cleanup(void) 1159a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1160a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_unregister_driver(&nj_driver); 1161a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1162a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1163a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilmodule_init(nj_init); 1164a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilmodule_exit(nj_cleanup); 1165