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, 194475be4d85a274d0961593db41cf85689db1d583cJoe Perches 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, 216475be4d85a274d0961593db41cf85689db1d583cJoe Perches 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; 240475be4d85a274d0961593db41cf85689db1d583cJoe Perches 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; 254475be4d85a274d0961593db41cf85689db1d583cJoe Perches 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", 276475be4d85a274d0961593db41cf85689db1d583cJoe Perches card->name, __func__, 277475be4d85a274d0961593db41cf85689db1d583cJoe Perches inb(card->base + NJ_DMACTRL), 278475be4d85a274d0961593db41cf85689db1d583cJoe Perches inb(card->base + NJ_IRQMASK0), 279475be4d85a274d0961593db41cf85689db1d583cJoe Perches inb(card->base + NJ_IRQSTAT0), 280475be4d85a274d0961593db41cf85689db1d583cJoe Perches card->send.idx, 281475be4d85a274d0961593db41cf85689db1d583cJoe Perches 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, 314475be4d85a274d0961593db41cf85689db1d583cJoe Perches &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" 347475be4d85a274d0961593db41cf85689db1d583cJoe Perches " size %zu u32\n", card->name, 348475be4d85a274d0961593db41cf85689db1d583cJoe Perches card->send.dmastart, card->send.dmairq, 349475be4d85a274d0961593db41cf85689db1d583cJoe Perches 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" 365475be4d85a274d0961593db41cf85689db1d583cJoe Perches " size %zu u32\n", card->name, 366475be4d85a274d0961593db41cf85689db1d583cJoe Perches card->recv.dmastart, card->recv.dmairq, 367475be4d85a274d0961593db41cf85689db1d583cJoe Perches 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; 389c27b46e7f1cbf3be95a4cf5840c76a7b7d54b26fKarsten Keil if (test_bit(FLG_RX_OFF, &bc->bch.Flags)) { 390c27b46e7f1cbf3be95a4cf5840c76a7b7d54b26fKarsten Keil bc->bch.dropcnt += cnt; 391c27b46e7f1cbf3be95a4cf5840c76a7b7d54b26fKarsten Keil return; 392c27b46e7f1cbf3be95a4cf5840c76a7b7d54b26fKarsten Keil } 3937206e659f689558b41aa058c3040b081cb281d03Karsten Keil stat = bchannel_get_rxbuf(&bc->bch, cnt); 3947206e659f689558b41aa058c3040b081cb281d03Karsten Keil /* only transparent use the count here, HDLC overun is detected later */ 3957206e659f689558b41aa058c3040b081cb281d03Karsten Keil if (stat == ENOMEM) { 3967206e659f689558b41aa058c3040b081cb281d03Karsten Keil pr_warning("%s.B%d: No memory for %d bytes\n", 3977206e659f689558b41aa058c3040b081cb281d03Karsten Keil card->name, bc->bch.nr, cnt); 3987206e659f689558b41aa058c3040b081cb281d03Karsten Keil return; 399a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 4007206e659f689558b41aa058c3040b081cb281d03Karsten Keil if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) 401a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = skb_put(bc->bch.rx_skb, cnt); 4027206e659f689558b41aa058c3040b081cb281d03Karsten Keil else 403a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = bc->hrbuf; 404a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 405a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < cnt; i++) { 406a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val = card->recv.start[idx++]; 407a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->bch.nr & 2) 408a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val >>= 8; 409a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (idx >= card->recv.size) 410a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil idx = 0; 411a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p[i] = val & 0xff; 412a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 4137206e659f689558b41aa058c3040b081cb281d03Karsten Keil 4147206e659f689558b41aa058c3040b081cb281d03Karsten Keil if (test_bit(FLG_TRANSPARENT, &bc->bch.Flags)) { 415034005a0119b9c2aabe0ac3953eb9a65ca937a69Karsten Keil recv_Bchannel(&bc->bch, 0, false); 4167206e659f689558b41aa058c3040b081cb281d03Karsten Keil return; 4177206e659f689558b41aa058c3040b081cb281d03Karsten Keil } 4187206e659f689558b41aa058c3040b081cb281d03Karsten Keil 419a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pn = bc->hrbuf; 4207206e659f689558b41aa058c3040b081cb281d03Karsten Keil while (cnt > 0) { 421a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil stat = isdnhdlc_decode(&bc->hrecv, pn, cnt, &i, 422475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->bch.rx_skb->data, bc->bch.maxlen); 4237206e659f689558b41aa058c3040b081cb281d03Karsten Keil if (stat > 0) { /* valid frame received */ 424a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = skb_put(bc->bch.rx_skb, stat); 4257206e659f689558b41aa058c3040b081cb281d03Karsten Keil if (debug & DEBUG_HW_BFIFO) { 4267206e659f689558b41aa058c3040b081cb281d03Karsten Keil snprintf(card->log, LOG_SIZE, 4277206e659f689558b41aa058c3040b081cb281d03Karsten Keil "B%1d-recv %s %d ", bc->bch.nr, 4287206e659f689558b41aa058c3040b081cb281d03Karsten Keil card->name, stat); 4297206e659f689558b41aa058c3040b081cb281d03Karsten Keil print_hex_dump_bytes(card->log, 4307206e659f689558b41aa058c3040b081cb281d03Karsten Keil DUMP_PREFIX_OFFSET, p, 4317206e659f689558b41aa058c3040b081cb281d03Karsten Keil stat); 4327206e659f689558b41aa058c3040b081cb281d03Karsten Keil } 433034005a0119b9c2aabe0ac3953eb9a65ca937a69Karsten Keil recv_Bchannel(&bc->bch, 0, false); 4347206e659f689558b41aa058c3040b081cb281d03Karsten Keil stat = bchannel_get_rxbuf(&bc->bch, bc->bch.maxlen); 4357206e659f689558b41aa058c3040b081cb281d03Karsten Keil if (stat < 0) { 4367206e659f689558b41aa058c3040b081cb281d03Karsten Keil pr_warning("%s.B%d: No memory for %d bytes\n", 4377206e659f689558b41aa058c3040b081cb281d03Karsten Keil card->name, bc->bch.nr, cnt); 4387206e659f689558b41aa058c3040b081cb281d03Karsten Keil return; 4397206e659f689558b41aa058c3040b081cb281d03Karsten Keil } 4407206e659f689558b41aa058c3040b081cb281d03Karsten Keil } else if (stat == -HDLC_CRC_ERROR) { 441a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d receive frame CRC error\n", 442a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, bc->bch.nr); 4437206e659f689558b41aa058c3040b081cb281d03Karsten Keil } else if (stat == -HDLC_FRAMING_ERROR) { 444a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d receive framing error\n", 445a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, bc->bch.nr); 4467206e659f689558b41aa058c3040b081cb281d03Karsten Keil } else if (stat == -HDLC_LENGTH_ERROR) { 447a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d receive frame too long (> %d)\n", 448a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, bc->bch.nr, bc->bch.maxlen); 449a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 450a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pn += i; 451a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil cnt -= i; 452a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 453a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 454a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 455a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 456a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilrecv_tiger(struct tiger_hw *card, u8 irq_stat) 457a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 458a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 idx; 459a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int cnt = card->recv.size / 2; 460a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 461a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* Note receive is via the WRITE DMA channel */ 462a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->last_is0 &= ~NJ_IRQM0_WR_MASK; 463a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->last_is0 |= (irq_stat & NJ_IRQM0_WR_MASK); 464a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 465a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (irq_stat & NJ_IRQM0_WR_END) 466a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil idx = cnt - 1; 467a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 468a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil idx = card->recv.size - 1; 469a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 470a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_ACTIVE, &card->bc[0].bch.Flags)) 471a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil read_dma(&card->bc[0], idx, cnt); 472a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_ACTIVE, &card->bc[1].bch.Flags)) 473a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil read_dma(&card->bc[1], idx, cnt); 474a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 475a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 476a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil/* sync with current DMA address at start or after exception */ 477a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 478a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilresync(struct tiger_ch *bc, struct tiger_hw *card) 479a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 480a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmacur = inl(card->base | NJ_DMA_READ_ADR); 481a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2; 482a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free > card->send.size / 2) 483a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free = card->send.size / 2; 484a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* currently we simple sync to the next complete free area 485a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * this hast the advantage that we have always maximum time to 486a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * handle TX irq 487a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil */ 488a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->send.idx < ((card->send.size / 2) - 1)) 489a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = (card->recv.size / 2) - 1; 490a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 491a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = card->recv.size - 1; 492a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate = TX_RUN; 493a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s B%1d free %d idx %d/%d\n", card->name, 494475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, bc->bch.nr, bc->free, bc->idx, card->send.idx); 495a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 496a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 497a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int bc_next_frame(struct tiger_ch *); 498a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 499a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 500a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilfill_hdlc_flag(struct tiger_ch *bc) 501a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 502a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bc->bch.hw; 503a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int count, i; 504a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u32 m, v; 505a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 *p; 506a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 507a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free == 0) 508a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 509a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s B%1d %d state %x idx %d/%d\n", card->name, 510475be4d85a274d0961593db41cf85689db1d583cJoe Perches __func__, bc->bch.nr, bc->free, bc->txstate, 511475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->idx, card->send.idx); 512a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN)) 513a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil resync(bc, card); 514a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil count = isdnhdlc_encode(&bc->hsend, NULL, 0, &i, 515475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->hsbuf, bc->free); 516a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d hdlc encoded %d flags\n", card->name, 517475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->bch.nr, count); 518a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free -= count; 519a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = bc->hsbuf; 520a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff; 521a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < count; i++) { 522a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->idx >= card->send.size) 523a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->idx = 0; 524a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v = card->send.start[bc->idx]; 525a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v &= m; 526a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil v |= (bc->bch.nr & 1) ? (u32)(p[i]) : ((u32)(p[i])) << 8; 527a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.start[bc->idx++] = v; 528a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 529a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (debug & DEBUG_HW_BFIFO) { 530a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ", 531475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->bch.nr, card->name, count); 532a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, p, count); 533a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 534a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 535a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 536a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 537a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilfill_dma(struct tiger_ch *bc) 538a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 539a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bc->bch.hw; 5406d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil int count, i, fillempty = 0; 5416d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil u32 m, v, n = 0; 542a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 *p; 543a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 544a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free == 0) 545a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 5466d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (!bc->bch.tx_skb) { 5476d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (!test_bit(FLG_TX_EMPTY, &bc->bch.Flags)) 5486d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil return; 5496d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil fillempty = 1; 5506d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil count = card->send.size >> 1; 5516d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil p = bc->bch.fill; 5526d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } else { 5536d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil count = bc->bch.tx_skb->len - bc->bch.tx_idx; 5546d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (count <= 0) 5556d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil return; 5566d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil pr_debug("%s: %s B%1d %d/%d/%d/%d state %x idx %d/%d\n", 5576d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil card->name, __func__, bc->bch.nr, count, bc->free, 5586d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil bc->bch.tx_idx, bc->bch.tx_skb->len, bc->txstate, 5596d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil bc->idx, card->send.idx); 5606d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil p = bc->bch.tx_skb->data + bc->bch.tx_idx; 5616d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } 562a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->txstate & (TX_IDLE | TX_INIT | TX_UNDERRUN)) 563a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil resync(bc, card); 5646d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (test_bit(FLG_HDLC, &bc->bch.Flags) && !fillempty) { 565a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil count = isdnhdlc_encode(&bc->hsend, p, count, &i, 566475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->hsbuf, bc->free); 567a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d hdlc encoded %d in %d\n", card->name, 568475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->bch.nr, i, count); 569a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.tx_idx += i; 570a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free -= count; 571a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil p = bc->hsbuf; 572a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } else { 573a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (count > bc->free) 574a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil count = bc->free; 5756d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (!fillempty) 5766d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil bc->bch.tx_idx += count; 577a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free -= count; 578a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 579a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil m = (bc->bch.nr & 1) ? 0xffffff00 : 0xffff00ff; 5806d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (fillempty) { 5816d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil n = p[0]; 5826d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (!(bc->bch.nr & 1)) 5836d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil n <<= 8; 5846d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil for (i = 0; i < count; i++) { 5856d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (bc->idx >= card->send.size) 5866d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil bc->idx = 0; 5876d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil v = card->send.start[bc->idx]; 5886d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil v &= m; 5896d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil v |= n; 5906d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil card->send.start[bc->idx++] = v; 5916d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } 5926d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } else { 5936d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil for (i = 0; i < count; i++) { 5946d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (bc->idx >= card->send.size) 5956d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil bc->idx = 0; 5966d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil v = card->send.start[bc->idx]; 5976d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil v &= m; 5986d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil n = p[i]; 5996d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil v |= (bc->bch.nr & 1) ? n : n << 8; 6006d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil card->send.start[bc->idx++] = v; 6016d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } 602a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 603a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (debug & DEBUG_HW_BFIFO) { 604a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil snprintf(card->log, LOG_SIZE, "B%1d-send %s %d ", 605475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->bch.nr, card->name, count); 606a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil print_hex_dump_bytes(card->log, DUMP_PREFIX_OFFSET, p, count); 607a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 608a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free) 609a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc_next_frame(bc); 610a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 611a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 612a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 613a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 614a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilbc_next_frame(struct tiger_ch *bc) 615a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 6166d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil int ret = 1; 6176d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil 6188bfddfbe2100862fd39b97001d0559ccd4c77f19Karsten Keil if (bc->bch.tx_skb && bc->bch.tx_idx < bc->bch.tx_skb->len) { 619a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_dma(bc); 6208bfddfbe2100862fd39b97001d0559ccd4c77f19Karsten Keil } else { 6218bfddfbe2100862fd39b97001d0559ccd4c77f19Karsten Keil if (bc->bch.tx_skb) 622a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil dev_kfree_skb(bc->bch.tx_skb); 6236d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil if (get_next_bframe(&bc->bch)) { 6246d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil fill_dma(bc); 6256d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil test_and_clear_bit(FLG_TX_EMPTY, &bc->bch.Flags); 6266d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } else if (test_bit(FLG_TX_EMPTY, &bc->bch.Flags)) { 627a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_dma(bc); 6286d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } else if (test_bit(FLG_FILLEMPTY, &bc->bch.Flags)) { 6296d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil test_and_set_bit(FLG_TX_EMPTY, &bc->bch.Flags); 6306d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil ret = 0; 6316d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } else { 6326d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil ret = 0; 6336d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil } 634a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 6356d1ee48fd0d8d2586aaeda24dacffc426c2be44aKarsten Keil return ret; 636a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 637a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 638a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 639a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilsend_tiger_bc(struct tiger_hw *card, struct tiger_ch *bc) 640a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 641a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret; 642a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 643a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free += card->send.size / 2; 644a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free >= card->send.size) { 645a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!(bc->txstate & (TX_UNDERRUN | TX_INIT))) { 646a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: B%1d TX underrun state %x\n", card->name, 647a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->bch.nr, bc->txstate); 648a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate |= TX_UNDERRUN; 649a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 650a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->free = card->send.size; 651a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 652a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = bc_next_frame(bc); 653a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!ret) { 654a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_HDLC, &bc->bch.Flags)) { 655a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_hdlc_flag(bc); 656a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 657a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 658a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: B%1d TX no data free %d idx %d/%d\n", card->name, 659475be4d85a274d0961593db41cf85689db1d583cJoe Perches bc->bch.nr, bc->free, bc->idx, card->send.idx); 660a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!(bc->txstate & (TX_IDLE | TX_INIT))) { 661a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_mem(bc, bc->idx, bc->free, 0xff); 662a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (bc->free == card->send.size) 663a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bc->txstate |= TX_IDLE; 664a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 665a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 666a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 667a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 668a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 669a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilsend_tiger(struct tiger_hw *card, u8 irq_stat) 670a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 671a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int i; 672a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 673a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* Note send is via the READ DMA channel */ 674a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((irq_stat & card->last_is0) & NJ_IRQM0_RD_MASK) { 675a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: tiger warn write double dma %x/%x\n", 676a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, irq_stat, card->last_is0); 677a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return; 678a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } else { 679a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->last_is0 &= ~NJ_IRQM0_RD_MASK; 680a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->last_is0 |= (irq_stat & NJ_IRQM0_RD_MASK); 681a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 682a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < 2; i++) { 683a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_bit(FLG_ACTIVE, &card->bc[i].bch.Flags)) 684a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil send_tiger_bc(card, &card->bc[i]); 685a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 686a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 687a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 688a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic irqreturn_t 689a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_irq(int intno, void *dev_id) 690a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 691a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = dev_id; 692a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u8 val, s1val, s0val; 693a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 694a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock(&card->lock); 695a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val = inb(card->base | NJ_IRQSTAT0); 696a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s1val = inb(card->base | NJ_IRQSTAT1); 697a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((s1val & NJ_ISACIRQ) && (s0val == 0)) { 698a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* shared IRQ */ 699a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock(&card->lock); 700a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return IRQ_NONE; 701a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 702a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: IRQSTAT0 %02x IRQSTAT1 %02x\n", card->name, s0val, s1val); 703a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->irqcnt++; 704a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!(s1val & NJ_ISACIRQ)) { 705a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil val = ReadISAC_nj(card, ISAC_ISTA); 706a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (val) 707a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDNisac_irq(&card->isac, val); 708a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 709a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 710a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (s0val) 711a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* write to clear */ 712a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil outb(s0val, card->base | NJ_IRQSTAT0); 713a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 714a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto end; 715a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s1val = s0val; 716a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* set bits in sval to indicate which page is free */ 717a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.dmacur = inl(card->base | NJ_DMA_WRITE_ADR); 718a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->recv.idx = (card->recv.dmacur - card->recv.dmastart) >> 2; 719a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->recv.dmacur < card->recv.dmairq) 720a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val = 0x08; /* the 2nd write area is free */ 721a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 722a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val = 0x04; /* the 1st write area is free */ 723a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 724a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.dmacur = inl(card->base | NJ_DMA_READ_ADR); 725a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->send.idx = (card->send.dmacur - card->send.dmastart) >> 2; 726a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->send.dmacur < card->send.dmairq) 727a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val |= 0x02; /* the 2nd read area is free */ 728a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 729a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil s0val |= 0x01; /* the 1st read area is free */ 730a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 731a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: DMA Status %02x/%02x/%02x %d/%d\n", card->name, 732475be4d85a274d0961593db41cf85689db1d583cJoe Perches s1val, s0val, card->last_is0, 733475be4d85a274d0961593db41cf85689db1d583cJoe Perches card->recv.idx, card->send.idx); 734a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* test if we have a DMA interrupt */ 735a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (s0val != card->last_is0) { 736a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((s0val & NJ_IRQM0_RD_MASK) != 737a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (card->last_is0 & NJ_IRQM0_RD_MASK)) 738a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* got a write dma int */ 739a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil send_tiger(card, s0val); 740a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if ((s0val & NJ_IRQM0_WR_MASK) != 741a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (card->last_is0 & NJ_IRQM0_WR_MASK)) 742a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* got a read dma int */ 743a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil recv_tiger(card, s0val); 744a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 745a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilend: 746a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock(&card->lock); 747a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return IRQ_HANDLED; 748a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 749a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 750a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 751a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_l2l1B(struct mISDNchannel *ch, struct sk_buff *skb) 752a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 753a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret = -EINVAL; 754a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct bchannel *bch = container_of(ch, struct bchannel, ch); 755a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch); 756a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bch->hw; 757a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct mISDNhead *hh = mISDN_HEAD_P(skb); 7588bfddfbe2100862fd39b97001d0559ccd4c77f19Karsten Keil unsigned long flags; 759a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 760a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (hh->prim) { 761a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case PH_DATA_REQ: 762a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 763a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = bchannel_senddata(bch, skb); 764a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (ret > 0) { /* direct TX */ 765a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil fill_dma(bc); 766a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = 0; 7678bfddfbe2100862fd39b97001d0559ccd4c77f19Karsten Keil } 7688bfddfbe2100862fd39b97001d0559ccd4c77f19Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 769a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 770a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case PH_ACTIVATE_REQ: 771a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 772a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!test_and_set_bit(FLG_ACTIVE, &bch->Flags)) 773a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = mode_tiger(bc, ch->protocol); 774a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 775a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = 0; 776a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 777a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!ret) 778a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil _queue_data(ch, PH_ACTIVATE_IND, MISDN_ID_ANY, 0, 779475be4d85a274d0961593db41cf85689db1d583cJoe Perches NULL, GFP_KERNEL); 780a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 781a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case PH_DEACTIVATE_REQ: 782a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 783a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDN_clear_bchannel(bch); 784a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(bc, ISDN_P_NONE); 785a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 786a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil _queue_data(ch, PH_DEACTIVATE_IND, MISDN_ID_ANY, 0, 787475be4d85a274d0961593db41cf85689db1d583cJoe Perches NULL, GFP_KERNEL); 788a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = 0; 789a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 790a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 791a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!ret) 792a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil dev_kfree_skb(skb); 793a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 794a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 795a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 796a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 797a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilchannel_bctrl(struct tiger_ch *bc, struct mISDN_ctrl_req *cq) 798a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 799034005a0119b9c2aabe0ac3953eb9a65ca937a69Karsten Keil return mISDN_ctrl_bchannel(&bc->bch, cq); 800a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 801a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 802a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 803a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg) 804a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 805a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct bchannel *bch = container_of(ch, struct bchannel, ch); 806a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_ch *bc = container_of(bch, struct tiger_ch, bch); 807a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = bch->hw; 808a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret = -EINVAL; 809a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 810a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 811a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg); 812a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (cmd) { 813a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case CLOSE_CHANNEL: 814a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_clear_bit(FLG_OPEN, &bch->Flags); 8154b921eda53366b319602351ff4d7256fafa4bd1bKarsten Keil cancel_work_sync(&bch->workq); 8161368112c07bae879fa3d1c21f236ca8eea3e5e84Karsten Keil spin_lock_irqsave(&card->lock, flags); 8174b921eda53366b319602351ff4d7256fafa4bd1bKarsten Keil mISDN_clear_bchannel(bch); 8181368112c07bae879fa3d1c21f236ca8eea3e5e84Karsten Keil mode_tiger(bc, ISDN_P_NONE); 8191368112c07bae879fa3d1c21f236ca8eea3e5e84Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 820a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ch->protocol = ISDN_P_NONE; 821a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ch->peer = NULL; 822a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil module_put(THIS_MODULE); 823a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = 0; 824a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 825a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case CONTROL_CHANNEL: 826a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = channel_bctrl(bc, arg); 827a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 828a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil default: 829a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: %s unknown prim(%x)\n", card->name, __func__, cmd); 830a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 831a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 832a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 833a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 834a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 835a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilchannel_ctrl(struct tiger_hw *card, struct mISDN_ctrl_req *cq) 836a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 837a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret = 0; 838a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 839a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (cq->op) { 840a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case MISDN_CTRL_GETOP: 841c626c127279b265ab293348763e043864d58d42cKarsten Keil cq->op = MISDN_CTRL_LOOP | MISDN_CTRL_L1_TIMER3; 842a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 843a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case MISDN_CTRL_LOOP: 844a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* cq->channel: 0 disable, 1 B1 loop 2 B2 loop, 3 both */ 845a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (cq->channel < 0 || cq->channel > 3) { 846a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = -EINVAL; 847a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 848a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 849a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = card->isac.ctrl(&card->isac, HW_TESTLOOP, cq->channel); 850a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 851c626c127279b265ab293348763e043864d58d42cKarsten Keil case MISDN_CTRL_L1_TIMER3: 852c626c127279b265ab293348763e043864d58d42cKarsten Keil ret = card->isac.ctrl(&card->isac, HW_TIMER3_VALUE, cq->p1); 853c626c127279b265ab293348763e043864d58d42cKarsten Keil break; 854a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil default: 855a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: %s unknown Op %x\n", card->name, __func__, cq->op); 856a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = -EINVAL; 857a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 858a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 859a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 860a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 861a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 862a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 863a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilopen_bchannel(struct tiger_hw *card, struct channel_req *rq) 864a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 865a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct bchannel *bch; 866a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 867819a100846295461bc0f1bfcb8e5ab11c1bc4cdbDan Carpenter if (rq->adr.channel == 0 || rq->adr.channel > 2) 868a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EINVAL; 869a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (rq->protocol == ISDN_P_NONE) 870a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EINVAL; 871a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bch = &card->bc[rq->adr.channel - 1].bch; 872a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (test_and_set_bit(FLG_OPEN, &bch->Flags)) 873a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EBUSY; /* b-channel can be only open once */ 874a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil test_and_clear_bit(FLG_FILLEMPTY, &bch->Flags); 875a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil bch->ch.protocol = rq->protocol; 876a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil rq->ch = &bch->ch; 877a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 878a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 879a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 880a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil/* 881a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * device control function 882a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil */ 883a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 884a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_dctrl(struct mISDNchannel *ch, u32 cmd, void *arg) 885a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 886a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct mISDNdevice *dev = container_of(ch, struct mISDNdevice, D); 887a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct dchannel *dch = container_of(dev, struct dchannel, dev); 888a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = dch->hw; 889a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct channel_req *rq; 890a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int err = 0; 891a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 892a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s cmd:%x %p\n", card->name, __func__, cmd, arg); 893a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil switch (cmd) { 894a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case OPEN_CHANNEL: 895a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil rq = arg; 896a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (rq->protocol == ISDN_P_TE_S0) 897a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = card->isac.open(&card->isac, rq); 898a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 899a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = open_bchannel(card, rq); 900a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) 901a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 902a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!try_module_get(THIS_MODULE)) 903a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: cannot get module\n", card->name); 904a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 905a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case CLOSE_CHANNEL: 906a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: dev(%d) close from %p\n", card->name, dch->dev.id, 907475be4d85a274d0961593db41cf85689db1d583cJoe Perches __builtin_return_address(0)); 908a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil module_put(THIS_MODULE); 909a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 910a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil case CONTROL_CHANNEL: 911a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = channel_ctrl(card, arg); 912a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil break; 913a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil default: 914a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_debug("%s: %s unknown command %x\n", 915475be4d85a274d0961593db41cf85689db1d583cJoe Perches card->name, __func__, cmd); 916a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EINVAL; 917a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 918a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 919a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 920a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 921a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 922a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_init_card(struct tiger_hw *card) 923a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 924a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 925a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int ret; 926a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 927a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 928a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_disable_hwirq(card); 929a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 930a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 931a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->irq = card->pdev->irq; 932a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (request_irq(card->irq, nj_irq, IRQF_SHARED, card->name, card)) { 933a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: couldn't get interrupt %d\n", 934a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, card->irq); 935a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->irq = -1; 936a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EIO; 937a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 938a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 939a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 940a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_reset(card); 941a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = card->isac.init(&card->isac); 942a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (ret) 943a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto error; 944a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ret = inittiger(card); 945a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (ret) 946a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto error; 947a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(&card->bc[0], ISDN_P_NONE); 948a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(&card->bc[1], ISDN_P_NONE); 949a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilerror: 950a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 951a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return ret; 952a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 953a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 954a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 955a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void 956a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_release(struct tiger_hw *card) 957a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 958a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 959a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int i; 960a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 961a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->base_s) { 962a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_irqsave(&card->lock, flags); 963a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_disable_hwirq(card); 964a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(&card->bc[0], ISDN_P_NONE); 965a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mode_tiger(&card->bc[1], ISDN_P_NONE); 966a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.release(&card->isac); 967a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_unlock_irqrestore(&card->lock, flags); 968a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil release_region(card->base, card->base_s); 969a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base_s = 0; 970a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 971a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->irq > 0) 972a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil free_irq(card->irq, card); 973a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->isac.dch.dev.dev.class) 974a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDN_unregister_device(&card->isac.dch.dev); 975475be4d85a274d0961593db41cf85689db1d583cJoe Perches 976a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < 2; i++) { 977a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDN_freebchannel(&card->bc[i].bch); 978a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil kfree(card->bc[i].hsbuf); 979a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil kfree(card->bc[i].hrbuf); 980a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 981a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card->dma_p) 982a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_free_consistent(card->pdev, NJ_DMA_SIZE, 983475be4d85a274d0961593db41cf85689db1d583cJoe Perches card->dma_p, card->dma); 984a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil write_lock_irqsave(&card_lock, flags); 985a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil list_del(&card->list); 986a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil write_unlock_irqrestore(&card_lock, flags); 987a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_clear_master(card->pdev); 988a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_disable_device(card->pdev); 989a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_set_drvdata(card->pdev, NULL); 990a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil kfree(card); 991a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 992a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 993a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 994a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int 995a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_setup(struct tiger_hw *card) 996a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 997a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base = pci_resource_start(card->pdev, 0); 998a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base_s = pci_resource_len(card->pdev, 0); 999a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!request_region(card->base, card->base_s, card->name)) { 1000a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s: NETjet config port %#x-%#x already in use\n", 1001a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->name, card->base, 1002a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (u32)(card->base + card->base_s - 1)); 1003a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base_s = 0; 1004a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -EIO; 1005a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1006a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil ASSIGN_FUNC(nj, ISAC, card->isac); 1007a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 1008a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1009a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1010a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1011ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartmanstatic int 1012a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilsetup_instance(struct tiger_hw *card) 1013a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1014a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int i, err; 1015a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil u_long flags; 1016a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1017a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil snprintf(card->name, MISDN_MAX_IDLEN - 1, "netjet.%d", nj_cnt + 1); 1018a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil write_lock_irqsave(&card_lock, flags); 1019a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil list_add_tail(&card->list, &Cards); 1020a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil write_unlock_irqrestore(&card_lock, flags); 1021a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1022a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil _set_debug(card); 1023a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.name = card->name; 1024a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil spin_lock_init(&card->lock); 1025a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.hwlock = &card->lock; 1026a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil mISDNisac_init(&card->isac, card); 1027a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1028a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.dch.dev.Bprotocols = (1 << (ISDN_P_B_RAW & ISDN_P_B_MASK)) | 1029a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil (1 << (ISDN_P_B_HDLC & ISDN_P_B_MASK)); 1030a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->isac.dch.dev.D.ctrl = nj_dctrl; 1031a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil for (i = 0; i < 2; i++) { 1032a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.nr = i + 1; 1033a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil set_channelmap(i + 1, card->isac.dch.dev.channelmap); 1034034005a0119b9c2aabe0ac3953eb9a65ca937a69Karsten Keil mISDN_initbchannel(&card->bc[i].bch, MAX_DATA_MEM, 1035034005a0119b9c2aabe0ac3953eb9a65ca937a69Karsten Keil NJ_DMA_RXSIZE >> 1); 1036a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.hw = card; 1037a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.ch.send = nj_l2l1B; 1038a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.ch.ctrl = nj_bctrl; 1039a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.ch.nr = i + 1; 1040a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil list_add(&card->bc[i].bch.ch.list, 1041475be4d85a274d0961593db41cf85689db1d583cJoe Perches &card->isac.dch.dev.bchannels); 1042a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->bc[i].bch.hw = card; 1043a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1044a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = nj_setup(card); 1045a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) 1046a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto error; 1047a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = mISDN_register_device(&card->isac.dch.dev, &card->pdev->dev, 1048475be4d85a274d0961593db41cf85689db1d583cJoe Perches card->name); 1049a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) 1050a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil goto error; 1051a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = nj_init_card(card); 1052a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!err) { 1053a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_cnt++; 1054a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("Netjet %d cards installed\n", nj_cnt); 1055a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return 0; 1056a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1057a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilerror: 1058a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_release(card); 1059a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1060a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1061a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1062ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartmanstatic int 1063a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilnj_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 1064a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1065a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int err = -ENOMEM; 1066a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int cfg; 1067a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card; 1068a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1069a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (pdev->subsystem_vendor == 0x8086 && 1070a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pdev->subsystem_device == 0x0003) { 1071a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("Netjet: Digium X100P/X101P not handled\n"); 1072a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENODEV; 1073a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1074a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1075a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (pdev->subsystem_vendor == 0x55 && 1076a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pdev->subsystem_device == 0x02) { 1077a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("Netjet: Enter!Now not handled yet\n"); 1078a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return -ENODEV; 1079a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1080a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1081367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava if (pdev->subsystem_vendor == 0xb100 && 1082475be4d85a274d0961593db41cf85689db1d583cJoe Perches pdev->subsystem_device == 0x0003) { 1083367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava pr_notice("Netjet: Digium TDM400P not handled yet\n"); 1084367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava return -ENODEV; 1085367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava } 1086367bbf2aa1654c12ab5d6dbf4428b043b425be29Prarit Bhargava 1087a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card = kzalloc(sizeof(struct tiger_hw), GFP_ATOMIC); 1088a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (!card) { 1089a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("No kmem for Netjet\n"); 1090a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1091a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1092a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1093a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->pdev = pdev; 1094a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1095a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = pci_enable_device(pdev); 1096a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) { 1097a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil kfree(card); 1098a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1099a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil } 1100a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1101a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil printk(KERN_INFO "nj_probe(mISDN): found adapter at %s\n", 1102475be4d85a274d0961593db41cf85689db1d583cJoe Perches pci_name(pdev)); 1103a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1104a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_set_master(pdev); 1105a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1106a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil /* the TJ300 and TJ320 must be detected, the IRQ handling is different 1107a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * unfortunately the chips use the same device ID, but the TJ320 has 1108a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * the bit20 in status PCI cfg register set 1109a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil */ 1110a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_read_config_dword(pdev, 0x04, &cfg); 1111a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (cfg & 0x00100000) 1112a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->typ = NETJET_S_TJ320; 1113a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 1114a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->typ = NETJET_S_TJ300; 1115a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1116a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->base = pci_resource_start(pdev, 0); 1117a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil card->irq = pdev->irq; 1118a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_set_drvdata(pdev, card); 1119a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = setup_instance(card); 1120a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (err) 1121a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_set_drvdata(pdev, NULL); 1122a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1123a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1124a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1125a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1126a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1127ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartmanstatic void nj_remove(struct pci_dev *pdev) 1128a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1129a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil struct tiger_hw *card = pci_get_drvdata(pdev); 1130a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1131a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil if (card) 1132a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil nj_release(card); 1133a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil else 1134a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_info("%s drvdata already removed\n", __func__); 1135a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1136a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1137a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil/* We cannot select cards with PCI_SUB... IDs, since here are cards with 1138a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * SUB IDs set to PCI_ANY_ID, so we need to match all and reject 1139a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil * known other cards which not work with this driver - see probe function */ 1140ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartmanstatic struct pci_device_id nj_pci_ids[] = { 1141a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil { PCI_VENDOR_ID_TIGERJET, PCI_DEVICE_ID_TIGERJET_300, 1142a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, 1143a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil { } 1144a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil}; 1145a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten KeilMODULE_DEVICE_TABLE(pci, nj_pci_ids); 1146a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1147a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic struct pci_driver nj_driver = { 1148a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil .name = "netjet", 1149a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil .probe = nj_probe, 1150ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartman .remove = nj_remove, 1151a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil .id_table = nj_pci_ids, 1152a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil}; 1153a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1154a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic int __init nj_init(void) 1155a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1156a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil int err; 1157a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1158a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pr_notice("Netjet PCI driver Rev. %s\n", NETJET_REV); 1159a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil err = pci_register_driver(&nj_driver); 1160a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil return err; 1161a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1162a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1163a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilstatic void __exit nj_cleanup(void) 1164a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil{ 1165a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil pci_unregister_driver(&nj_driver); 1166a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil} 1167a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keil 1168a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilmodule_init(nj_init); 1169a900845e56617edc005fd8f35bfd5a407aaf96c8Karsten Keilmodule_exit(nj_cleanup); 1170