1/*
2 * Driver for AVM Fritz!PCI, Fritz!PCI v2, Fritz!PnP ISDN cards
3 *
4 * Author       Kai Germaschewski
5 * Copyright    2001 by Kai Germaschewski  <kai.germaschewski@gmx.de>
6 *              2001 by Karsten Keil       <keil@isdn4linux.de>
7 *
8 * based upon Karsten Keil's original avm_pci.c driver
9 *
10 * This software may be used and distributed according to the terms
11 * of the GNU General Public License, incorporated herein by reference.
12 *
13 * Thanks to Wizard Computersysteme GmbH, Bremervoerde and
14 *           SoHaNet Technology GmbH, Berlin
15 * for supporting the development of this driver
16 */
17
18
19/* TODO:
20 *
21 * o POWER PC
22 * o clean up debugging
23 * o tx_skb at PH_DEACTIVATE time
24 */
25
26#include <linux/module.h>
27#include <linux/init.h>
28#include <linux/interrupt.h>
29#include <linux/pci.h>
30#include <linux/isapnp.h>
31#include <linux/kmod.h>
32#include <linux/slab.h>
33#include <linux/skbuff.h>
34#include <linux/netdevice.h>
35#include <linux/delay.h>
36
37#include <asm/io.h>
38
39#include "hisax_fcpcipnp.h"
40
41// debugging cruft
42#define __debug_variable debug
43#include "hisax_debug.h"
44
45#ifdef CONFIG_HISAX_DEBUG
46static int debug = 0;
47/* static int hdlcfifosize = 32; */
48module_param(debug, int, 0);
49/* module_param(hdlcfifosize, int, 0); */
50#endif
51
52MODULE_AUTHOR("Kai Germaschewski <kai.germaschewski@gmx.de>/Karsten Keil <kkeil@suse.de>");
53MODULE_DESCRIPTION("AVM Fritz!PCI/PnP ISDN driver");
54
55static struct pci_device_id fcpci_ids[] = {
56	{ .vendor      = PCI_VENDOR_ID_AVM,
57	  .device      = PCI_DEVICE_ID_AVM_A1,
58	  .subvendor   = PCI_ANY_ID,
59	  .subdevice   = PCI_ANY_ID,
60	  .driver_data = (unsigned long) "Fritz!Card PCI",
61	},
62	{ .vendor      = PCI_VENDOR_ID_AVM,
63	  .device      = PCI_DEVICE_ID_AVM_A1_V2,
64	  .subvendor   = PCI_ANY_ID,
65	  .subdevice   = PCI_ANY_ID,
66	  .driver_data = (unsigned long) "Fritz!Card PCI v2" },
67	{}
68};
69
70MODULE_DEVICE_TABLE(pci, fcpci_ids);
71
72#ifdef CONFIG_PNP
73static struct pnp_device_id fcpnp_ids[] = {
74	{
75		.id		= "AVM0900",
76		.driver_data	= (unsigned long) "Fritz!Card PnP",
77	},
78	{ .id = "" }
79};
80
81MODULE_DEVICE_TABLE(pnp, fcpnp_ids);
82#endif
83
84static int protocol = 2;       /* EURO-ISDN Default */
85module_param(protocol, int, 0);
86MODULE_LICENSE("GPL");
87
88// ----------------------------------------------------------------------
89
90#define  AVM_INDEX              0x04
91#define  AVM_DATA               0x10
92
93#define	 AVM_IDX_HDLC_1		0x00
94#define	 AVM_IDX_HDLC_2		0x01
95#define	 AVM_IDX_ISAC_FIFO	0x02
96#define	 AVM_IDX_ISAC_REG_LOW	0x04
97#define	 AVM_IDX_ISAC_REG_HIGH	0x06
98
99#define  AVM_STATUS0            0x02
100
101#define  AVM_STATUS0_IRQ_ISAC	0x01
102#define  AVM_STATUS0_IRQ_HDLC	0x02
103#define  AVM_STATUS0_IRQ_TIMER	0x04
104#define  AVM_STATUS0_IRQ_MASK	0x07
105
106#define  AVM_STATUS0_RESET	0x01
107#define  AVM_STATUS0_DIS_TIMER	0x02
108#define  AVM_STATUS0_RES_TIMER	0x04
109#define  AVM_STATUS0_ENA_IRQ	0x08
110#define  AVM_STATUS0_TESTBIT	0x10
111
112#define  AVM_STATUS1            0x03
113#define  AVM_STATUS1_ENA_IOM	0x80
114
115#define  HDLC_FIFO		0x0
116#define  HDLC_STATUS		0x4
117#define  HDLC_CTRL		0x4
118
119#define  HDLC_MODE_ITF_FLG	0x01
120#define  HDLC_MODE_TRANS	0x02
121#define  HDLC_MODE_CCR_7	0x04
122#define  HDLC_MODE_CCR_16	0x08
123#define  HDLC_MODE_TESTLOOP	0x80
124
125#define  HDLC_INT_XPR		0x80
126#define  HDLC_INT_XDU		0x40
127#define  HDLC_INT_RPR		0x20
128#define  HDLC_INT_MASK		0xE0
129
130#define  HDLC_STAT_RME		0x01
131#define  HDLC_STAT_RDO		0x10
132#define  HDLC_STAT_CRCVFRRAB	0x0E
133#define  HDLC_STAT_CRCVFR	0x06
134#define  HDLC_STAT_RML_MASK	0xff00
135
136#define  HDLC_CMD_XRS		0x80
137#define  HDLC_CMD_XME		0x01
138#define  HDLC_CMD_RRS		0x20
139#define  HDLC_CMD_XML_MASK	0xff00
140
141#define  AVM_HDLC_FIFO_1        0x10
142#define  AVM_HDLC_FIFO_2        0x18
143
144#define  AVM_HDLC_STATUS_1      0x14
145#define  AVM_HDLC_STATUS_2      0x1c
146
147#define  AVM_ISACSX_INDEX       0x04
148#define  AVM_ISACSX_DATA        0x08
149
150// ----------------------------------------------------------------------
151// Fritz!PCI
152
153static unsigned char fcpci_read_isac(struct isac *isac, unsigned char offset)
154{
155	struct fritz_adapter *adapter = isac->priv;
156	unsigned char idx = (offset > 0x2f) ?
157		AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
158	unsigned char val;
159	unsigned long flags;
160
161	spin_lock_irqsave(&adapter->hw_lock, flags);
162	outb(idx, adapter->io + AVM_INDEX);
163	val = inb(adapter->io + AVM_DATA + (offset & 0xf));
164	spin_unlock_irqrestore(&adapter->hw_lock, flags);
165	DBG(0x1000, " port %#x, value %#x",
166	    offset, val);
167	return val;
168}
169
170static void fcpci_write_isac(struct isac *isac, unsigned char offset,
171			     unsigned char value)
172{
173	struct fritz_adapter *adapter = isac->priv;
174	unsigned char idx = (offset > 0x2f) ?
175		AVM_IDX_ISAC_REG_HIGH : AVM_IDX_ISAC_REG_LOW;
176	unsigned long flags;
177
178	DBG(0x1000, " port %#x, value %#x",
179	    offset, value);
180	spin_lock_irqsave(&adapter->hw_lock, flags);
181	outb(idx, adapter->io + AVM_INDEX);
182	outb(value, adapter->io + AVM_DATA + (offset & 0xf));
183	spin_unlock_irqrestore(&adapter->hw_lock, flags);
184}
185
186static void fcpci_read_isac_fifo(struct isac *isac, unsigned char *data,
187				 int size)
188{
189	struct fritz_adapter *adapter = isac->priv;
190	unsigned long flags;
191
192	spin_lock_irqsave(&adapter->hw_lock, flags);
193	outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
194	insb(adapter->io + AVM_DATA, data, size);
195	spin_unlock_irqrestore(&adapter->hw_lock, flags);
196}
197
198static void fcpci_write_isac_fifo(struct isac *isac, unsigned char *data,
199				  int size)
200{
201	struct fritz_adapter *adapter = isac->priv;
202	unsigned long flags;
203
204	spin_lock_irqsave(&adapter->hw_lock, flags);
205	outb(AVM_IDX_ISAC_FIFO, adapter->io + AVM_INDEX);
206	outsb(adapter->io + AVM_DATA, data, size);
207	spin_unlock_irqrestore(&adapter->hw_lock, flags);
208}
209
210static u32 fcpci_read_hdlc_status(struct fritz_adapter *adapter, int nr)
211{
212	u32 val;
213	int idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
214	unsigned long flags;
215
216	spin_lock_irqsave(&adapter->hw_lock, flags);
217	outl(idx, adapter->io + AVM_INDEX);
218	val = inl(adapter->io + AVM_DATA + HDLC_STATUS);
219	spin_unlock_irqrestore(&adapter->hw_lock, flags);
220	return val;
221}
222
223static void __fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
224{
225	struct fritz_adapter *adapter = bcs->adapter;
226	int idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
227
228	DBG(0x40, "hdlc %c wr%x ctrl %x",
229	    'A' + bcs->channel, which, bcs->ctrl.ctrl);
230
231	outl(idx, adapter->io + AVM_INDEX);
232	outl(bcs->ctrl.ctrl, adapter->io + AVM_DATA + HDLC_CTRL);
233}
234
235static void fcpci_write_ctrl(struct fritz_bcs *bcs, int which)
236{
237	struct fritz_adapter *adapter = bcs->adapter;
238	unsigned long flags;
239
240	spin_lock_irqsave(&adapter->hw_lock, flags);
241	__fcpci_write_ctrl(bcs, which);
242	spin_unlock_irqrestore(&adapter->hw_lock, flags);
243}
244
245// ----------------------------------------------------------------------
246// Fritz!PCI v2
247
248static unsigned char fcpci2_read_isac(struct isac *isac, unsigned char offset)
249{
250	struct fritz_adapter *adapter = isac->priv;
251	unsigned char val;
252	unsigned long flags;
253
254	spin_lock_irqsave(&adapter->hw_lock, flags);
255	outl(offset, adapter->io + AVM_ISACSX_INDEX);
256	val = inl(adapter->io + AVM_ISACSX_DATA);
257	spin_unlock_irqrestore(&adapter->hw_lock, flags);
258	DBG(0x1000, " port %#x, value %#x",
259	    offset, val);
260
261	return val;
262}
263
264static void fcpci2_write_isac(struct isac *isac, unsigned char offset,
265			      unsigned char value)
266{
267	struct fritz_adapter *adapter = isac->priv;
268	unsigned long flags;
269
270	DBG(0x1000, " port %#x, value %#x",
271	    offset, value);
272	spin_lock_irqsave(&adapter->hw_lock, flags);
273	outl(offset, adapter->io + AVM_ISACSX_INDEX);
274	outl(value, adapter->io + AVM_ISACSX_DATA);
275	spin_unlock_irqrestore(&adapter->hw_lock, flags);
276}
277
278static void fcpci2_read_isac_fifo(struct isac *isac, unsigned char *data,
279				  int size)
280{
281	struct fritz_adapter *adapter = isac->priv;
282	int i;
283	unsigned long flags;
284
285	spin_lock_irqsave(&adapter->hw_lock, flags);
286	outl(0, adapter->io + AVM_ISACSX_INDEX);
287	for (i = 0; i < size; i++)
288		data[i] = inl(adapter->io + AVM_ISACSX_DATA);
289	spin_unlock_irqrestore(&adapter->hw_lock, flags);
290}
291
292static void fcpci2_write_isac_fifo(struct isac *isac, unsigned char *data,
293				   int size)
294{
295	struct fritz_adapter *adapter = isac->priv;
296	int i;
297	unsigned long flags;
298
299	spin_lock_irqsave(&adapter->hw_lock, flags);
300	outl(0, adapter->io + AVM_ISACSX_INDEX);
301	for (i = 0; i < size; i++)
302		outl(data[i], adapter->io + AVM_ISACSX_DATA);
303	spin_unlock_irqrestore(&adapter->hw_lock, flags);
304}
305
306static u32 fcpci2_read_hdlc_status(struct fritz_adapter *adapter, int nr)
307{
308	int offset = nr ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
309
310	return inl(adapter->io + offset);
311}
312
313static void fcpci2_write_ctrl(struct fritz_bcs *bcs, int which)
314{
315	struct fritz_adapter *adapter = bcs->adapter;
316	int offset = bcs->channel ? AVM_HDLC_STATUS_2 : AVM_HDLC_STATUS_1;
317
318	DBG(0x40, "hdlc %c wr%x ctrl %x",
319	    'A' + bcs->channel, which, bcs->ctrl.ctrl);
320
321	outl(bcs->ctrl.ctrl, adapter->io + offset);
322}
323
324// ----------------------------------------------------------------------
325// Fritz!PnP (ISAC access as for Fritz!PCI)
326
327static u32 fcpnp_read_hdlc_status(struct fritz_adapter *adapter, int nr)
328{
329	unsigned char idx = nr ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
330	u32 val;
331	unsigned long flags;
332
333	spin_lock_irqsave(&adapter->hw_lock, flags);
334	outb(idx, adapter->io + AVM_INDEX);
335	val = inb(adapter->io + AVM_DATA + HDLC_STATUS);
336	if (val & HDLC_INT_RPR)
337		val |= inb(adapter->io + AVM_DATA + HDLC_STATUS + 1) << 8;
338	spin_unlock_irqrestore(&adapter->hw_lock, flags);
339	return val;
340}
341
342static void __fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
343{
344	struct fritz_adapter *adapter = bcs->adapter;
345	unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
346
347	DBG(0x40, "hdlc %c wr%x ctrl %x",
348	    'A' + bcs->channel, which, bcs->ctrl.ctrl);
349
350	outb(idx, adapter->io + AVM_INDEX);
351	if (which & 4)
352		outb(bcs->ctrl.sr.mode,
353		     adapter->io + AVM_DATA + HDLC_STATUS + 2);
354	if (which & 2)
355		outb(bcs->ctrl.sr.xml,
356		     adapter->io + AVM_DATA + HDLC_STATUS + 1);
357	if (which & 1)
358		outb(bcs->ctrl.sr.cmd,
359		     adapter->io + AVM_DATA + HDLC_STATUS + 0);
360}
361
362static void fcpnp_write_ctrl(struct fritz_bcs *bcs, int which)
363{
364	struct fritz_adapter *adapter = bcs->adapter;
365	unsigned long flags;
366
367	spin_lock_irqsave(&adapter->hw_lock, flags);
368	__fcpnp_write_ctrl(bcs, which);
369	spin_unlock_irqrestore(&adapter->hw_lock, flags);
370}
371
372// ----------------------------------------------------------------------
373
374static inline void B_L1L2(struct fritz_bcs *bcs, int pr, void *arg)
375{
376	struct hisax_if *ifc = (struct hisax_if *) &bcs->b_if;
377
378	DBG(2, "pr %#x", pr);
379	ifc->l1l2(ifc, pr, arg);
380}
381
382static void hdlc_fill_fifo(struct fritz_bcs *bcs)
383{
384	struct fritz_adapter *adapter = bcs->adapter;
385	struct sk_buff *skb = bcs->tx_skb;
386	int count;
387	unsigned long flags;
388	unsigned char *p;
389
390	DBG(0x40, "hdlc_fill_fifo");
391
392	BUG_ON(skb->len == 0);
393
394	bcs->ctrl.sr.cmd &= ~HDLC_CMD_XME;
395	if (bcs->tx_skb->len > bcs->fifo_size) {
396		count = bcs->fifo_size;
397	} else {
398		count = bcs->tx_skb->len;
399		if (bcs->mode != L1_MODE_TRANS)
400			bcs->ctrl.sr.cmd |= HDLC_CMD_XME;
401	}
402	DBG(0x40, "hdlc_fill_fifo %d/%d", count, bcs->tx_skb->len);
403	p = bcs->tx_skb->data;
404	skb_pull(bcs->tx_skb, count);
405	bcs->tx_cnt += count;
406	bcs->ctrl.sr.xml = ((count == bcs->fifo_size) ? 0 : count);
407
408	switch (adapter->type) {
409	case AVM_FRITZ_PCI:
410		spin_lock_irqsave(&adapter->hw_lock, flags);
411		// sets the correct AVM_INDEX, too
412		__fcpci_write_ctrl(bcs, 3);
413		outsl(adapter->io + AVM_DATA + HDLC_FIFO,
414		      p, (count + 3) / 4);
415		spin_unlock_irqrestore(&adapter->hw_lock, flags);
416		break;
417	case AVM_FRITZ_PCIV2:
418		fcpci2_write_ctrl(bcs, 3);
419		outsl(adapter->io +
420		      (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
421		      p, (count + 3) / 4);
422		break;
423	case AVM_FRITZ_PNP:
424		spin_lock_irqsave(&adapter->hw_lock, flags);
425		// sets the correct AVM_INDEX, too
426		__fcpnp_write_ctrl(bcs, 3);
427		outsb(adapter->io + AVM_DATA, p, count);
428		spin_unlock_irqrestore(&adapter->hw_lock, flags);
429		break;
430	}
431}
432
433static inline void hdlc_empty_fifo(struct fritz_bcs *bcs, int count)
434{
435	struct fritz_adapter *adapter = bcs->adapter;
436	unsigned char *p;
437	unsigned char idx = bcs->channel ? AVM_IDX_HDLC_2 : AVM_IDX_HDLC_1;
438
439	DBG(0x10, "hdlc_empty_fifo %d", count);
440	if (bcs->rcvidx + count > HSCX_BUFMAX) {
441		DBG(0x10, "hdlc_empty_fifo: incoming packet too large");
442		return;
443	}
444	p = bcs->rcvbuf + bcs->rcvidx;
445	bcs->rcvidx += count;
446	switch (adapter->type) {
447	case AVM_FRITZ_PCI:
448		spin_lock(&adapter->hw_lock);
449		outl(idx, adapter->io + AVM_INDEX);
450		insl(adapter->io + AVM_DATA + HDLC_FIFO,
451		     p, (count + 3) / 4);
452		spin_unlock(&adapter->hw_lock);
453		break;
454	case AVM_FRITZ_PCIV2:
455		insl(adapter->io +
456		     (bcs->channel ? AVM_HDLC_FIFO_2 : AVM_HDLC_FIFO_1),
457		     p, (count + 3) / 4);
458		break;
459	case AVM_FRITZ_PNP:
460		spin_lock(&adapter->hw_lock);
461		outb(idx, adapter->io + AVM_INDEX);
462		insb(adapter->io + AVM_DATA, p, count);
463		spin_unlock(&adapter->hw_lock);
464		break;
465	}
466}
467
468static inline void hdlc_rpr_irq(struct fritz_bcs *bcs, u32 stat)
469{
470	struct fritz_adapter *adapter = bcs->adapter;
471	struct sk_buff *skb;
472	int len;
473
474	if (stat & HDLC_STAT_RDO) {
475		DBG(0x10, "RDO");
476		bcs->ctrl.sr.xml = 0;
477		bcs->ctrl.sr.cmd |= HDLC_CMD_RRS;
478		adapter->write_ctrl(bcs, 1);
479		bcs->ctrl.sr.cmd &= ~HDLC_CMD_RRS;
480		adapter->write_ctrl(bcs, 1);
481		bcs->rcvidx = 0;
482		return;
483	}
484
485	len = (stat & HDLC_STAT_RML_MASK) >> 8;
486	if (len == 0)
487		len = bcs->fifo_size;
488
489	hdlc_empty_fifo(bcs, len);
490
491	if ((stat & HDLC_STAT_RME) || (bcs->mode == L1_MODE_TRANS)) {
492		if (((stat & HDLC_STAT_CRCVFRRAB) == HDLC_STAT_CRCVFR) ||
493		    (bcs->mode == L1_MODE_TRANS)) {
494			skb = dev_alloc_skb(bcs->rcvidx);
495			if (!skb) {
496				printk(KERN_WARNING "HDLC: receive out of memory\n");
497			} else {
498				memcpy(skb_put(skb, bcs->rcvidx), bcs->rcvbuf,
499				       bcs->rcvidx);
500				DBG_SKB(1, skb);
501				B_L1L2(bcs, PH_DATA | INDICATION, skb);
502			}
503			bcs->rcvidx = 0;
504		} else {
505			DBG(0x10, "ch%d invalid frame %#x",
506			    bcs->channel, stat);
507			bcs->rcvidx = 0;
508		}
509	}
510}
511
512static inline void hdlc_xdu_irq(struct fritz_bcs *bcs)
513{
514	struct fritz_adapter *adapter = bcs->adapter;
515
516
517	/* Here we lost an TX interrupt, so
518	 * restart transmitting the whole frame.
519	 */
520	bcs->ctrl.sr.xml = 0;
521	bcs->ctrl.sr.cmd |= HDLC_CMD_XRS;
522	adapter->write_ctrl(bcs, 1);
523	bcs->ctrl.sr.cmd &= ~HDLC_CMD_XRS;
524
525	if (!bcs->tx_skb) {
526		DBG(0x10, "XDU without skb");
527		adapter->write_ctrl(bcs, 1);
528		return;
529	}
530	/* only hdlc restarts the frame, transparent mode must continue */
531	if (bcs->mode == L1_MODE_HDLC) {
532		skb_push(bcs->tx_skb, bcs->tx_cnt);
533		bcs->tx_cnt = 0;
534	}
535}
536
537static inline void hdlc_xpr_irq(struct fritz_bcs *bcs)
538{
539	struct sk_buff *skb;
540
541	skb = bcs->tx_skb;
542	if (!skb)
543		return;
544
545	if (skb->len) {
546		hdlc_fill_fifo(bcs);
547		return;
548	}
549	bcs->tx_cnt = 0;
550	bcs->tx_skb = NULL;
551	B_L1L2(bcs, PH_DATA | CONFIRM, (void *)(unsigned long)skb->truesize);
552	dev_kfree_skb_irq(skb);
553}
554
555static void hdlc_irq_one(struct fritz_bcs *bcs, u32 stat)
556{
557	DBG(0x10, "ch%d stat %#x", bcs->channel, stat);
558	if (stat & HDLC_INT_RPR) {
559		DBG(0x10, "RPR");
560		hdlc_rpr_irq(bcs, stat);
561	}
562	if (stat & HDLC_INT_XDU) {
563		DBG(0x10, "XDU");
564		hdlc_xdu_irq(bcs);
565		hdlc_xpr_irq(bcs);
566		return;
567	}
568	if (stat & HDLC_INT_XPR) {
569		DBG(0x10, "XPR");
570		hdlc_xpr_irq(bcs);
571	}
572}
573
574static inline void hdlc_irq(struct fritz_adapter *adapter)
575{
576	int nr;
577	u32 stat;
578
579	for (nr = 0; nr < 2; nr++) {
580		stat = adapter->read_hdlc_status(adapter, nr);
581		DBG(0x10, "HDLC %c stat %#x", 'A' + nr, stat);
582		if (stat & HDLC_INT_MASK)
583			hdlc_irq_one(&adapter->bcs[nr], stat);
584	}
585}
586
587static void modehdlc(struct fritz_bcs *bcs, int mode)
588{
589	struct fritz_adapter *adapter = bcs->adapter;
590
591	DBG(0x40, "hdlc %c mode %d --> %d",
592	    'A' + bcs->channel, bcs->mode, mode);
593
594	if (bcs->mode == mode)
595		return;
596
597	bcs->fifo_size = 32;
598	bcs->ctrl.ctrl = 0;
599	bcs->ctrl.sr.cmd  = HDLC_CMD_XRS | HDLC_CMD_RRS;
600	switch (mode) {
601	case L1_MODE_NULL:
602		bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
603		adapter->write_ctrl(bcs, 5);
604		break;
605	case L1_MODE_TRANS:
606	case L1_MODE_HDLC:
607		bcs->rcvidx = 0;
608		bcs->tx_cnt = 0;
609		bcs->tx_skb = NULL;
610		if (mode == L1_MODE_TRANS) {
611			bcs->ctrl.sr.mode = HDLC_MODE_TRANS;
612		} else {
613			bcs->ctrl.sr.mode = HDLC_MODE_ITF_FLG;
614		}
615		adapter->write_ctrl(bcs, 5);
616		bcs->ctrl.sr.cmd = HDLC_CMD_XRS;
617		adapter->write_ctrl(bcs, 1);
618		bcs->ctrl.sr.cmd = 0;
619		break;
620	}
621	bcs->mode = mode;
622}
623
624static void fritz_b_l2l1(struct hisax_if *ifc, int pr, void *arg)
625{
626	struct fritz_bcs *bcs = ifc->priv;
627	struct sk_buff *skb = arg;
628	int mode;
629
630	DBG(0x10, "pr %#x", pr);
631
632	switch (pr) {
633	case PH_DATA | REQUEST:
634		BUG_ON(bcs->tx_skb);
635		bcs->tx_skb = skb;
636		DBG_SKB(1, skb);
637		hdlc_fill_fifo(bcs);
638		break;
639	case PH_ACTIVATE | REQUEST:
640		mode = (long) arg;
641		DBG(4, "B%d,PH_ACTIVATE_REQUEST %d", bcs->channel + 1, mode);
642		modehdlc(bcs, mode);
643		B_L1L2(bcs, PH_ACTIVATE | INDICATION, NULL);
644		break;
645	case PH_DEACTIVATE | REQUEST:
646		DBG(4, "B%d,PH_DEACTIVATE_REQUEST", bcs->channel + 1);
647		modehdlc(bcs, L1_MODE_NULL);
648		B_L1L2(bcs, PH_DEACTIVATE | INDICATION, NULL);
649		break;
650	}
651}
652
653// ----------------------------------------------------------------------
654
655static irqreturn_t
656fcpci2_irq(int intno, void *dev)
657{
658	struct fritz_adapter *adapter = dev;
659	unsigned char val;
660
661	val = inb(adapter->io + AVM_STATUS0);
662	if (!(val & AVM_STATUS0_IRQ_MASK))
663		/* hopefully a shared  IRQ reqest */
664		return IRQ_NONE;
665	DBG(2, "STATUS0 %#x", val);
666	if (val & AVM_STATUS0_IRQ_ISAC)
667		isacsx_irq(&adapter->isac);
668	if (val & AVM_STATUS0_IRQ_HDLC)
669		hdlc_irq(adapter);
670	if (val & AVM_STATUS0_IRQ_ISAC)
671		isacsx_irq(&adapter->isac);
672	return IRQ_HANDLED;
673}
674
675static irqreturn_t
676fcpci_irq(int intno, void *dev)
677{
678	struct fritz_adapter *adapter = dev;
679	unsigned char sval;
680
681	sval = inb(adapter->io + 2);
682	if ((sval & AVM_STATUS0_IRQ_MASK) == AVM_STATUS0_IRQ_MASK)
683		/* possibly a shared  IRQ reqest */
684		return IRQ_NONE;
685	DBG(2, "sval %#x", sval);
686	if (!(sval & AVM_STATUS0_IRQ_ISAC))
687		isac_irq(&adapter->isac);
688
689	if (!(sval & AVM_STATUS0_IRQ_HDLC))
690		hdlc_irq(adapter);
691	return IRQ_HANDLED;
692}
693
694// ----------------------------------------------------------------------
695
696static inline void fcpci2_init(struct fritz_adapter *adapter)
697{
698	outb(AVM_STATUS0_RES_TIMER, adapter->io + AVM_STATUS0);
699	outb(AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
700
701}
702
703static inline void fcpci_init(struct fritz_adapter *adapter)
704{
705	outb(AVM_STATUS0_DIS_TIMER | AVM_STATUS0_RES_TIMER |
706	     AVM_STATUS0_ENA_IRQ, adapter->io + AVM_STATUS0);
707
708	outb(AVM_STATUS1_ENA_IOM | adapter->irq,
709	     adapter->io + AVM_STATUS1);
710	mdelay(10);
711}
712
713// ----------------------------------------------------------------------
714
715static int fcpcipnp_setup(struct fritz_adapter *adapter)
716{
717	u32 val = 0;
718	int retval;
719
720	DBG(1, "");
721
722	isac_init(&adapter->isac); // FIXME is this okay now
723
724	retval = -EBUSY;
725	if (!request_region(adapter->io, 32, "fcpcipnp"))
726		goto err;
727
728	switch (adapter->type) {
729	case AVM_FRITZ_PCIV2:
730	case AVM_FRITZ_PCI:
731		val = inl(adapter->io);
732		break;
733	case AVM_FRITZ_PNP:
734		val = inb(adapter->io);
735		val |= inb(adapter->io + 1) << 8;
736		break;
737	}
738
739	DBG(1, "stat %#x Class %X Rev %d",
740	    val, val & 0xff, (val >> 8) & 0xff);
741
742	spin_lock_init(&adapter->hw_lock);
743	adapter->isac.priv = adapter;
744	switch (adapter->type) {
745	case AVM_FRITZ_PCIV2:
746		adapter->isac.read_isac       = &fcpci2_read_isac;
747		adapter->isac.write_isac      = &fcpci2_write_isac;
748		adapter->isac.read_isac_fifo  = &fcpci2_read_isac_fifo;
749		adapter->isac.write_isac_fifo = &fcpci2_write_isac_fifo;
750
751		adapter->read_hdlc_status     = &fcpci2_read_hdlc_status;
752		adapter->write_ctrl           = &fcpci2_write_ctrl;
753		break;
754	case AVM_FRITZ_PCI:
755		adapter->isac.read_isac       = &fcpci_read_isac;
756		adapter->isac.write_isac      = &fcpci_write_isac;
757		adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
758		adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
759
760		adapter->read_hdlc_status     = &fcpci_read_hdlc_status;
761		adapter->write_ctrl           = &fcpci_write_ctrl;
762		break;
763	case AVM_FRITZ_PNP:
764		adapter->isac.read_isac       = &fcpci_read_isac;
765		adapter->isac.write_isac      = &fcpci_write_isac;
766		adapter->isac.read_isac_fifo  = &fcpci_read_isac_fifo;
767		adapter->isac.write_isac_fifo = &fcpci_write_isac_fifo;
768
769		adapter->read_hdlc_status     = &fcpnp_read_hdlc_status;
770		adapter->write_ctrl           = &fcpnp_write_ctrl;
771		break;
772	}
773
774	// Reset
775	outb(0, adapter->io + AVM_STATUS0);
776	mdelay(10);
777	outb(AVM_STATUS0_RESET, adapter->io + AVM_STATUS0);
778	mdelay(10);
779	outb(0, adapter->io + AVM_STATUS0);
780	mdelay(10);
781
782	switch (adapter->type) {
783	case AVM_FRITZ_PCIV2:
784		retval = request_irq(adapter->irq, fcpci2_irq, IRQF_SHARED,
785				     "fcpcipnp", adapter);
786		break;
787	case AVM_FRITZ_PCI:
788		retval = request_irq(adapter->irq, fcpci_irq, IRQF_SHARED,
789				     "fcpcipnp", adapter);
790		break;
791	case AVM_FRITZ_PNP:
792		retval = request_irq(adapter->irq, fcpci_irq, 0,
793				     "fcpcipnp", adapter);
794		break;
795	}
796	if (retval)
797		goto err_region;
798
799	switch (adapter->type) {
800	case AVM_FRITZ_PCIV2:
801		fcpci2_init(adapter);
802		isacsx_setup(&adapter->isac);
803		break;
804	case AVM_FRITZ_PCI:
805	case AVM_FRITZ_PNP:
806		fcpci_init(adapter);
807		isac_setup(&adapter->isac);
808		break;
809	}
810	val = adapter->read_hdlc_status(adapter, 0);
811	DBG(0x20, "HDLC A STA %x", val);
812	val = adapter->read_hdlc_status(adapter, 1);
813	DBG(0x20, "HDLC B STA %x", val);
814
815	adapter->bcs[0].mode = -1;
816	adapter->bcs[1].mode = -1;
817	modehdlc(&adapter->bcs[0], L1_MODE_NULL);
818	modehdlc(&adapter->bcs[1], L1_MODE_NULL);
819
820	return 0;
821
822err_region:
823	release_region(adapter->io, 32);
824err:
825	return retval;
826}
827
828static void fcpcipnp_release(struct fritz_adapter *adapter)
829{
830	DBG(1, "");
831
832	outb(0, adapter->io + AVM_STATUS0);
833	free_irq(adapter->irq, adapter);
834	release_region(adapter->io, 32);
835}
836
837// ----------------------------------------------------------------------
838
839static struct fritz_adapter *new_adapter(void)
840{
841	struct fritz_adapter *adapter;
842	struct hisax_b_if *b_if[2];
843	int i;
844
845	adapter = kzalloc(sizeof(struct fritz_adapter), GFP_KERNEL);
846	if (!adapter)
847		return NULL;
848
849	adapter->isac.hisax_d_if.owner = THIS_MODULE;
850	adapter->isac.hisax_d_if.ifc.priv = &adapter->isac;
851	adapter->isac.hisax_d_if.ifc.l2l1 = isac_d_l2l1;
852
853	for (i = 0; i < 2; i++) {
854		adapter->bcs[i].adapter = adapter;
855		adapter->bcs[i].channel = i;
856		adapter->bcs[i].b_if.ifc.priv = &adapter->bcs[i];
857		adapter->bcs[i].b_if.ifc.l2l1 = fritz_b_l2l1;
858	}
859
860	for (i = 0; i < 2; i++)
861		b_if[i] = &adapter->bcs[i].b_if;
862
863	if (hisax_register(&adapter->isac.hisax_d_if, b_if, "fcpcipnp",
864			   protocol) != 0) {
865		kfree(adapter);
866		adapter = NULL;
867	}
868
869	return adapter;
870}
871
872static void delete_adapter(struct fritz_adapter *adapter)
873{
874	hisax_unregister(&adapter->isac.hisax_d_if);
875	kfree(adapter);
876}
877
878static int fcpci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
879{
880	struct fritz_adapter *adapter;
881	int retval;
882
883	retval = -ENOMEM;
884	adapter = new_adapter();
885	if (!adapter)
886		goto err;
887
888	pci_set_drvdata(pdev, adapter);
889
890	if (pdev->device == PCI_DEVICE_ID_AVM_A1_V2)
891		adapter->type = AVM_FRITZ_PCIV2;
892	else
893		adapter->type = AVM_FRITZ_PCI;
894
895	retval = pci_enable_device(pdev);
896	if (retval)
897		goto err_free;
898
899	adapter->io = pci_resource_start(pdev, 1);
900	adapter->irq = pdev->irq;
901
902	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at %s\n",
903	       (char *) ent->driver_data, pci_name(pdev));
904
905	retval = fcpcipnp_setup(adapter);
906	if (retval)
907		goto err_free;
908
909	return 0;
910
911err_free:
912	delete_adapter(adapter);
913err:
914	return retval;
915}
916
917#ifdef CONFIG_PNP
918static int fcpnp_probe(struct pnp_dev *pdev, const struct pnp_device_id *dev_id)
919{
920	struct fritz_adapter *adapter;
921	int retval;
922
923	if (!pdev)
924		return (-ENODEV);
925
926	retval = -ENOMEM;
927	adapter = new_adapter();
928	if (!adapter)
929		goto err;
930
931	pnp_set_drvdata(pdev, adapter);
932
933	adapter->type = AVM_FRITZ_PNP;
934
935	pnp_disable_dev(pdev);
936	retval = pnp_activate_dev(pdev);
937	if (retval < 0) {
938		printk(KERN_WARNING "%s: pnp_activate_dev(%s) ret(%d)\n", __func__,
939		       (char *)dev_id->driver_data, retval);
940		goto err_free;
941	}
942	adapter->io = pnp_port_start(pdev, 0);
943	adapter->irq = pnp_irq(pdev, 0);
944
945	printk(KERN_INFO "hisax_fcpcipnp: found adapter %s at IO %#x irq %d\n",
946	       (char *) dev_id->driver_data, adapter->io, adapter->irq);
947
948	retval = fcpcipnp_setup(adapter);
949	if (retval)
950		goto err_free;
951
952	return 0;
953
954err_free:
955	delete_adapter(adapter);
956err:
957	return retval;
958}
959
960static void fcpnp_remove(struct pnp_dev *pdev)
961{
962	struct fritz_adapter *adapter = pnp_get_drvdata(pdev);
963
964	if (adapter) {
965		fcpcipnp_release(adapter);
966		delete_adapter(adapter);
967	}
968	pnp_disable_dev(pdev);
969}
970
971static struct pnp_driver fcpnp_driver = {
972	.name		= "fcpnp",
973	.probe		= fcpnp_probe,
974	.remove		= fcpnp_remove,
975	.id_table	= fcpnp_ids,
976};
977#endif
978
979static void fcpci_remove(struct pci_dev *pdev)
980{
981	struct fritz_adapter *adapter = pci_get_drvdata(pdev);
982
983	fcpcipnp_release(adapter);
984	pci_disable_device(pdev);
985	delete_adapter(adapter);
986}
987
988static struct pci_driver fcpci_driver = {
989	.name		= "fcpci",
990	.probe		= fcpci_probe,
991	.remove		= fcpci_remove,
992	.id_table	= fcpci_ids,
993};
994
995static int __init hisax_fcpcipnp_init(void)
996{
997	int retval;
998
999	printk(KERN_INFO "hisax_fcpcipnp: Fritz!Card PCI/PCIv2/PnP ISDN driver v0.0.1\n");
1000
1001	retval = pci_register_driver(&fcpci_driver);
1002	if (retval)
1003		return retval;
1004#ifdef CONFIG_PNP
1005	retval = pnp_register_driver(&fcpnp_driver);
1006	if (retval < 0) {
1007		pci_unregister_driver(&fcpci_driver);
1008		return retval;
1009	}
1010#endif
1011	return 0;
1012}
1013
1014static void __exit hisax_fcpcipnp_exit(void)
1015{
1016#ifdef CONFIG_PNP
1017	pnp_unregister_driver(&fcpnp_driver);
1018#endif
1019	pci_unregister_driver(&fcpci_driver);
1020}
1021
1022module_init(hisax_fcpcipnp_init);
1023module_exit(hisax_fcpcipnp_exit);
1024