11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* $Id: hfc_pci.c,v 1.48.2.4 2004/02/11 13:21:33 keil Exp $
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
396de0e252cedffad61b3cb5e05662c591898e69aJan Engelhardt * low level driver for CCD's hfc-pci based cards
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Author       Werner Cornelius
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              based on existing driver for CCD hfc ISA cards
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright    by Werner Cornelius  <werner@isdn4linux.de>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *              by Karsten Keil      <keil@isdn4linux.de>
998fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * This software may be used and distributed according to the terms
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * of the GNU General Public License, incorporated herein by reference.
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * For changes and modifications please read
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Documentation/isdn/HiSax.cert
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hisax.h"
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "hfc_pci.h"
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "isdnl1.h"
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/pci.h>
23d43c36dc6b357fa1806800f18aa30123c747a6d1Alexey Dobriyan#include <linux/sched.h>
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/interrupt.h>
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const char *hfcpci_revision = "$Revision: 1.48.2.4 $";
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* table entry in the PCI devices list */
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldstypedef struct {
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int vendor_id;
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int device_id;
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *vendor_name;
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char *card_name;
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} PCI_ENTRY;
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define NT_T1_COUNT	20	/* number of 3.125ms interrupts for G2 timeout */
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CLKDEL_TE	0x0e	/* CLKDEL in TE mode */
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CLKDEL_NT	0x6c	/* CLKDEL in NT mode */
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic const PCI_ENTRY id_list[] =
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_2BD0, "CCD/Billion/Asuscom", "2BD0"},
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B000, "Billion", "B000"},
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B006, "Billion", "B006"},
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B007, "Billion", "B007"},
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B008, "Billion", "B008"},
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B009, "Billion", "B009"},
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00A, "Billion", "B00A"},
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00B, "Billion", "B00B"},
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B00C, "Billion", "B00C"},
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B100, "Seyeon", "B100"},
521e4b27df55166ce3b276f55bab223fa4ae8c5525Karsten Keil	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B700, "Primux II S0", "B700"},
531e4b27df55166ce3b276f55bab223fa4ae8c5525Karsten Keil	{PCI_VENDOR_ID_CCD, PCI_DEVICE_ID_CCD_B701, "Primux II S0 NT", "B701"},
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_ABOCOM, PCI_DEVICE_ID_ABOCOM_2BD1, "Abocom/Magitek", "2BD1"},
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_ASUSTEK, PCI_DEVICE_ID_ASUSTEK_0675, "Asuscom/Askey", "675"},
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_T_CONCEPT, "German telekom", "T-Concept"},
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_BERKOM, PCI_DEVICE_ID_BERKOM_A1T, "German telekom", "A1T"},
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_ANIGMA, PCI_DEVICE_ID_ANIGMA_MC145575, "Motorola MC145575", "MC145575"},
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{PCI_VENDOR_ID_ZOLTRIX, PCI_DEVICE_ID_ZOLTRIX_2BD0, "Zoltrix", "2BD0"},
60475be4d85a274d0961593db41cf85689db1d583cJoe Perches	{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_E, "Digi International", "Digi DataFire Micro V IOM2 (Europe)"},
61475be4d85a274d0961593db41cf85689db1d583cJoe Perches	{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_E, "Digi International", "Digi DataFire Micro V (Europe)"},
62475be4d85a274d0961593db41cf85689db1d583cJoe Perches	{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_IOM2_A, "Digi International", "Digi DataFire Micro V IOM2 (North America)"},
63475be4d85a274d0961593db41cf85689db1d583cJoe Perches	{PCI_VENDOR_ID_DIGI, PCI_DEVICE_ID_DIGI_DF_M_A, "Digi International", "Digi DataFire Micro V (North America)"},
64a063cf5b7dde94d98f3f7c9f1c951e02c6564022Karsten Keil	{PCI_VENDOR_ID_SITECOM, PCI_DEVICE_ID_SITECOM_DC105V2, "Sitecom Europe", "DC-105 ISDN PCI"},
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	{0, 0, NULL, NULL},
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************/
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* free hardware resources used by driver */
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************/
72672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic void
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsrelease_io_hfcpci(struct IsdnCardState *cs)
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "HiSax: release hfcpci at %p\n",
76475be4d85a274d0961593db41cf85689db1d583cJoe Perches	       cs->hw.hfcpci.pci_io);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.int_m2 = 0;					/* interrupt output off ! */
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);			/* Reset On */
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mdelay(10);
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CIRM, 0);					/* Reset Off */
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mdelay(10);
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, 0);	/* disable memory mapped ports + busmaster */
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	del_timer(&cs->hw.hfcpci.timer);
868a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	pci_free_consistent(cs->hw.hfcpci.dev, 0x8000,
87475be4d85a274d0961593db41cf85689db1d583cJoe Perches			    cs->hw.hfcpci.fifos, cs->hw.hfcpci.dma);
888a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	cs->hw.hfcpci.fifos = NULL;
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	iounmap((void *)cs->hw.hfcpci.pci_io);
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************************/
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* function called to reset the HFC PCI chip. A complete software reset of chip */
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* and fifos is done.                                                           */
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************************/
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreset_hfcpci(struct IsdnCardState *cs)
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.int_m2 = 0;	/* interrupt output off ! */
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "HFC_PCI: resetting card\n");
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO + PCI_ENA_MASTER);	/* enable memory ports + busmaster */
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CIRM, HFCPCI_RESET);	/* Reset On */
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mdelay(10);
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CIRM, 0);	/* Reset Off */
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mdelay(10);
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (Read_hfc(cs, HFCPCI_STATUS) & 2)
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "HFC-PCI init bit busy\n");
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.fifo_en = 0x30;	/* only D fifos enabled */
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.trm = 0 + HFCPCI_BTRANS_THRESMASK;	/* no echo connect , threshold */
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_TE); /* ST-Bit delay for TE-Mode */
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.sctrl_e = HFCPCI_AUTO_AWAKE;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e);	/* S/T Auto awake */
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.bswapped = 0;	/* no exchange */
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.nt_mode = 0;	/* we are in TE mode */
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.ctmt = HFCPCI_TIM3_125 | HFCPCI_AUTO_TIMER;
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.int_m1 = HFCPCI_INTS_DTRANS | HFCPCI_INTS_DREC |
127475be4d85a274d0961593db41cf85689db1d583cJoe Perches		HFCPCI_INTS_L1STATE | HFCPCI_INTS_TIMER;
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Clear already pending ints */
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (Read_hfc(cs, HFCPCI_INT_S1));
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 2);	/* HFC ST 2 */
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	udelay(10);
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_STATES, 2);	/* HFC ST 2 */
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.mst_m = HFCPCI_MASTER;	/* HFC Master Mode */
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.sctrl = 0x40;	/* set tx_lo mode, error in datasheet ! */
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.sctrl_r = 0;
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Init GCI/IOM2 in master mode */
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Slots 0 and 1 are set for B-chan 1 and 2 */
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* D- and monitor/CI channel are not enabled */
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* STIO2 is used as data input, B1+B2 from IOM->ST */
14925985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* ST B-channel send disabled -> continuous 1s */
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* The IOM slots are always enabled */
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.conn = 0x36;	/* set data flow directions */
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_B1_SSL, 0x80);	/* B1-Slot 0 STIO1 out enabled */
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_B2_SSL, 0x81);	/* B2-Slot 1 STIO1 out enabled */
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_B1_RSL, 0x80);	/* B1-Slot 0 STIO2 in enabled */
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_B2_RSL, 0x81);	/* B2-Slot 1 STIO2 in enabled */
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Finally enable IRQ output */
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.int_m2 = HFCPCI_IRQ_ENABLE;
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (Read_hfc(cs, HFCPCI_INT_S1));
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************/
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Timer function called when kernel timer expires */
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************/
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshfcpci_Timer(struct IsdnCardState *cs)
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.timer.expires = jiffies + 75;
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* WD RESET */
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*      WriteReg(cs, HFCD_DATA, HFCD_CTMT, cs->hw.hfcpci.ctmt | 0x80);
173475be4d85a274d0961593db41cf85689db1d583cJoe Perches	add_timer(&cs->hw.hfcpci.timer);
174475be4d85a274d0961593db41cf85689db1d583cJoe Perches*/
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************/
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* schedule a new D-channel task */
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************/
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssched_event_D_pci(struct IsdnCardState *cs, int event)
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(event, &cs->event);
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	schedule_work(&cs->tqueue);
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************/
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* schedule a new b_channel task */
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************/
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshfcpci_sched_event(struct BCState *bcs, int event)
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_set_bit(event, &bcs->event);
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	schedule_work(&bcs->tqueue);
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************************************/
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* select a b-channel entry matching and active */
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/************************************************/
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstruct BCState *
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsSel_BCS(struct IsdnCardState *cs, int channel)
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->bcs[0].mode && (cs->bcs[0].channel == channel))
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (&cs->bcs[0]);
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else if (cs->bcs[1].mode && (cs->bcs[1].channel == channel))
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (&cs->bcs[1]);
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (NULL);
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************/
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* clear the desired B-channel rx fifo */
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************/
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void hfcpci_clear_fifo_rx(struct IsdnCardState *cs, int fifo)
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       u_char fifo_state;
218475be4d85a274d0961593db41cf85689db1d583cJoe Perches	bzfifo_type *bzr;
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fifo) {
221475be4d85a274d0961593db41cf85689db1d583cJoe Perches		bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fifo_state = cs->hw.hfcpci.fifo_en & HFCPCI_FIFOEN_B2RX;
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
224475be4d85a274d0961593db41cf85689db1d583cJoe Perches		bzr = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fifo_state = cs->hw.hfcpci.fifo_en & HFCPCI_FIFOEN_B1RX;
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fifo_state)
228475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.fifo_en ^= fifo_state;
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.last_bfifo_cnt[fifo] = 0;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzr->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzr->za[MAX_B_FRAMES].z2 = bzr->za[MAX_B_FRAMES].z1;
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzr->f1 = MAX_B_FRAMES;
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzr->f2 = bzr->f1;	/* init F pointers to remain constant */
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fifo_state)
236475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.fifo_en |= fifo_state;
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
23898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************/
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* clear the desired B-channel tx fifo */
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************/
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void hfcpci_clear_fifo_tx(struct IsdnCardState *cs, int fifo)
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{       u_char fifo_state;
245475be4d85a274d0961593db41cf85689db1d583cJoe Perches	bzfifo_type *bzt;
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fifo) {
248475be4d85a274d0961593db41cf85689db1d583cJoe Perches		bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fifo_state = cs->hw.hfcpci.fifo_en & HFCPCI_FIFOEN_B2TX;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
251475be4d85a274d0961593db41cf85689db1d583cJoe Perches		bzt = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fifo_state = cs->hw.hfcpci.fifo_en & HFCPCI_FIFOEN_B1TX;
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fifo_state)
255475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.fifo_en ^= fifo_state;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzt->za[MAX_B_FRAMES].z1 = B_FIFO_SIZE + B_SUB_VAL - 1;
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzt->za[MAX_B_FRAMES].z2 = bzt->za[MAX_B_FRAMES].z1;
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzt->f1 = MAX_B_FRAMES;
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzt->f2 = bzt->f1;	/* init F pointers to remain constant */
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fifo_state)
262475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.fifo_en |= fifo_state;
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
26498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik}
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************************/
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* read a complete B-frame out of the buffer */
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************************/
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sk_buff
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds*
271475be4d85a274d0961593db41cf85689db1d583cJoe Percheshfcpci_empty_fifo(struct BCState *bcs, bzfifo_type *bz, u_char *bdata, int count)
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *ptr, *ptr1, new_f2;
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = bcs->cs;
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int total, maxlen, new_z2;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	z_type *zp;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((cs->debug & L1_DEB_HSCX) && !(cs->debug & L1_DEB_HSCX_FIFO))
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "hfcpci_empty_fifo");
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	zp = &bz->za[bz->f2];	/* point to Z-Regs */
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_z2 = zp->z2 + count;	/* new position in fifo */
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((count > HSCX_BUFMAX + 3) || (count < 4) ||
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (*(bdata + (zp->z1 - B_SUB_VAL)))) {
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_WARN)
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci_empty_fifo: incoming packet invalid length %d or crc", count);
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ERROR_STATISTIC
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bcs->err_inv++;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bz->za[new_f2].z2 = new_z2;
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bz->f2 = new_f2;	/* next buffer */
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb = NULL;
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (!(skb = dev_alloc_skb(count - 3)))
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		total = count;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= 3;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptr = skb_put(skb, count);
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (zp->z2 + count <= B_FIFO_SIZE + B_SUB_VAL)
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			maxlen = count;		/* complete transfer */
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(ptr, ptr1, maxlen);	/* copy data */
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count -= maxlen;
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (count) {	/* rest remaining */
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ptr += maxlen;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ptr1 = bdata;	/* start of buffer */
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ptr, ptr1, count);	/* rest */
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
3171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bz->za[new_f2].z2 = new_z2;
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bz->f2 = new_f2;	/* next buffer */
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (skb);
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************/
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* D-channel receive procedure */
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************/
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsint
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreceive_dmsg(struct IsdnCardState *cs)
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int maxlen;
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rcnt, total;
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int count = 5;
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *ptr, *ptr1;
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dfifo_type *df;
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	z_type *zp;
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_rx;
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "rec_dmsg blocked");
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (1);
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (((df->f1 & D_FREG_MASK) != (df->f2 & D_FREG_MASK)) && count--) {
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		zp = &df->za[df->f2 & D_FREG_MASK];
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcnt = zp->z1 - zp->z2;
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rcnt < 0)
3481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt += D_FIFO_SIZE;
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcnt++;
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_ISAC)
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci recd f1(%d) f2(%d) z1(%x) z2(%x) cnt(%d)",
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				df->f1, df->f2, zp->z1, zp->z2, rcnt);
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((rcnt > MAX_DFRAME_LEN + 3) || (rcnt < 4) ||
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (df->data[zp->z1])) {
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cs->debug & L1_DEB_WARN)
357465b1678ebdf5dbd9bc0502358ae472343351c2cMasanari Iida				debugl1(cs, "empty_fifo hfcpci packet inv. len %d or crc %d", rcnt, df->data[zp->z1]);
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ERROR_STATISTIC
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->err_rx++;
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);	/* next buffer */
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + rcnt) & (D_FIFO_SIZE - 1);
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else if ((skb = dev_alloc_skb(rcnt - 3))) {
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			total = rcnt;
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt -= 3;
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ptr = skb_put(skb, rcnt);
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (zp->z2 + rcnt <= D_FIFO_SIZE)
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				maxlen = rcnt;	/* complete transfer */
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				maxlen = D_FIFO_SIZE - zp->z2;	/* maximum */
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ptr1 = df->data + zp->z2;	/* start of data */
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ptr, ptr1, maxlen);	/* copy data */
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt -= maxlen;
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (rcnt) {	/* rest remaining */
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ptr += maxlen;
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ptr1 = df->data;	/* start of buffer */
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(ptr, ptr1, rcnt);	/* rest */
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			df->f2 = ((df->f2 + 1) & MAX_D_FRAMES) | (MAX_D_FRAMES + 1);	/* next buffer */
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			df->za[df->f2 & D_FREG_MASK].z2 = (zp->z2 + total) & (D_FIFO_SIZE - 1);
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_queue_tail(&cs->rq, skb);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			sched_event_D_pci(cs, D_RCVBUFREADY);
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			printk(KERN_WARNING "HFC-PCI: D receive out of memory\n");
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (1);
3921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************/
3951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* check for transparent receive data and read max one threshold size if avail */
3961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************************************************/
397672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic int
398475be4d85a274d0961593db41cf85689db1d583cJoe Percheshfcpci_empty_fifo_trans(struct BCState *bcs, bzfifo_type *bz, u_char *bdata)
3991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short *z1r, *z2r;
4011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int new_z2, fcnt, maxlen;
4021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
4031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *ptr, *ptr1;
4041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	z1r = &bz->za[MAX_B_FRAMES].z1;		/* pointer to z reg */
4061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	z2r = z1r + 1;
4071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(fcnt = *z1r - *z2r))
4091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);	/* no data avail */
4101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fcnt <= 0)
4121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fcnt += B_FIFO_SIZE;	/* bytes actually buffered */
4131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fcnt > HFCPCI_BTRANS_THRESHOLD)
4141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fcnt = HFCPCI_BTRANS_THRESHOLD;		/* limit size */
4151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_z2 = *z2r + fcnt;	/* new position in fifo */
4171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
4181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
4191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(skb = dev_alloc_skb(fcnt)))
4211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_WARNING "HFCPCI: receive out of memory\n");
4221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else {
4231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptr = skb_put(skb, fcnt);
4241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (*z2r + fcnt <= B_FIFO_SIZE + B_SUB_VAL)
4251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			maxlen = fcnt;	/* complete transfer */
4261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
4271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			maxlen = B_FIFO_SIZE + B_SUB_VAL - *z2r;	/* maximum */
4281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ptr1 = bdata + (*z2r - B_SUB_VAL);	/* start of data */
4301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(ptr, ptr1, maxlen);	/* copy data */
4311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fcnt -= maxlen;
4321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (fcnt) {	/* rest remaining */
4341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ptr += maxlen;
4351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ptr1 = bdata;	/* start of buffer */
4361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ptr, ptr1, fcnt);	/* rest */
4371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_tail(&bcs->rqueue, skb);
4391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hfcpci_sched_event(bcs, B_RCVBUFREADY);
4401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	*z2r = new_z2;		/* new position */
4431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (1);
4441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				/* hfcpci_empty_fifo_trans */
4451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**********************************/
4471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* B-channel main receive routine */
4481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**********************************/
449672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic void
4501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmain_rec_hfcpci(struct BCState *bcs)
4511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
4521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = bcs->cs;
4531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rcnt, real_fifo;
4541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int receive, count = 5;
4551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb;
4561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzfifo_type *bz;
4571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *bdata;
4581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	z_type *zp;
4591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
4621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
4631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
4641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		real_fifo = 1;
4651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
4661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b1;
4671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b1;
4681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		real_fifo = 0;
4691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
470475be4d85a274d0961593db41cf85689db1d583cJoe PerchesBegin:
4711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count--;
4721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
4731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "rec_data %d blocked", bcs->channel);
4741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
4751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
4761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bz->f1 != bz->f2) {
4771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_HSCX)
4781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci rec %d f1(%d) f2(%d)",
4791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bcs->channel, bz->f1, bz->f2);
4801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		zp = &bz->za[bz->f2];
4811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
4821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcnt = zp->z1 - zp->z2;
4831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rcnt < 0)
4841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt += B_FIFO_SIZE;
4851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcnt++;
4861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_HSCX)
4871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci rec %d z1(%x) z2(%x) cnt(%d)",
4881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bcs->channel, zp->z1, zp->z2, rcnt);
4891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((skb = hfcpci_empty_fifo(bcs, bz, bdata, rcnt))) {
4901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			skb_queue_tail(&bcs->rqueue, skb);
4911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			hfcpci_sched_event(bcs, B_RCVBUFREADY);
4921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
4931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcnt = bz->f1 - bz->f2;
4941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rcnt < 0)
4951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt += MAX_B_FRAMES + 1;
4961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->hw.hfcpci.last_bfifo_cnt[real_fifo] > rcnt + 1) {
497475be4d85a274d0961593db41cf85689db1d583cJoe Perches			rcnt = 0;
4981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			hfcpci_clear_fifo_rx(cs, real_fifo);
4991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
5001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.last_bfifo_cnt[real_fifo] = rcnt;
5011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rcnt > 1)
5021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			receive = 1;
5031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
5041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			receive = 0;
5051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else if (bcs->mode == L1_MODE_TRANS)
5061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		receive = hfcpci_empty_fifo_trans(bcs, bz, bdata);
5071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
5081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		receive = 0;
5091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
5101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count && receive)
5111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto Begin;
5121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**************************/
5151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* D-channel send routine */
5161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**************************/
5171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshfcpci_fill_dfifo(struct IsdnCardState *cs)
5191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fcnt;
5211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int count, new_z1, maxlen;
5221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dfifo_type *df;
5231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *src, *dst, new_f1;
5241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!cs->tx_skb)
5261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->tx_skb->len <= 0)
5281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	df = &((fifo_area *) (cs->hw.hfcpci.fifos))->d_chan.d_tx;
5311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->debug & L1_DEB_ISAC)
5331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "hfcpci_fill_Dfifo f1(%d) f2(%d) z1(f1)(%x)",
5341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			df->f1, df->f2,
5351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			df->za[df->f1 & D_FREG_MASK].z1);
5361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fcnt = df->f1 - df->f2;	/* frame count actually buffered */
5371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fcnt < 0)
5381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fcnt += (MAX_D_FRAMES + 1);	/* if wrap around */
5391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fcnt > (MAX_D_FRAMES - 1)) {
5401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_ISAC)
5411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci_fill_Dfifo more as 14 frames");
5421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef ERROR_STATISTIC
5431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->err_tx++;
5441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
5451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* now determine free bytes in FIFO buffer */
5481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = df->za[df->f2 & D_FREG_MASK].z2 - df->za[df->f1 & D_FREG_MASK].z1 - 1;
5491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count <= 0)
5501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count += D_FIFO_SIZE;	/* count now contains available bytes */
5511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->debug & L1_DEB_ISAC)
5539920239c90d5f6dadfb44325abf3568a5e3fd827Joe Perches		debugl1(cs, "hfcpci_fill_Dfifo count(%u/%d)",
5541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->tx_skb->len, count);
5551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count < cs->tx_skb->len) {
5561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_ISAC)
5571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci_fill_Dfifo no fifo mem");
5581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
5591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = cs->tx_skb->len;	/* get frame len */
5611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_z1 = (df->za[df->f1 & D_FREG_MASK].z1 + count) & (D_FIFO_SIZE - 1);
5621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_f1 = ((df->f1 + 1) & D_FREG_MASK) | (D_FREG_MASK + 1);
5631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	src = cs->tx_skb->data;	/* source pointer */
5641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dst = df->data + df->za[df->f1 & D_FREG_MASK].z1;
5651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	maxlen = D_FIFO_SIZE - df->za[df->f1 & D_FREG_MASK].z1;		/* end fifo */
5661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (maxlen > count)
5671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		maxlen = count;	/* limit size */
5681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(dst, src, maxlen);	/* first copy */
5691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count -= maxlen;	/* remaining bytes */
5711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count) {
5721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dst = df->data;	/* start of buffer */
5731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		src += maxlen;	/* new position */
5741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(dst, src, count);
5751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
5761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	df->za[new_f1 & D_FREG_MASK].z1 = new_z1;	/* for next buffer */
5771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	df->za[df->f1 & D_FREG_MASK].z1 = new_z1;	/* new pos actual buffer */
5781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	df->f1 = new_f1;	/* next frame */
5791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_kfree_skb_any(cs->tx_skb);
5811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->tx_skb = NULL;
5821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
5831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**************************/
5851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* B-channel send routine */
5861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**************************/
5871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
5881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshfcpci_fill_fifo(struct BCState *bcs)
5891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
5901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = bcs->cs;
5911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int maxlen, fcnt;
5921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int count, new_z1;
5931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzfifo_type *bz;
5941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *bdata;
5951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char new_f1, *src, *dst;
5961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned short *z1t, *z2t;
5971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
5981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!bcs->tx_skb)
5991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bcs->tx_skb->len <= 0)
6011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((bcs->channel) && (!cs->hw.hfcpci.bswapped)) {
6041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b2;
6051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b2;
6061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
6071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txbz_b1;
6081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.txdat_b1;
6091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bcs->mode == L1_MODE_TRANS) {
6121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		z1t = &bz->za[MAX_B_FRAMES].z1;
6131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		z2t = z1t + 1;
6141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_HSCX)
6151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci_fill_fifo_trans %d z1(%x) z2(%x)",
6161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bcs->channel, *z1t, *z2t);
6171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fcnt = *z2t - *z1t;
6181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (fcnt <= 0)
6191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			fcnt += B_FIFO_SIZE;	/* fcnt contains available bytes in fifo */
6201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fcnt = B_FIFO_SIZE - fcnt;	/* remaining bytes to send */
6211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		while ((fcnt < 2 * HFCPCI_BTRANS_THRESHOLD) && (bcs->tx_skb)) {
6231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (bcs->tx_skb->len < B_FIFO_SIZE - fcnt) {
6241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				/* data is suitable for fifo */
6251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				count = bcs->tx_skb->len;
6261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				new_z1 = *z1t + count;	/* new buffer Position */
6281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
6291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
6301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				src = bcs->tx_skb->data;	/* source pointer */
6311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				dst = bdata + (*z1t - B_SUB_VAL);
6321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				maxlen = (B_FIFO_SIZE + B_SUB_VAL) - *z1t;	/* end of fifo */
6331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (maxlen > count)
6341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					maxlen = count;		/* limit size */
6351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(dst, src, maxlen);	/* first copy */
6361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				count -= maxlen;	/* remaining bytes */
6381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (count) {
6391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dst = bdata;	/* start of buffer */
6401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					src += maxlen;	/* new position */
6411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					memcpy(dst, src, count);
6421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
6431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bcs->tx_cnt -= bcs->tx_skb->len;
6441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				fcnt += bcs->tx_skb->len;
6451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				*z1t = new_z1;	/* now send data */
6461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else if (cs->debug & L1_DEB_HSCX)
6471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				debugl1(cs, "hfcpci_fill_fifo_trans %d frame length %d discarded",
6481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					bcs->channel, bcs->tx_skb->len);
6491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
650475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) &&
651475be4d85a274d0961593db41cf85689db1d583cJoe Perches			    (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
6521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				u_long	flags;
6531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				spin_lock_irqsave(&bcs->aclock, flags);
6541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bcs->ackcnt += bcs->tx_skb->len;
6551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				spin_unlock_irqrestore(&bcs->aclock, flags);
6561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				schedule_event(bcs, B_ACKPENDING);
6571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
6581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_kfree_skb_any(bcs->tx_skb);
6601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bcs->tx_skb = skb_dequeue(&bcs->squeue);	/* fetch next data */
6611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
6621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
6631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->debug & L1_DEB_HSCX)
6661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "hfcpci_fill_fifo_hdlc %d f1(%d) f2(%d) z1(f1)(%x)",
6671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bcs->channel, bz->f1, bz->f2,
6681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bz->za[bz->f1].z1);
6691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fcnt = bz->f1 - bz->f2;	/* frame count actually buffered */
6711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fcnt < 0)
6721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		fcnt += (MAX_B_FRAMES + 1);	/* if wrap around */
6731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (fcnt > (MAX_B_FRAMES - 1)) {
6741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_HSCX)
6751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci_fill_Bfifo more as 14 frames");
6761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* now determine free bytes in FIFO buffer */
6791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = bz->za[bz->f2].z2 - bz->za[bz->f1].z1 - 1;
6801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count <= 0)
6811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		count += B_FIFO_SIZE;	/* count now contains available bytes */
6821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->debug & L1_DEB_HSCX)
6849920239c90d5f6dadfb44325abf3568a5e3fd827Joe Perches		debugl1(cs, "hfcpci_fill_fifo %d count(%u/%d),%lx",
6851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bcs->channel, bcs->tx_skb->len,
6861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			count, current->state);
6871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count < bcs->tx_skb->len) {
6891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_HSCX)
6901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci_fill_fifo no fifo mem");
6911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
6921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
6931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count = bcs->tx_skb->len;	/* get frame len */
6941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_z1 = bz->za[bz->f1].z1 + count;	/* new buffer Position */
6951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (new_z1 >= (B_FIFO_SIZE + B_SUB_VAL))
6961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new_z1 -= B_FIFO_SIZE;	/* buffer wrap */
6971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
6981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	new_f1 = ((bz->f1 + 1) & MAX_B_FRAMES);
6991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	src = bcs->tx_skb->data;	/* source pointer */
7001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dst = bdata + (bz->za[bz->f1].z1 - B_SUB_VAL);
7011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	maxlen = (B_FIFO_SIZE + B_SUB_VAL) - bz->za[bz->f1].z1;		/* end fifo */
7021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (maxlen > count)
7031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		maxlen = count;	/* limit size */
7041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	memcpy(dst, src, maxlen);	/* first copy */
7051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count -= maxlen;	/* remaining bytes */
7071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count) {
7081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		dst = bdata;	/* start of buffer */
7091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		src += maxlen;	/* new position */
7101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		memcpy(dst, src, count);
7111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->tx_cnt -= bcs->tx_skb->len;
713475be4d85a274d0961593db41cf85689db1d583cJoe Perches	if (test_bit(FLG_LLI_L1WAKEUP, &bcs->st->lli.flag) &&
714475be4d85a274d0961593db41cf85689db1d583cJoe Perches	    (PACKET_NOACK != bcs->tx_skb->pkt_type)) {
7151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		u_long	flags;
7161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_lock_irqsave(&bcs->aclock, flags);
7171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		bcs->ackcnt += bcs->tx_skb->len;
7181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&bcs->aclock, flags);
7191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		schedule_event(bcs, B_ACKPENDING);
7201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bz->za[new_f1].z1 = new_z1;	/* for next buffer */
7231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bz->f1 = new_f1;	/* next frame */
7241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	dev_kfree_skb_any(bcs->tx_skb);
7261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->tx_skb = NULL;
7271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
7281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**********************************************/
7311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* D-channel l1 state call for leased NT-mode */
7321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**********************************************/
7331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
7341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsdch_nt_l2l1(struct PStack *st, int pr, void *arg)
7351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
7371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
739475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_DATA | REQUEST):
740475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PULL | REQUEST):
741475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PULL | INDICATION):
742475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l1.l1hw(st, pr, arg);
743475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
744475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_ACTIVATE | REQUEST):
745475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l1.l1l2(st, PH_ACTIVATE | CONFIRM, NULL);
746475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
747475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_TESTLOOP | REQUEST):
748475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (1 & (long) arg)
749475be4d85a274d0961593db41cf85689db1d583cJoe Perches			debugl1(cs, "PH_TEST_LOOP B1");
750475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (2 & (long) arg)
751475be4d85a274d0961593db41cf85689db1d583cJoe Perches			debugl1(cs, "PH_TEST_LOOP B2");
752475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (!(3 & (long) arg))
753475be4d85a274d0961593db41cf85689db1d583cJoe Perches			debugl1(cs, "PH_TEST_LOOP DISABLED");
754475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l1.l1hw(st, HW_TESTLOOP | REQUEST, arg);
755475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
756475be4d85a274d0961593db41cf85689db1d583cJoe Perches	default:
757475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->debug)
758475be4d85a274d0961593db41cf85689db1d583cJoe Perches			debugl1(cs, "dch_nt_l2l1 msg %04X unhandled", pr);
759475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
7601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
7621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************/
7661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* set/reset echo mode */
7671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************/
7681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
769475be4d85a274d0961593db41cf85689db1d583cJoe Percheshfcpci_auxcmd(struct IsdnCardState *cs, isdn_ctrl *ic)
7701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
7711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long	flags;
7721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int	i = *(unsigned int *) ic->parm.num;
7731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((ic->arg == 98) &&
7751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (!(cs->hw.hfcpci.int_m1 & (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC + HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC)))) {
776475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
7771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Write_hfc(cs, HFCPCI_CLKDEL, CLKDEL_NT); /* ST-Bit delay for NT-Mode */
7781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 0);	/* HFC ST G0 */
7791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(10);
7801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.sctrl |= SCTRL_MODE_NT;
7811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);	/* set NT-mode */
7821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(10);
7831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 1);	/* HFC ST G1 */
7841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		udelay(10);
7851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Write_hfc(cs, HFCPCI_STATES, 1 | HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
7861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->dc.hfcpci.ph_state = 1;
7871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.nt_mode = 1;
7881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.nt_timer = 0;
7891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->stlist->l2.l2l1 = dch_nt_l2l1;
7901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&cs->lock, flags);
7911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "NT mode activated");
7921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (0);
7931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
7941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if ((cs->chanlimit > 1) || (cs->hw.hfcpci.bswapped) ||
7951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    (cs->hw.hfcpci.nt_mode) || (ic->arg != 12))
7961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-EINVAL);
7971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
7981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&cs->lock, flags);
7991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (i) {
8001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->logecho = 1;
8011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.trm |= 0x20;	/* enable echo chan */
8021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_B2REC;
8031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2RX;
8041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
8051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->logecho = 0;
8061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.trm &= ~0x20;	/* disable echo chan */
8071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_B2REC;
8081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2RX;
8091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
8111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
8121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.conn |= 0x10;	/* B2-IOM -> B2-ST */
8131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.ctmt &= ~2;
8141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
8151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
8161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
8171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
8181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
8191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
8201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
8211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&cs->lock, flags);
8221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
8231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				/* hfcpci_auxcmd */
8241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************/
8261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* E-channel receive routine */
8271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*****************************/
8281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
8291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsreceive_emsg(struct IsdnCardState *cs)
8301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
8311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int rcnt;
8321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int receive, count = 5;
8331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bzfifo_type *bz;
8341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *bdata;
8351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	z_type *zp;
8361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char *ptr, *ptr1, new_f2;
8371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int total, maxlen, new_z2;
8381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char e_buffer[256];
8391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bz = &((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxbz_b2;
8411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bdata = ((fifo_area *) (cs->hw.hfcpci.fifos))->b_chans.rxdat_b2;
842475be4d85a274d0961593db41cf85689db1d583cJoe PerchesBegin:
8431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	count--;
8441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
8451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "echo_rec_data blocked");
8461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return;
8471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
8481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (bz->f1 != bz->f2) {
8491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_ISAC)
8501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci e_rec f1(%d) f2(%d)",
8511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				bz->f1, bz->f2);
8521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		zp = &bz->za[bz->f2];
8531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcnt = zp->z1 - zp->z2;
8551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rcnt < 0)
8561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt += B_FIFO_SIZE;
8571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcnt++;
8581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_ISAC)
8591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "hfcpci e_rec z1(%x) z2(%x) cnt(%d)",
8601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				zp->z1, zp->z2, rcnt);
8611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new_z2 = zp->z2 + rcnt;		/* new position in fifo */
8621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (new_z2 >= (B_FIFO_SIZE + B_SUB_VAL))
8631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			new_z2 -= B_FIFO_SIZE;	/* buffer wrap */
8641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		new_f2 = (bz->f2 + 1) & MAX_B_FRAMES;
8651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if ((rcnt > 256 + 3) || (count < 4) ||
8661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		    (*(bdata + (zp->z1 - B_SUB_VAL)))) {
8671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cs->debug & L1_DEB_WARN)
8681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				debugl1(cs, "hfcpci_empty_echan: incoming packet invalid length %d or crc", rcnt);
8691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bz->za[new_f2].z2 = new_z2;
8701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bz->f2 = new_f2;	/* next buffer */
8711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
8721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			total = rcnt;
8731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt -= 3;
8741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ptr = e_buffer;
8751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (zp->z2 <= B_FIFO_SIZE + B_SUB_VAL)
8771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				maxlen = rcnt;	/* complete transfer */
8781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else
8791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				maxlen = B_FIFO_SIZE + B_SUB_VAL - zp->z2;	/* maximum */
8801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			ptr1 = bdata + (zp->z2 - B_SUB_VAL);	/* start of data */
8821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			memcpy(ptr, ptr1, maxlen);	/* copy data */
8831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt -= maxlen;
8841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
8851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (rcnt) {	/* rest remaining */
8861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ptr += maxlen;
8871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ptr1 = bdata;	/* start of buffer */
8881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				memcpy(ptr, ptr1, rcnt);	/* rest */
8891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
8901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bz->za[new_f2].z2 = new_z2;
8911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bz->f2 = new_f2;	/* next buffer */
8921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cs->debug & DEB_DLOG_HEX) {
8931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				ptr = cs->dlog;
8941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if ((total - 3) < MAX_DLOG_SPACE / 3 - 10) {
8951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					*ptr++ = 'E';
8961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					*ptr++ = 'C';
8971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					*ptr++ = 'H';
8981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					*ptr++ = 'O';
8991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					*ptr++ = ':';
9001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ptr += QuickHex(ptr, e_buffer, total - 3);
9011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					ptr--;
9021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					*ptr++ = '\n';
9031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					*ptr = 0;
90435a4a5733b0a8290de39558b82896ab795b108a7Kees Cook					HiSax_putstatus(cs, NULL, "%s", cs->dlog);
9051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else
9061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					HiSax_putstatus(cs, "LogEcho: ", "warning Frame too big (%d)", total - 3);
9071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
9081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		rcnt = bz->f1 - bz->f2;
9111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rcnt < 0)
9121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			rcnt += MAX_B_FRAMES + 1;
9131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (rcnt > 1)
9141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			receive = 1;
9151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		else
9161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			receive = 0;
9171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
9181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		receive = 0;
9191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
9201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (count && receive)
9211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		goto Begin;
9221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}				/* receive_emsg */
9231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************/
9251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Interrupt handler */
9261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************/
9271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic irqreturn_t
9287d12e780e003f93433d49ce78cfedf4b4c52adc5David Howellshfcpci_interrupt(int intno, void *dev_id)
9291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
9301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
9311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = dev_id;
9321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char exval;
9331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct BCState *bcs;
9341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int count = 15;
9351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_char val, stat;
9361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
9371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!(cs->hw.hfcpci.int_m2 & 0x08)) {
9381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "HFC-PCI: int_m2 %x not initialised", cs->hw.hfcpci.int_m2);
9391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return IRQ_NONE;	/* not initialised */
9401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_lock_irqsave(&cs->lock, flags);
9421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (HFCPCI_ANYINT & (stat = Read_hfc(cs, HFCPCI_STATUS))) {
9431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val = Read_hfc(cs, HFCPCI_INT_S1);
9441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_ISAC)
9451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "HFC-PCI: stat(%02x) s1(%02x)", stat, val);
9461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
9471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		spin_unlock_irqrestore(&cs->lock, flags);
9481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return IRQ_NONE;
9491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->debug & L1_DEB_ISAC)
9511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "HFC-PCI irq %x %s", val,
9521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags) ?
9531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			"locked" : "unlocked");
9541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	val &= cs->hw.hfcpci.int_m1;
9551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val & 0x40) {	/* state machine irq */
9561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		exval = Read_hfc(cs, HFCPCI_STATES) & 0xf;
9571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->debug & L1_DEB_ISAC)
9581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			debugl1(cs, "ph_state chg %d->%d", cs->dc.hfcpci.ph_state,
9591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				exval);
9601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->dc.hfcpci.ph_state = exval;
9611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sched_event_D_pci(cs, D_L1STATECHANGE);
9621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val &= ~0x40;
9631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (val & 0x80) {	/* timer irq */
9651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->hw.hfcpci.nt_mode) {
9661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((--cs->hw.hfcpci.nt_timer) < 0)
9671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sched_event_D_pci(cs, D_L1STATECHANGE);
9681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		val &= ~0x80;
9701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
9711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
9721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	while (val) {
9731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (test_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
9741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfcpci.int_s1 |= val;
9751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(&cs->lock, flags);
9761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			return IRQ_HANDLED;
9771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->hw.hfcpci.int_s1 & 0x18) {
9791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			exval = val;
9801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			val = cs->hw.hfcpci.int_s1;
9811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfcpci.int_s1 = exval;
9821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val & 0x08) {
9841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) {
9851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (cs->debug)
9861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					debugl1(cs, "hfcpci spurious 0x08 IRQ");
9871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
9881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				main_rec_hfcpci(bcs);
9891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val & 0x10) {
9911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cs->logecho)
9921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				receive_emsg(cs);
9931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			else if (!(bcs = Sel_BCS(cs, 1))) {
9941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (cs->debug)
9951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					debugl1(cs, "hfcpci spurious 0x10 IRQ");
9961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
9971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				main_rec_hfcpci(bcs);
9981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
9991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val & 0x01) {
10001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(bcs = Sel_BCS(cs, cs->hw.hfcpci.bswapped ? 1 : 0))) {
10011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (cs->debug)
10021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					debugl1(cs, "hfcpci spurious 0x01 IRQ");
10031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
10041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (bcs->tx_skb) {
10051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
10061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						hfcpci_fill_fifo(bcs);
10071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
10081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					} else
10091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						debugl1(cs, "fill_data %d blocked", bcs->channel);
10101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
10111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
10121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
10131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							hfcpci_fill_fifo(bcs);
10141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
10151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						} else
10161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							debugl1(cs, "fill_data %d blocked", bcs->channel);
10171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					} else {
10181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						hfcpci_sched_event(bcs, B_XMTBUFREADY);
10191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
10201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
10211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val & 0x02) {
10241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!(bcs = Sel_BCS(cs, 1))) {
10251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (cs->debug)
10261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					debugl1(cs, "hfcpci spurious 0x02 IRQ");
10271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
10281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (bcs->tx_skb) {
10291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
10301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						hfcpci_fill_fifo(bcs);
10311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
10321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					} else
10331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						debugl1(cs, "fill_data %d blocked", bcs->channel);
10341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
10351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if ((bcs->tx_skb = skb_dequeue(&bcs->squeue))) {
10361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
10371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							hfcpci_fill_fifo(bcs);
10381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
10391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						} else
10401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds							debugl1(cs, "fill_data %d blocked", bcs->channel);
10411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					} else {
10421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						hfcpci_sched_event(bcs, B_XMTBUFREADY);
10431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
10441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
10451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val & 0x20) {	/* receive dframe */
10481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			receive_dmsg(cs);
10491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
10501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (val & 0x04) {	/* dframe transmitted */
10511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (test_and_clear_bit(FLG_DBUSY_TIMER, &cs->HW_Flags))
10521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				del_timer(&cs->dbusytimer);
10531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (test_and_clear_bit(FLG_L1_DBUSY, &cs->HW_Flags))
10541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sched_event_D_pci(cs, D_CLEARBUSY);
10551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cs->tx_skb) {
10561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (cs->tx_skb->len) {
10571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
10581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						hfcpci_fill_dfifo(cs);
10591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
10601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					} else {
10611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds						debugl1(cs, "hfcpci_fill_dfifo irq blocked");
10621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					}
10631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					goto afterXPR;
10641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
10651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					dev_kfree_skb_irq(cs->tx_skb);
10661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					cs->tx_cnt = 0;
10671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					cs->tx_skb = NULL;
10681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
10691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
10701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if ((cs->tx_skb = skb_dequeue(&cs->sq))) {
10711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cs->tx_cnt = 0;
10721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
10731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					hfcpci_fill_dfifo(cs);
10741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
10751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				} else {
10761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					debugl1(cs, "hfcpci_fill_dfifo irq blocked");
10771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				}
10781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
10791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				sched_event_D_pci(cs, D_XMTBUFREADY);
10801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
1081475be4d85a274d0961593db41cf85689db1d583cJoe Perches	afterXPR:
10821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (cs->hw.hfcpci.int_s1 && count--) {
10831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			val = cs->hw.hfcpci.int_s1;
10841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfcpci.int_s1 = 0;
10851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cs->debug & L1_DEB_ISAC)
10861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				debugl1(cs, "HFC-PCI irq %x loop %d", val, 15 - count);
10871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else
10881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			val = 0;
10891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
10901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	spin_unlock_irqrestore(&cs->lock, flags);
10911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return IRQ_HANDLED;
10921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
10931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
10941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************/
10951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* timer callback for D-chan busy resolution. Currently no function */
10961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************************************************/
10971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
10981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshfcpci_dbusy_timer(struct IsdnCardState *cs)
10991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
11011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************************************/
11031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Layer 1 D-channel hardware access */
11041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************************************/
11051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
11061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsHFCPCI_l1hw(struct PStack *st, int pr, void *arg)
11071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
11081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
11091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = (struct IsdnCardState *) st->l1.hardware;
11101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff *skb = arg;
11111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
11121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
1113475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_DATA | REQUEST):
1114475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->debug & DEB_DLOG_HEX)
1115475be4d85a274d0961593db41cf85689db1d583cJoe Perches			LogFrame(cs, skb->data, skb->len);
1116475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->debug & DEB_DLOG_VERBOSE)
1117475be4d85a274d0961593db41cf85689db1d583cJoe Perches			dlogframe(cs, skb, 0);
1118475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1119475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->tx_skb) {
1120475be4d85a274d0961593db41cf85689db1d583cJoe Perches			skb_queue_tail(&cs->sq, skb);
11211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef L2FRAME_DEBUG		/* psa */
1122475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (cs->debug & L1_DEB_LAPD)
1123475be4d85a274d0961593db41cf85689db1d583cJoe Perches				Logl2Frame(cs, skb, "PH_DATA Queued", 0);
11241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1125475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
11261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->tx_skb = skb;
11271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->tx_cnt = 0;
11281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef L2FRAME_DEBUG		/* psa */
11291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cs->debug & L1_DEB_LAPD)
1130475be4d85a274d0961593db41cf85689db1d583cJoe Perches				Logl2Frame(cs, skb, "PH_DATA", 0);
11311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
11321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
11331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				hfcpci_fill_dfifo(cs);
11341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
11351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else
11361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				debugl1(cs, "hfcpci_fill_dfifo blocked");
1137475be4d85a274d0961593db41cf85689db1d583cJoe Perches
1138475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1139475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1140475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1141475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PULL | INDICATION):
1142475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1143475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->tx_skb) {
1144475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if (cs->debug & L1_DEB_WARN)
1145475be4d85a274d0961593db41cf85689db1d583cJoe Perches				debugl1(cs, " l2l1 tx_skb exist this shouldn't happen");
1146475be4d85a274d0961593db41cf85689db1d583cJoe Perches			skb_queue_tail(&cs->sq, skb);
11471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(&cs->lock, flags);
11481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1149475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1150475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->debug & DEB_DLOG_HEX)
1151475be4d85a274d0961593db41cf85689db1d583cJoe Perches			LogFrame(cs, skb->data, skb->len);
1152475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->debug & DEB_DLOG_VERBOSE)
1153475be4d85a274d0961593db41cf85689db1d583cJoe Perches			dlogframe(cs, skb, 0);
1154475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->tx_skb = skb;
1155475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->tx_cnt = 0;
11561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#ifdef L2FRAME_DEBUG		/* psa */
1157475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->debug & L1_DEB_LAPD)
1158475be4d85a274d0961593db41cf85689db1d583cJoe Perches			Logl2Frame(cs, skb, "PH_DATA_PULLED", 0);
11591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1160475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
1161475be4d85a274d0961593db41cf85689db1d583cJoe Perches			hfcpci_fill_dfifo(cs);
1162475be4d85a274d0961593db41cf85689db1d583cJoe Perches			test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
1163475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else
1164475be4d85a274d0961593db41cf85689db1d583cJoe Perches			debugl1(cs, "hfcpci_fill_dfifo blocked");
1165475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1166475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1167475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PULL | REQUEST):
1168475be4d85a274d0961593db41cf85689db1d583cJoe Perches#ifdef L2FRAME_DEBUG		/* psa */
1169475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->debug & L1_DEB_LAPD)
1170475be4d85a274d0961593db41cf85689db1d583cJoe Perches			debugl1(cs, "-> PH_REQUEST_PULL");
1171475be4d85a274d0961593db41cf85689db1d583cJoe Perches#endif
1172475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (!cs->tx_skb) {
1173475be4d85a274d0961593db41cf85689db1d583cJoe Perches			test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1174475be4d85a274d0961593db41cf85689db1d583cJoe Perches			st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1175475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else
1176475be4d85a274d0961593db41cf85689db1d583cJoe Perches			test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1177475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1178475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (HW_RESET | REQUEST):
1179475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1180475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_STATES, HFCPCI_LOAD_STATE | 3);	/* HFC ST 3 */
1181475be4d85a274d0961593db41cf85689db1d583cJoe Perches		udelay(6);
1182475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_STATES, 3);	/* HFC ST 2 */
1183475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
1184475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1185475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_STATES, HFCPCI_ACTIVATE | HFCPCI_DO_ACTION);
1186475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1187475be4d85a274d0961593db41cf85689db1d583cJoe Perches		l1_msg(cs, HW_POWERUP | CONFIRM, NULL);
1188475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1189475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (HW_ENABLE | REQUEST):
1190475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1191475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_STATES, HFCPCI_DO_ACTION);
1192475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1193475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1194475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (HW_DEACTIVATE | REQUEST):
1195475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1196475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.mst_m &= ~HFCPCI_MASTER;
1197475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1198475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1199475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1200475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (HW_INFO3 | REQUEST):
1201475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1202475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.mst_m |= HFCPCI_MASTER;
1203475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1204475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1205475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1206475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (HW_TESTLOOP | REQUEST):
1207475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1208475be4d85a274d0961593db41cf85689db1d583cJoe Perches		switch ((long) arg) {
1209475be4d85a274d0961593db41cf85689db1d583cJoe Perches		case (1):
1210475be4d85a274d0961593db41cf85689db1d583cJoe Perches			Write_hfc(cs, HFCPCI_B1_SSL, 0x80);	/* tx slot */
1211475be4d85a274d0961593db41cf85689db1d583cJoe Perches			Write_hfc(cs, HFCPCI_B1_RSL, 0x80);	/* rx slot */
1212475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~7) | 1;
1213475be4d85a274d0961593db41cf85689db1d583cJoe Perches			Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
12141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1215475be4d85a274d0961593db41cf85689db1d583cJoe Perches
1216475be4d85a274d0961593db41cf85689db1d583cJoe Perches		case (2):
1217475be4d85a274d0961593db41cf85689db1d583cJoe Perches			Write_hfc(cs, HFCPCI_B2_SSL, 0x81);	/* tx slot */
1218475be4d85a274d0961593db41cf85689db1d583cJoe Perches			Write_hfc(cs, HFCPCI_B2_RSL, 0x81);	/* rx slot */
1219475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.conn = (cs->hw.hfcpci.conn & ~0x38) | 0x08;
1220475be4d85a274d0961593db41cf85689db1d583cJoe Perches			Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
12211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1222475be4d85a274d0961593db41cf85689db1d583cJoe Perches
12231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		default:
1224475be4d85a274d0961593db41cf85689db1d583cJoe Perches			spin_unlock_irqrestore(&cs->lock, flags);
12251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (cs->debug & L1_DEB_WARN)
1226475be4d85a274d0961593db41cf85689db1d583cJoe Perches				debugl1(cs, "hfcpci_l1hw loop invalid %4lx", (long) arg);
1227475be4d85a274d0961593db41cf85689db1d583cJoe Perches			return;
1228475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1229475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.trm |= 0x80;	/* enable IOM-loop */
1230475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_TRM, cs->hw.hfcpci.trm);
1231475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1232475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1233475be4d85a274d0961593db41cf85689db1d583cJoe Perches	default:
1234475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (cs->debug & L1_DEB_WARN)
1235475be4d85a274d0961593db41cf85689db1d583cJoe Perches			debugl1(cs, "hfcpci_l1hw unknown pr %4x", pr);
1236475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
12371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************/
12411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* called during init setting l1 stack pointer */
12421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***********************************************/
1243672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic void
12441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_hfcpci(struct PStack *st, struct IsdnCardState *cs)
12451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l1.l1hw = HFCPCI_l1hw;
12471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**************************************/
12501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* send B-channel data if not blocked */
12511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/**************************************/
12521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
12531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshfcpci_send_data(struct BCState *bcs)
12541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = bcs->cs;
12561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!test_and_set_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags)) {
12581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		hfcpci_fill_fifo(bcs);
12591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		test_and_clear_bit(FLG_LOCK_ATOMIC, &cs->HW_Flags);
12601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else
12611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "send_data %d blocked", bcs->channel);
12621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
12631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************/
12651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* activate/deactivate hardware for selected channels and mode */
12661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************************************************/
1267672c3fd9069e5a138f9d4afc9aeb5aa34aacce32Adrian Bunkstatic void
12681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmode_hfcpci(struct BCState *bcs, int mode, int bc)
12691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
12701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = bcs->cs;
12711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int fifo2;
12721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->debug & L1_DEB_HSCX)
12741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "HFCPCI bchannel mode %d bchan %d/%d",
12751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			mode, bc, bcs->channel);
12761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->mode = mode;
12771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->channel = bc;
12781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	fifo2 = bc;
12791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->chanlimit > 1) {
12801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.bswapped = 0;	/* B1 and B2 normal mode */
12811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		cs->hw.hfcpci.sctrl_e &= ~0x80;
12821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
12831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (bc) {
12841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			if (mode != L1_MODE_NULL) {
12851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cs->hw.hfcpci.bswapped = 1;	/* B1 and B2 exchanged */
12861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cs->hw.hfcpci.sctrl_e |= 0x80;
12871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			} else {
12881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cs->hw.hfcpci.bswapped = 0;	/* B1 and B2 normal mode */
12891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				cs->hw.hfcpci.sctrl_e &= ~0x80;
12901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
12911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			fifo2 = 0;
12921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		} else {
12931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfcpci.bswapped = 0;	/* B1 and B2 normal mode */
12941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			cs->hw.hfcpci.sctrl_e &= ~0x80;
12951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
12961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
12971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (mode) {
1298475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (L1_MODE_NULL):
1299475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (bc) {
1300475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl &= ~SCTRL_B2_ENA;
1301475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl_r &= ~SCTRL_B2_ENA;
1302475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1303475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl &= ~SCTRL_B1_ENA;
1304475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl_r &= ~SCTRL_B1_ENA;
1305475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1306475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (fifo2) {
1307475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
1308475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
1309475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1310475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
1311475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
1312475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1313475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1314475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (L1_MODE_TRANS):
1315475be4d85a274d0961593db41cf85689db1d583cJoe Perches		hfcpci_clear_fifo_rx(cs, fifo2);
1316475be4d85a274d0961593db41cf85689db1d583cJoe Perches		hfcpci_clear_fifo_tx(cs, fifo2);
1317475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (bc) {
1318475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
1319475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
1320475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1321475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
1322475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
1323475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1324475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (fifo2) {
1325475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
1326475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
1327475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.ctmt |= 2;
1328475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.conn &= ~0x18;
1329475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1330475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
1331475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
1332475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.ctmt |= 1;
1333475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.conn &= ~0x03;
1334475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1335475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1336475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (L1_MODE_HDLC):
1337475be4d85a274d0961593db41cf85689db1d583cJoe Perches		hfcpci_clear_fifo_rx(cs, fifo2);
1338475be4d85a274d0961593db41cf85689db1d583cJoe Perches		hfcpci_clear_fifo_tx(cs, fifo2);
1339475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (bc) {
1340475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
1341475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
1342475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1343475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
1344475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
1345475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1346475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (fifo2) {
1347475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.last_bfifo_cnt[1] = 0;
1348475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B2;
1349475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
1350475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.ctmt &= ~2;
1351475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.conn &= ~0x18;
1352475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1353475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.last_bfifo_cnt[0] = 0;
1354475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.fifo_en |= HFCPCI_FIFOEN_B1;
1355475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.int_m1 |= (HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
1356475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.ctmt &= ~1;
1357475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.conn &= ~0x03;
1358475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1359475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1360475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (L1_MODE_EXTRN):
1361475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (bc) {
1362475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.conn |= 0x10;
1363475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl |= SCTRL_B2_ENA;
1364475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl_r |= SCTRL_B2_ENA;
1365475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B2;
1366475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B2TRANS + HFCPCI_INTS_B2REC);
1367475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
1368475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.conn |= 0x02;
1369475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl |= SCTRL_B1_ENA;
1370475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.sctrl_r |= SCTRL_B1_ENA;
1371475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.fifo_en &= ~HFCPCI_FIFOEN_B1;
1372475be4d85a274d0961593db41cf85689db1d583cJoe Perches			cs->hw.hfcpci.int_m1 &= ~(HFCPCI_INTS_B1TRANS + HFCPCI_INTS_B1REC);
1373475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1374475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
13751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
13761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_SCTRL_E, cs->hw.hfcpci.sctrl_e);
13771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
13781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_FIFO_EN, cs->hw.hfcpci.fifo_en);
13791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_SCTRL, cs->hw.hfcpci.sctrl);
13801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_SCTRL_R, cs->hw.hfcpci.sctrl_r);
13811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt);
13821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
13831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
13841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************/
13861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Layer2 -> Layer 1 Transfer */
13871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************/
13881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
13891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshfcpci_l2l1(struct PStack *st, int pr, void *arg)
13901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
13911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct BCState	*bcs = st->l1.bcs;
13921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long		flags;
13931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct sk_buff	*skb = arg;
13941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
13951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (pr) {
1396475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_DATA | REQUEST):
1397475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&bcs->cs->lock, flags);
1398475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (bcs->tx_skb) {
1399475be4d85a274d0961593db41cf85689db1d583cJoe Perches			skb_queue_tail(&bcs->squeue, skb);
1400475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else {
14011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bcs->tx_skb = skb;
1402475be4d85a274d0961593db41cf85689db1d583cJoe Perches//				test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
14031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bcs->cs->BC_Send_Data(bcs);
1404475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1405475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&bcs->cs->lock, flags);
1406475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1407475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PULL | INDICATION):
1408475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&bcs->cs->lock, flags);
1409475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (bcs->tx_skb) {
14101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(&bcs->cs->lock, flags);
1411475be4d85a274d0961593db41cf85689db1d583cJoe Perches			printk(KERN_WARNING "hfc_l2l1: this shouldn't happen\n");
14121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			break;
1413475be4d85a274d0961593db41cf85689db1d583cJoe Perches		}
1414475be4d85a274d0961593db41cf85689db1d583cJoe Perches//			test_and_set_bit(BC_FLG_BUSY, &bcs->Flag);
1415475be4d85a274d0961593db41cf85689db1d583cJoe Perches		bcs->tx_skb = skb;
1416475be4d85a274d0961593db41cf85689db1d583cJoe Perches		bcs->cs->BC_Send_Data(bcs);
1417475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&bcs->cs->lock, flags);
1418475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1419475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_PULL | REQUEST):
1420475be4d85a274d0961593db41cf85689db1d583cJoe Perches		if (!bcs->tx_skb) {
1421475be4d85a274d0961593db41cf85689db1d583cJoe Perches			test_and_clear_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1422475be4d85a274d0961593db41cf85689db1d583cJoe Perches			st->l1.l1l2(st, PH_PULL | CONFIRM, NULL);
1423475be4d85a274d0961593db41cf85689db1d583cJoe Perches		} else
1424475be4d85a274d0961593db41cf85689db1d583cJoe Perches			test_and_set_bit(FLG_L1_PULL_REQ, &st->l1.Flags);
1425475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1426475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_ACTIVATE | REQUEST):
1427475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&bcs->cs->lock, flags);
1428475be4d85a274d0961593db41cf85689db1d583cJoe Perches		test_and_set_bit(BC_FLG_ACTIV, &bcs->Flag);
1429475be4d85a274d0961593db41cf85689db1d583cJoe Perches		mode_hfcpci(bcs, st->l1.mode, st->l1.bc);
1430475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&bcs->cs->lock, flags);
1431475be4d85a274d0961593db41cf85689db1d583cJoe Perches		l1_msg_b(st, pr, arg);
1432475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1433475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_DEACTIVATE | REQUEST):
1434475be4d85a274d0961593db41cf85689db1d583cJoe Perches		l1_msg_b(st, pr, arg);
1435475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
1436475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case (PH_DEACTIVATE | CONFIRM):
1437475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&bcs->cs->lock, flags);
1438475be4d85a274d0961593db41cf85689db1d583cJoe Perches		test_and_clear_bit(BC_FLG_ACTIV, &bcs->Flag);
1439475be4d85a274d0961593db41cf85689db1d583cJoe Perches		test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
1440475be4d85a274d0961593db41cf85689db1d583cJoe Perches		mode_hfcpci(bcs, 0, st->l1.bc);
1441475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&bcs->cs->lock, flags);
1442475be4d85a274d0961593db41cf85689db1d583cJoe Perches		st->l1.l1l2(st, PH_DEACTIVATE | CONFIRM, NULL);
1443475be4d85a274d0961593db41cf85689db1d583cJoe Perches		break;
14441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************/
14481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* deactivate B-channel access and queues */
14491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/******************************************/
14501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
14511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsclose_hfcpci(struct BCState *bcs)
14521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mode_hfcpci(bcs, 0, bcs->channel);
14541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(BC_FLG_INIT, &bcs->Flag)) {
14551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_purge(&bcs->rqueue);
14561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_purge(&bcs->squeue);
14571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (bcs->tx_skb) {
14581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			dev_kfree_skb_any(bcs->tx_skb);
14591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			bcs->tx_skb = NULL;
14601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
14611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
14621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************************************/
14661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* init B-channel queues and control */
14671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*************************************/
14681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
14691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsopen_hfcpcistate(struct IsdnCardState *cs, struct BCState *bcs)
14701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (!test_and_set_bit(BC_FLG_INIT, &bcs->Flag)) {
14721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_head_init(&bcs->rqueue);
14731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		skb_queue_head_init(&bcs->squeue);
14741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
14751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->tx_skb = NULL;
14761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	test_and_clear_bit(BC_FLG_BUSY, &bcs->Flag);
14771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->event = 0;
14781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->tx_cnt = 0;
14791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
14801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************/
14831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* inits the stack for B-channel */
14841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*********************************/
14851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
14861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetstack_2b(struct PStack *st, struct BCState *bcs)
14871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
14881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->channel = st->l1.bc;
14891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (open_hfcpcistate(st->l1.hardware, bcs))
14901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return (-1);
14911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l1.bcs = bcs;
14921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	st->l2.l2l1 = hfcpci_l2l1;
14931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	setstack_manager(st);
14941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	bcs->st = st;
14951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	setstack_l1_B(st);
14961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
14971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
14981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
14991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************/
15001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* handle L1 state changes */
15011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/***************************/
15021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
1503c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellshfcpci_bh(struct work_struct *work)
15041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1505c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells	struct IsdnCardState *cs =
1506c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells		container_of(work, struct IsdnCardState, tqueue);
15071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long	flags;
15081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds//      struct PStack *stptr;
15091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(D_L1STATECHANGE, &cs->event)) {
15111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (!cs->hw.hfcpci.nt_mode)
15121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			switch (cs->dc.hfcpci.ph_state) {
1513475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (0):
1514475be4d85a274d0961593db41cf85689db1d583cJoe Perches				l1_msg(cs, HW_RESET | INDICATION, NULL);
1515475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
1516475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (3):
1517475be4d85a274d0961593db41cf85689db1d583cJoe Perches				l1_msg(cs, HW_DEACTIVATE | INDICATION, NULL);
1518475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
1519475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (8):
1520475be4d85a274d0961593db41cf85689db1d583cJoe Perches				l1_msg(cs, HW_RSYNC | INDICATION, NULL);
1521475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
1522475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (6):
1523475be4d85a274d0961593db41cf85689db1d583cJoe Perches				l1_msg(cs, HW_INFO2 | INDICATION, NULL);
1524475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
1525475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (7):
1526475be4d85a274d0961593db41cf85689db1d583cJoe Perches				l1_msg(cs, HW_INFO4_P8 | INDICATION, NULL);
1527475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
1528475be4d85a274d0961593db41cf85689db1d583cJoe Perches			default:
1529475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
1530475be4d85a274d0961593db41cf85689db1d583cJoe Perches			} else {
15311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_lock_irqsave(&cs->lock, flags);
15321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			switch (cs->dc.hfcpci.ph_state) {
1533475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (2):
1534475be4d85a274d0961593db41cf85689db1d583cJoe Perches				if (cs->hw.hfcpci.nt_timer < 0) {
15351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					cs->hw.hfcpci.nt_timer = 0;
15361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
15371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds					Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1538475be4d85a274d0961593db41cf85689db1d583cJoe Perches					/* Clear already pending ints */
1539475be4d85a274d0961593db41cf85689db1d583cJoe Perches					if (Read_hfc(cs, HFCPCI_INT_S1));
1540475be4d85a274d0961593db41cf85689db1d583cJoe Perches					Write_hfc(cs, HFCPCI_STATES, 4 | HFCPCI_LOAD_STATE);
1541475be4d85a274d0961593db41cf85689db1d583cJoe Perches					udelay(10);
1542475be4d85a274d0961593db41cf85689db1d583cJoe Perches					Write_hfc(cs, HFCPCI_STATES, 4);
1543475be4d85a274d0961593db41cf85689db1d583cJoe Perches					cs->dc.hfcpci.ph_state = 4;
1544475be4d85a274d0961593db41cf85689db1d583cJoe Perches				} else {
1545475be4d85a274d0961593db41cf85689db1d583cJoe Perches					cs->hw.hfcpci.int_m1 |= HFCPCI_INTS_TIMER;
1546475be4d85a274d0961593db41cf85689db1d583cJoe Perches					Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1547475be4d85a274d0961593db41cf85689db1d583cJoe Perches					cs->hw.hfcpci.ctmt &= ~HFCPCI_AUTO_TIMER;
1548475be4d85a274d0961593db41cf85689db1d583cJoe Perches					cs->hw.hfcpci.ctmt |= HFCPCI_TIM3_125;
1549475be4d85a274d0961593db41cf85689db1d583cJoe Perches					Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
1550475be4d85a274d0961593db41cf85689db1d583cJoe Perches					Write_hfc(cs, HFCPCI_CTMT, cs->hw.hfcpci.ctmt | HFCPCI_CLTIMER);
1551475be4d85a274d0961593db41cf85689db1d583cJoe Perches					cs->hw.hfcpci.nt_timer = NT_T1_COUNT;
1552475be4d85a274d0961593db41cf85689db1d583cJoe Perches					Write_hfc(cs, HFCPCI_STATES, 2 | HFCPCI_NT_G2_G3);	/* allow G2 -> G3 transition */
1553475be4d85a274d0961593db41cf85689db1d583cJoe Perches				}
1554475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
1555475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (1):
1556475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (3):
1557475be4d85a274d0961593db41cf85689db1d583cJoe Perches			case (4):
1558475be4d85a274d0961593db41cf85689db1d583cJoe Perches				cs->hw.hfcpci.nt_timer = 0;
1559475be4d85a274d0961593db41cf85689db1d583cJoe Perches				cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
1560475be4d85a274d0961593db41cf85689db1d583cJoe Perches				Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1561475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
1562475be4d85a274d0961593db41cf85689db1d583cJoe Perches			default:
1563475be4d85a274d0961593db41cf85689db1d583cJoe Perches				break;
15641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			}
15651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			spin_unlock_irqrestore(&cs->lock, flags);
15661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
15671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
15681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(D_RCVBUFREADY, &cs->event))
15691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DChannel_proc_rcv(cs);
15701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (test_and_clear_bit(D_XMTBUFREADY, &cs->event))
15711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		DChannel_proc_xmt(cs);
15721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************/
15761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* called for card init message */
15771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/********************************/
157867eb5db5874076db01febed5a1a9281628fa9fb4Karsten Keilstatic void
15791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsinithfcpci(struct IsdnCardState *cs)
15801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
15811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->bcs[0].BC_SetStack = setstack_2b;
15821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->bcs[1].BC_SetStack = setstack_2b;
15831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->bcs[0].BC_Close = close_hfcpci;
15841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->bcs[1].BC_Close = close_hfcpci;
15851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->dbusytimer.function = (void *) hfcpci_dbusy_timer;
15861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->dbusytimer.data = (long) cs;
15871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	init_timer(&cs->dbusytimer);
15881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mode_hfcpci(cs->bcs, 0, 0);
15891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	mode_hfcpci(cs->bcs + 1, 0, 1);
15901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
15911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
15941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************/
15951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* handle card messages from control layer */
15961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*******************************************/
15971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
15981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldshfcpci_card_msg(struct IsdnCardState *cs, int mt, void *arg)
15991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
16011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (cs->debug & L1_DEB_ISAC)
16031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		debugl1(cs, "HFCPCI: card_msg %x", mt);
16041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (mt) {
1605475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case CARD_RESET:
1606475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1607475be4d85a274d0961593db41cf85689db1d583cJoe Perches		reset_hfcpci(cs);
1608475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1609475be4d85a274d0961593db41cf85689db1d583cJoe Perches		return (0);
1610475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case CARD_RELEASE:
1611475be4d85a274d0961593db41cf85689db1d583cJoe Perches		release_io_hfcpci(cs);
1612475be4d85a274d0961593db41cf85689db1d583cJoe Perches		return (0);
1613475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case CARD_INIT:
1614475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1615475be4d85a274d0961593db41cf85689db1d583cJoe Perches		inithfcpci(cs);
1616475be4d85a274d0961593db41cf85689db1d583cJoe Perches		reset_hfcpci(cs);
1617475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1618475be4d85a274d0961593db41cf85689db1d583cJoe Perches		msleep(80);				/* Timeout 80ms */
1619475be4d85a274d0961593db41cf85689db1d583cJoe Perches		/* now switch timer interrupt off */
1620475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_lock_irqsave(&cs->lock, flags);
1621475be4d85a274d0961593db41cf85689db1d583cJoe Perches		cs->hw.hfcpci.int_m1 &= ~HFCPCI_INTS_TIMER;
1622475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
1623475be4d85a274d0961593db41cf85689db1d583cJoe Perches		/* reinit mode reg */
1624475be4d85a274d0961593db41cf85689db1d583cJoe Perches		Write_hfc(cs, HFCPCI_MST_MODE, cs->hw.hfcpci.mst_m);
1625475be4d85a274d0961593db41cf85689db1d583cJoe Perches		spin_unlock_irqrestore(&cs->lock, flags);
1626475be4d85a274d0961593db41cf85689db1d583cJoe Perches		return (0);
1627475be4d85a274d0961593db41cf85689db1d583cJoe Perches	case CARD_TEST:
1628475be4d85a274d0961593db41cf85689db1d583cJoe Perches		return (0);
16291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
16301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return (0);
16311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
16321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this variable is used as card index when more than one cards are present */
1635ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartmanstatic struct pci_dev *dev_hfcpci = NULL;
16361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1637ed5a84cdf593e54969518e82762786fbe1284ce4Greg Kroah-Hartmanint
16381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssetup_hfcpci(struct IsdnCard *card)
16391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
16401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u_long flags;
16411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct IsdnCardState *cs = card->cs;
16421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	char tmp[64];
16431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int i;
16441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	struct pci_dev *tmp_hfcpci = NULL;
16451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
16461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	strcpy(tmp, hfcpci_revision);
16471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "HiSax: HFC-PCI driver Rev. %s\n", HiSax_getrev(tmp));
164898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
16491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.int_s1 = 0;
16501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->dc.hfcpci.ph_state = 0;
16511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	cs->hw.hfcpci.fifo = 255;
165298fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	if (cs->typ != ISDN_CTYPE_HFC_PCI)
1653475be4d85a274d0961593db41cf85689db1d583cJoe Perches		return (0);
165498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
165598fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	i = 0;
165698fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	while (id_list[i].vendor_id) {
165741a68a748bbc61f5bcea999e33ba72926dfbe6f7Tilman Schmidt		tmp_hfcpci = hisax_find_pci_device(id_list[i].vendor_id,
1658475be4d85a274d0961593db41cf85689db1d583cJoe Perches						   id_list[i].device_id,
1659475be4d85a274d0961593db41cf85689db1d583cJoe Perches						   dev_hfcpci);
166098fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik		i++;
16611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		if (tmp_hfcpci) {
16628a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil			dma_addr_t	dma_mask = DMA_BIT_MASK(32) & ~0x7fffUL;
166398fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik			if (pci_enable_device(tmp_hfcpci))
166498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik				continue;
16658a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil			if (pci_set_dma_mask(tmp_hfcpci, dma_mask)) {
16668a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil				printk(KERN_WARNING
1667475be4d85a274d0961593db41cf85689db1d583cJoe Perches				       "HiSax hfc_pci: No suitable DMA available.\n");
16688a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil				continue;
16698a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil			}
16708a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil			if (pci_set_consistent_dma_mask(tmp_hfcpci, dma_mask)) {
16718a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil				printk(KERN_WARNING
1672475be4d85a274d0961593db41cf85689db1d583cJoe Perches				       "HiSax hfc_pci: No suitable consistent DMA available.\n");
16738a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil				continue;
16748a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil			}
167598fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik			pci_set_master(tmp_hfcpci);
1676475be4d85a274d0961593db41cf85689db1d583cJoe Perches			if ((card->para[0]) && (card->para[0] != (tmp_hfcpci->resource[0].start & PCI_BASE_ADDRESS_IO_MASK)))
167798fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik				continue;
167898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik			else
167998fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik				break;
16801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		}
168198fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	}
168298fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
168398fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	if (!tmp_hfcpci) {
168498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik		printk(KERN_WARNING "HFC-PCI: No PCI card found\n");
168598fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik		return (0);
168698fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	}
168798fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
168898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	i--;
168998fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	dev_hfcpci = tmp_hfcpci;	/* old device */
169098fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->hw.hfcpci.dev = dev_hfcpci;
169198fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->irq = dev_hfcpci->irq;
169298fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	if (!cs->irq) {
169398fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik		printk(KERN_WARNING "HFC-PCI: No IRQ for PCI card found\n");
169498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik		return (0);
169598fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	}
169698fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->hw.hfcpci.pci_io = (char *)(unsigned long)dev_hfcpci->resource[1].start;
169798fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	printk(KERN_INFO "HiSax: HFC-PCI card manufacturer: %s card name: %s\n", id_list[i].vendor_name, id_list[i].card_name);
169898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
169998fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	if (!cs->hw.hfcpci.pci_io) {
170098fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik		printk(KERN_WARNING "HFC-PCI: No IO-Mem for PCI card found\n");
170198fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik		return (0);
170298fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	}
17038a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil
170498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	/* Allocate memory for FIFOS */
17058a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	cs->hw.hfcpci.fifos = pci_alloc_consistent(cs->hw.hfcpci.dev,
1706475be4d85a274d0961593db41cf85689db1d583cJoe Perches						   0x8000, &cs->hw.hfcpci.dma);
17078a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	if (!cs->hw.hfcpci.fifos) {
17088a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil		printk(KERN_WARNING "HFC-PCI: Error allocating FIFO memory!\n");
17098a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil		return 0;
17108a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	}
17118a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	if (cs->hw.hfcpci.dma & 0x7fff) {
17128a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil		printk(KERN_WARNING
1713475be4d85a274d0961593db41cf85689db1d583cJoe Perches		       "HFC-PCI: Error DMA memory not on 32K boundary (%lx)\n",
1714475be4d85a274d0961593db41cf85689db1d583cJoe Perches		       (u_long)cs->hw.hfcpci.dma);
17158a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil		pci_free_consistent(cs->hw.hfcpci.dev, 0x8000,
1716475be4d85a274d0961593db41cf85689db1d583cJoe Perches				    cs->hw.hfcpci.fifos, cs->hw.hfcpci.dma);
171798fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik		return 0;
171898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	}
17198a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	pci_write_config_dword(cs->hw.hfcpci.dev, 0x80, (u32)cs->hw.hfcpci.dma);
172098fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->hw.hfcpci.pci_io = ioremap((ulong) cs->hw.hfcpci.pci_io, 256);
172198fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	printk(KERN_INFO
17228a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	       "HFC-PCI: defined at mem %p fifo %p(%lx) IRQ %d HZ %d\n",
172398fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	       cs->hw.hfcpci.pci_io,
172498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	       cs->hw.hfcpci.fifos,
17258a745b9d91962991ce87a649a4dc3af3206c2c8bKarsten Keil	       (u_long)cs->hw.hfcpci.dma,
172698fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	       cs->irq, HZ);
172798fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
172898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	spin_lock_irqsave(&cs->lock, flags);
172998fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
173098fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	pci_write_config_word(cs->hw.hfcpci.dev, PCI_COMMAND, PCI_ENA_MEMIO);	/* enable memory mapped ports, disable busmaster */
173198fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->hw.hfcpci.int_m2 = 0;	/* disable alle interrupts */
173298fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->hw.hfcpci.int_m1 = 0;
173398fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	Write_hfc(cs, HFCPCI_INT_M1, cs->hw.hfcpci.int_m1);
173498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	Write_hfc(cs, HFCPCI_INT_M2, cs->hw.hfcpci.int_m2);
173598fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	/* At this point the needed PCI config is done */
173698fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	/* fifos are still not enabled */
173798fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
173898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	INIT_WORK(&cs->tqueue,  hfcpci_bh);
173998fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->setstack_d = setstack_hfcpci;
174098fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->BC_Send_Data = &hfcpci_send_data;
174198fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->readisac = NULL;
174298fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->writeisac = NULL;
174398fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->readisacfifo = NULL;
174498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->writeisacfifo = NULL;
174598fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->BC_Read_Reg = NULL;
174698fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->BC_Write_Reg = NULL;
174798fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->irq_func = &hfcpci_interrupt;
174898fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->irq_flags |= IRQF_SHARED;
174998fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->hw.hfcpci.timer.function = (void *) hfcpci_Timer;
175098fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->hw.hfcpci.timer.data = (long) cs;
175198fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	init_timer(&cs->hw.hfcpci.timer);
175298fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->cardmsg = &hfcpci_card_msg;
175398fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	cs->auxcmd = &hfcpci_auxcmd;
175498fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
175598fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	spin_unlock_irqrestore(&cs->lock, flags);
175698fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik
175798fc4839aa00a02da83625e9fedad7a348c0af91Jeff Garzik	return (1);
17581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1759