You should never need this option, say N.
 
-config PC300
-       tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
-       depends on HDLC && PCI && BROKEN
-       ---help---
-         This driver is broken because of struct tty_driver change.
-
-         Driver for the Cyclades-PC300 synchronous communication boards.
-
-         These boards provide synchronous serial interfaces to your
-         Linux box (interfaces currently available are RS-232/V.35, X.21 and
-         T1/E1). If you wish to support Multilink PPP, please select the
-         option later and read the file README.mlppp provided by PC300
-         package.
-
-         To compile this as a module, choose M here: the module
-         will be called pc300.
-
-         If unsure, say N.
-
-config PC300_MLPPP
-       bool "Cyclades-PC300 MLPPP support"
-       depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
-       help
-         Multilink PPP over the PC300 synchronous communication boards.
-
-comment "Cyclades-PC300 MLPPP support is disabled."
-       depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
-
-comment "Refer to the file README.mlppp, provided by PC300 package."
-       depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
-
 config PC300TOO
        tristate "Cyclades PC300 RSV/X21 alternative support"
        depends on HDLC && PCI
 
 obj-$(CONFIG_HDLC_PPP)         += hdlc_ppp.o
 obj-$(CONFIG_HDLC_X25)         += hdlc_x25.o
 
-pc300-y                                := pc300_drv.o
-pc300-$(CONFIG_PC300_MLPPP)    += pc300_tty.o
-pc300-objs                     := $(pc300-y)
-
 obj-$(CONFIG_HOSTESS_SV11)     += z85230.o     hostess_sv11.o
 obj-$(CONFIG_SEALEVEL_4021)    += z85230.o     sealevel.o
 obj-$(CONFIG_COSA)             += cosa.o
 obj-$(CONFIG_CYCLADES_SYNC)    += cycx_drv.o cyclomx.o
 obj-$(CONFIG_LAPBETHER)                += lapbether.o
 obj-$(CONFIG_SBNI)             += sbni.o
-obj-$(CONFIG_PC300)            += pc300.o
 obj-$(CONFIG_N2)               += n2.o
 obj-$(CONFIG_C101)             += c101.o
 obj-$(CONFIG_WANXL)            += wanxl.o
 
+++ /dev/null
-/*
- * falc.h      Description of the Siemens FALC T1/E1 framer.
- *
- * Author:     Ivan Passos <ivan@cyclades.com>
- *
- * Copyright:  (c) 2000-2001 Cyclades Corp.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- * $Log: falc-lh.h,v $
- * Revision 3.1  2001/06/15 12:41:10  regina
- * upping major version number
- *
- * Revision 1.1.1.1  2001/06/13 20:24:47  daniela
- * PC300 initial CVS version (3.4.0-pre1)
- *
- * Revision 1.1 2000/05/15 ivan
- * Included DJA bits for the LIM2 register.
- *
- * Revision 1.0 2000/02/22 ivan
- * Initial version.
- *
- */
-
-#ifndef _FALC_LH_H
-#define _FALC_LH_H
-
-#define NUM_OF_T1_CHANNELS     24
-#define NUM_OF_E1_CHANNELS     32
-
-/*>>>>>>>>>>>>>>>>>  FALC Register Bits (Transmit Mode)  <<<<<<<<<<<<<<<<<<< */
-
-/* CMDR (Command Register)
-   ---------------- E1 & T1 ------------------------------ */
-#define CMDR_RMC       0x80
-#define CMDR_RRES      0x40
-#define CMDR_XREP      0x20
-#define CMDR_XRES      0x10
-#define CMDR_XHF       0x08
-#define CMDR_XTF       0x04
-#define CMDR_XME       0x02
-#define CMDR_SRES      0x01
-
-/* MODE (Mode Register)
-   ----------------- E1 & T1 ----------------------------- */
-#define MODE_MDS2      0x80
-#define MODE_MDS1      0x40
-#define MODE_MDS0      0x20
-#define MODE_BRAC      0x10
-#define MODE_HRAC      0x08
-
-/* IPC (Interrupt Port Configuration)
-   ----------------- E1 & T1 ----------------------------- */
-#define IPC_VIS                0x80
-#define IPC_SCI                0x04
-#define IPC_IC1                0x02
-#define IPC_IC0                0x01
-
-/* CCR1 (Common Configuration Register 1)
-   ----------------- E1 & T1 ----------------------------- */
-#define CCR1_SFLG       0x80
-#define CCR1_XTS16RA    0x40
-#define CCR1_BRM        0x40
-#define CCR1_CASSYM     0x20
-#define CCR1_EDLX       0x20
-#define CCR1_EITS       0x10
-#define CCR1_ITF        0x08
-#define CCR1_RFT1       0x02
-#define CCR1_RFT0       0x01
-
-/* CCR3 (Common Configuration Register 3)
-   ---------------- E1 & T1 ------------------------------ */
-
-#define CCR3_PRE1       0x80
-#define CCR3_PRE0       0x40
-#define CCR3_EPT        0x20
-#define CCR3_RADD       0x10
-#define CCR3_RCRC       0x04
-#define CCR3_XCRC       0x02
-
-
-/* RTR1-4 (Receive Timeslot Register 1-4)
-   ---------------- E1 & T1 ------------------------------ */
-
-#define RTR1_TS0        0x80
-#define RTR1_TS1        0x40
-#define RTR1_TS2        0x20
-#define RTR1_TS3        0x10
-#define RTR1_TS4        0x08
-#define RTR1_TS5        0x04
-#define RTR1_TS6        0x02
-#define RTR1_TS7        0x01
-
-#define RTR2_TS8        0x80
-#define RTR2_TS9        0x40
-#define RTR2_TS10       0x20
-#define RTR2_TS11       0x10
-#define RTR2_TS12       0x08
-#define RTR2_TS13       0x04
-#define RTR2_TS14       0x02
-#define RTR2_TS15       0x01
-
-#define RTR3_TS16       0x80
-#define RTR3_TS17       0x40
-#define RTR3_TS18       0x20
-#define RTR3_TS19       0x10
-#define RTR3_TS20       0x08
-#define RTR3_TS21       0x04
-#define RTR3_TS22       0x02
-#define RTR3_TS23       0x01
-
-#define RTR4_TS24       0x80
-#define RTR4_TS25       0x40
-#define RTR4_TS26       0x20
-#define RTR4_TS27       0x10
-#define RTR4_TS28       0x08
-#define RTR4_TS29       0x04
-#define RTR4_TS30       0x02
-#define RTR4_TS31       0x01
-
-
-/* TTR1-4 (Transmit Timeslot Register 1-4)
-   ---------------- E1 & T1 ------------------------------ */
-
-#define TTR1_TS0        0x80
-#define TTR1_TS1        0x40
-#define TTR1_TS2        0x20
-#define TTR1_TS3        0x10
-#define TTR1_TS4        0x08
-#define TTR1_TS5        0x04
-#define TTR1_TS6        0x02
-#define TTR1_TS7        0x01
-
-#define TTR2_TS8        0x80
-#define TTR2_TS9        0x40
-#define TTR2_TS10       0x20
-#define TTR2_TS11       0x10
-#define TTR2_TS12       0x08
-#define TTR2_TS13       0x04
-#define TTR2_TS14       0x02
-#define TTR2_TS15       0x01
-
-#define TTR3_TS16       0x80
-#define TTR3_TS17       0x40
-#define TTR3_TS18       0x20
-#define TTR3_TS19       0x10
-#define TTR3_TS20       0x08
-#define TTR3_TS21       0x04
-#define TTR3_TS22       0x02
-#define TTR3_TS23       0x01
-
-#define TTR4_TS24       0x80
-#define TTR4_TS25       0x40
-#define TTR4_TS26       0x20
-#define TTR4_TS27       0x10
-#define TTR4_TS28       0x08
-#define TTR4_TS29       0x04
-#define TTR4_TS30       0x02
-#define TTR4_TS31       0x01
-
-
-
-/* IMR0-4 (Interrupt Mask Register 0-4)
-
-   ----------------- E1 & T1 ----------------------------- */
-
-#define IMR0_RME        0x80
-#define IMR0_RFS        0x40
-#define IMR0_T8MS       0x20
-#define IMR0_ISF        0x20
-#define IMR0_RMB        0x10
-#define IMR0_CASC       0x08
-#define IMR0_RSC        0x08
-#define IMR0_CRC6       0x04
-#define IMR0_CRC4       0x04
-#define IMR0_PDEN      0x02
-#define IMR0_RPF        0x01
-
-#define IMR1_CASE       0x80
-#define IMR1_RDO        0x40
-#define IMR1_ALLS       0x20
-#define IMR1_XDU        0x10
-#define IMR1_XMB        0x08
-#define IMR1_XLSC       0x02
-#define IMR1_XPR        0x01
-#define IMR1_LLBSC     0x80
-
-#define IMR2_FAR        0x80
-#define IMR2_LFA        0x40
-#define IMR2_MFAR       0x20
-#define IMR2_T400MS     0x10
-#define IMR2_LMFA       0x10
-#define IMR2_AIS        0x08
-#define IMR2_LOS        0x04
-#define IMR2_RAR        0x02
-#define IMR2_RA         0x01
-
-#define IMR3_ES         0x80
-#define IMR3_SEC        0x40
-#define IMR3_LMFA16     0x20
-#define IMR3_AIS16      0x10
-#define IMR3_RA16       0x08
-#define IMR3_API        0x04
-#define IMR3_XSLP       0x20
-#define IMR3_XSLN       0x10
-#define IMR3_LLBSC      0x08
-#define IMR3_XRS        0x04
-#define IMR3_SLN        0x02
-#define IMR3_SLP        0x01
-
-#define IMR4_LFA        0x80
-#define IMR4_FER        0x40
-#define IMR4_CER        0x20
-#define IMR4_AIS        0x10
-#define IMR4_LOS        0x08
-#define IMR4_CVE        0x04
-#define IMR4_SLIP       0x02
-#define IMR4_EBE        0x01
-
-/* FMR0-5 for E1 and T1  (Framer Mode Register ) */
-
-#define FMR0_XC1        0x80
-#define FMR0_XC0        0x40
-#define FMR0_RC1        0x20
-#define FMR0_RC0        0x10
-#define FMR0_EXTD       0x08
-#define FMR0_ALM        0x04
-#define E1_FMR0_FRS     0x02
-#define T1_FMR0_FRS     0x08
-#define FMR0_SRAF       0x04
-#define FMR0_EXLS       0x02
-#define FMR0_SIM        0x01
-
-#define FMR1_MFCS       0x80
-#define FMR1_AFR        0x40
-#define FMR1_ENSA       0x20
-#define FMR1_CTM        0x80
-#define FMR1_SIGM       0x40
-#define FMR1_EDL        0x20
-#define FMR1_PMOD       0x10
-#define FMR1_XFS        0x08
-#define FMR1_CRC        0x08
-#define FMR1_ECM        0x04
-#define FMR1_IMOD       0x02
-#define FMR1_XAIS       0x01
-
-#define FMR2_RFS1       0x80
-#define FMR2_RFS0       0x40
-#define FMR2_MCSP      0x40
-#define FMR2_RTM        0x20
-#define FMR2_SSP        0x20
-#define FMR2_DAIS       0x10
-#define FMR2_SAIS       0x08
-#define FMR2_PLB        0x04
-#define FMR2_AXRA       0x02
-#define FMR2_ALMF       0x01
-#define FMR2_EXZE       0x01
-
-#define LOOP_RTM       0x40
-#define LOOP_SFM       0x40
-#define LOOP_ECLB      0x20
-#define LOOP_CLA       0x1f
-
-/*--------------------- E1 ----------------------------*/
-#define FMR3_XLD       0x20
-#define FMR3_XLU       0x10
-
-/*--------------------- T1 ----------------------------*/
-#define FMR4_AIS3       0x80
-#define FMR4_TM         0x40
-#define FMR4_XRA        0x20
-#define FMR4_SSC1       0x10
-#define FMR4_SSC0       0x08
-#define FMR4_AUTO       0x04
-#define FMR4_FM1        0x02
-#define FMR4_FM0        0x01
-
-#define FMR5_SRS        0x80
-#define FMR5_EIBR       0x40
-#define FMR5_XLD        0x20
-#define FMR5_XLU        0x10
-
-
-/* LOOP (Channel Loop Back)
-
-   ------------------ E1 & T1 ---------------------------- */
-
-#define LOOP_SFM        0x40
-#define LOOP_ECLB       0x20
-#define LOOP_CLA4       0x10
-#define LOOP_CLA3       0x08
-#define LOOP_CLA2       0x04
-#define LOOP_CLA1       0x02
-#define LOOP_CLA0       0x01
-
-
-
-/* XSW (Transmit Service Word Pulseframe)
-
-   ------------------- E1 --------------------------- */
-
-#define XSW_XSIS        0x80
-#define XSW_XTM         0x40
-#define XSW_XRA         0x20
-#define XSW_XY0         0x10
-#define XSW_XY1         0x08
-#define XSW_XY2         0x04
-#define XSW_XY3         0x02
-#define XSW_XY4         0x01
-
-
-/* XSP (Transmit Spare Bits)
-
-   ------------------- E1 --------------------------- */
-
-#define XSP_XAP         0x80
-#define XSP_CASEN       0x40
-#define XSP_TT0         0x20
-#define XSP_EBP         0x10
-#define XSP_AXS         0x08
-#define XSP_XSIF        0x04
-#define XSP_XS13        0x02
-#define XSP_XS15        0x01
-
-
-/* XC0/1 (Transmit Control 0/1)
-   ------------------ E1 & T1 ---------------------------- */
-
-#define XC0_SA8E        0x80
-#define XC0_SA7E        0x40
-#define XC0_SA6E        0x20
-#define XC0_SA5E        0x10
-#define XC0_SA4E        0x08
-#define XC0_BRM         0x80
-#define XC0_MFBS        0x40
-#define XC0_SFRZ        0x10
-#define XC0_XCO2        0x04
-#define XC0_XCO1        0x02
-#define XC0_XCO0        0x01
-
-#define XC1_XTO5        0x20
-#define XC1_XTO4        0x10
-#define XC1_XTO3        0x08
-#define XC1_XTO2        0x04
-#define XC1_XTO1        0x02
-#define XC1_XTO0        0x01
-
-
-/* RC0/1 (Receive Control 0/1)
-   ------------------ E1 & T1 ---------------------------- */
-
-#define RC0_SICS        0x40
-#define RC0_CRCI        0x20
-#define RC0_XCRCI       0x10
-#define RC0_RDIS        0x08
-#define RC0_RCO2        0x04
-#define RC0_RCO1        0x02
-#define RC0_RCO0        0x01
-
-#define RC1_SWD         0x80
-#define RC1_ASY4        0x40
-#define RC1_RRAM        0x40
-#define RC1_RTO5        0x20
-#define RC1_RTO4        0x10
-#define RC1_RTO3        0x08
-#define RC1_RTO2        0x04
-#define RC1_RTO1        0x02
-#define RC1_RTO0        0x01
-
-
-
-/* XPM0-2 (Transmit Pulse Mask 0-2)
-   --------------------- E1 & T1 ------------------------- */
-
-#define XPM0_XP12       0x80
-#define XPM0_XP11       0x40
-#define XPM0_XP10       0x20
-#define XPM0_XP04       0x10
-#define XPM0_XP03       0x08
-#define XPM0_XP02       0x04
-#define XPM0_XP01       0x02
-#define XPM0_XP00       0x01
-
-#define XPM1_XP30       0x80
-#define XPM1_XP24       0x40
-#define XPM1_XP23       0x20
-#define XPM1_XP22       0x10
-#define XPM1_XP21       0x08
-#define XPM1_XP20       0x04
-#define XPM1_XP14       0x02
-#define XPM1_XP13       0x01
-
-#define XPM2_XLHP       0x80
-#define XPM2_XLT        0x40
-#define XPM2_DAXLT      0x20
-#define XPM2_XP34       0x08
-#define XPM2_XP33       0x04
-#define XPM2_XP32       0x02
-#define XPM2_XP31       0x01
-
-
-/* TSWM (Transparent Service Word Mask)
-   ------------------ E1 ---------------------------- */
-
-#define TSWM_TSIS       0x80
-#define TSWM_TSIF       0x40
-#define TSWM_TRA        0x20
-#define TSWM_TSA4       0x10
-#define TSWM_TSA5       0x08
-#define TSWM_TSA6       0x04
-#define TSWM_TSA7       0x02
-#define TSWM_TSA8       0x01
-
-/* IDLE <Idle Channel Code Register>
-
-   ------------------ E1 & T1 ----------------------- */
-
-#define IDLE_IDL7       0x80
-#define IDLE_IDL6       0x40
-#define IDLE_IDL5       0x20
-#define IDLE_IDL4       0x10
-#define IDLE_IDL3       0x08
-#define IDLE_IDL2       0x04
-#define IDLE_IDL1       0x02
-#define IDLE_IDL0       0x01
-
-
-/* XSA4-8 <Transmit SA4-8 Register(Read/Write) >
-   -------------------E1 ----------------------------- */
-
-#define XSA4_XS47       0x80
-#define XSA4_XS46       0x40
-#define XSA4_XS45       0x20
-#define XSA4_XS44       0x10
-#define XSA4_XS43       0x08
-#define XSA4_XS42       0x04
-#define XSA4_XS41       0x02
-#define XSA4_XS40       0x01
-
-#define XSA5_XS57       0x80
-#define XSA5_XS56       0x40
-#define XSA5_XS55       0x20
-#define XSA5_XS54       0x10
-#define XSA5_XS53       0x08
-#define XSA5_XS52       0x04
-#define XSA5_XS51       0x02
-#define XSA5_XS50       0x01
-
-#define XSA6_XS67       0x80
-#define XSA6_XS66       0x40
-#define XSA6_XS65       0x20
-#define XSA6_XS64       0x10
-#define XSA6_XS63       0x08
-#define XSA6_XS62       0x04
-#define XSA6_XS61       0x02
-#define XSA6_XS60       0x01
-
-#define XSA7_XS77       0x80
-#define XSA7_XS76       0x40
-#define XSA7_XS75       0x20
-#define XSA7_XS74       0x10
-#define XSA7_XS73       0x08
-#define XSA7_XS72       0x04
-#define XSA7_XS71       0x02
-#define XSA7_XS70       0x01
-
-#define XSA8_XS87       0x80
-#define XSA8_XS86       0x40
-#define XSA8_XS85       0x20
-#define XSA8_XS84       0x10
-#define XSA8_XS83       0x08
-#define XSA8_XS82       0x04
-#define XSA8_XS81       0x02
-#define XSA8_XS80       0x01
-
-
-/* XDL1-3 (Transmit DL-Bit Register1-3 (read/write))
-   ----------------------- T1 --------------------- */
-
-#define XDL1_XDL17      0x80
-#define XDL1_XDL16      0x40
-#define XDL1_XDL15      0x20
-#define XDL1_XDL14      0x10
-#define XDL1_XDL13      0x08
-#define XDL1_XDL12      0x04
-#define XDL1_XDL11      0x02
-#define XDL1_XDL10      0x01
-
-#define XDL2_XDL27      0x80
-#define XDL2_XDL26      0x40
-#define XDL2_XDL25      0x20
-#define XDL2_XDL24      0x10
-#define XDL2_XDL23      0x08
-#define XDL2_XDL22      0x04
-#define XDL2_XDL21      0x02
-#define XDL2_XDL20      0x01
-
-#define XDL3_XDL37      0x80
-#define XDL3_XDL36      0x40
-#define XDL3_XDL35      0x20
-#define XDL3_XDL34      0x10
-#define XDL3_XDL33      0x08
-#define XDL3_XDL32      0x04
-#define XDL3_XDL31      0x02
-#define XDL3_XDL30      0x01
-
-
-/* ICB1-4 (Idle Channel Register 1-4)
-   ------------------ E1 ---------------------------- */
-
-#define E1_ICB1_IC0    0x80
-#define E1_ICB1_IC1    0x40
-#define E1_ICB1_IC2    0x20
-#define E1_ICB1_IC3    0x10
-#define E1_ICB1_IC4    0x08
-#define E1_ICB1_IC5    0x04
-#define E1_ICB1_IC6    0x02
-#define E1_ICB1_IC7    0x01
-
-#define E1_ICB2_IC8    0x80
-#define E1_ICB2_IC9    0x40
-#define E1_ICB2_IC10   0x20
-#define E1_ICB2_IC11   0x10
-#define E1_ICB2_IC12   0x08
-#define E1_ICB2_IC13   0x04
-#define E1_ICB2_IC14   0x02
-#define E1_ICB2_IC15   0x01
-
-#define E1_ICB3_IC16   0x80
-#define E1_ICB3_IC17   0x40
-#define E1_ICB3_IC18   0x20
-#define E1_ICB3_IC19   0x10
-#define E1_ICB3_IC20   0x08
-#define E1_ICB3_IC21   0x04
-#define E1_ICB3_IC22   0x02
-#define E1_ICB3_IC23   0x01
-
-#define E1_ICB4_IC24   0x80
-#define E1_ICB4_IC25   0x40
-#define E1_ICB4_IC26   0x20
-#define E1_ICB4_IC27   0x10
-#define E1_ICB4_IC28   0x08
-#define E1_ICB4_IC29   0x04
-#define E1_ICB4_IC30   0x02
-#define E1_ICB4_IC31   0x01
-
-/* ICB1-4 (Idle Channel Register 1-4)
-   ------------------ T1 ---------------------------- */
-
-#define T1_ICB1_IC1    0x80
-#define T1_ICB1_IC2    0x40
-#define T1_ICB1_IC3    0x20
-#define T1_ICB1_IC4    0x10
-#define T1_ICB1_IC5    0x08
-#define T1_ICB1_IC6    0x04
-#define T1_ICB1_IC7    0x02
-#define T1_ICB1_IC8    0x01
-
-#define T1_ICB2_IC9    0x80
-#define T1_ICB2_IC10   0x40
-#define T1_ICB2_IC11   0x20
-#define T1_ICB2_IC12   0x10
-#define T1_ICB2_IC13   0x08
-#define T1_ICB2_IC14   0x04
-#define T1_ICB2_IC15   0x02
-#define T1_ICB2_IC16   0x01
-
-#define T1_ICB3_IC17   0x80
-#define T1_ICB3_IC18   0x40
-#define T1_ICB3_IC19   0x20
-#define T1_ICB3_IC20   0x10
-#define T1_ICB3_IC21   0x08
-#define T1_ICB3_IC22   0x04
-#define T1_ICB3_IC23   0x02
-#define T1_ICB3_IC24   0x01
-
-/* FMR3 (Framer Mode Register 3)
-   --------------------E1------------------------ */
-
-#define FMR3_CMI        0x08
-#define FMR3_SYNSA      0x04
-#define FMR3_CFRZ       0x02
-#define FMR3_EXTIW      0x01
-
-
-
-/* CCB1-3 (Clear Channel Register)
-   ------------------- T1 ----------------------- */
-
-#define CCB1_CH1        0x80
-#define CCB1_CH2        0x40
-#define CCB1_CH3        0x20
-#define CCB1_CH4        0x10
-#define CCB1_CH5        0x08
-#define CCB1_CH6        0x04
-#define CCB1_CH7        0x02
-#define CCB1_CH8        0x01
-
-#define CCB2_CH9        0x80
-#define CCB2_CH10       0x40
-#define CCB2_CH11       0x20
-#define CCB2_CH12       0x10
-#define CCB2_CH13       0x08
-#define CCB2_CH14       0x04
-#define CCB2_CH15       0x02
-#define CCB2_CH16       0x01
-
-#define CCB3_CH17       0x80
-#define CCB3_CH18       0x40
-#define CCB3_CH19       0x20
-#define CCB3_CH20       0x10
-#define CCB3_CH21       0x08
-#define CCB3_CH22       0x04
-#define CCB3_CH23       0x02
-#define CCB3_CH24       0x01
-
-
-/* LIM0/1 (Line Interface Mode 0/1)
-   ------------------- E1 & T1 --------------------------- */
-
-#define LIM0_XFB        0x80
-#define LIM0_XDOS       0x40
-#define LIM0_SCL1       0x20
-#define LIM0_SCL0       0x10
-#define LIM0_EQON       0x08
-#define LIM0_ELOS       0x04
-#define LIM0_LL         0x02
-#define LIM0_MAS        0x01
-
-#define LIM1_EFSC       0x80
-#define LIM1_RIL2       0x40
-#define LIM1_RIL1       0x20
-#define LIM1_RIL0       0x10
-#define LIM1_DCOC       0x08
-#define LIM1_JATT       0x04
-#define LIM1_RL         0x02
-#define LIM1_DRS        0x01
-
-
-/* PCDR (Pulse Count Detection Register(Read/Write))
-   ------------------ E1 & T1 ------------------------- */
-
-#define PCDR_PCD7      0x80
-#define PCDR_PCD6      0x40
-#define PCDR_PCD5      0x20
-#define PCDR_PCD4      0x10
-#define PCDR_PCD3      0x08
-#define PCDR_PCD2      0x04
-#define PCDR_PCD1      0x02
-#define PCDR_PCD0      0x01
-
-#define PCRR_PCR7      0x80
-#define PCRR_PCR6      0x40
-#define PCRR_PCR5      0x20
-#define PCRR_PCR4      0x10
-#define PCRR_PCR3      0x08
-#define PCRR_PCR2      0x04
-#define PCRR_PCR1      0x02
-#define PCRR_PCR0      0x01
-
-
-/* LIM2 (Line Interface Mode 2)
-
-   ------------------ E1 & T1 ---------------------------- */
-
-#define LIM2_DJA2      0x20
-#define LIM2_DJA1      0x10
-#define LIM2_LOS2      0x02
-#define LIM2_LOS1      0x01
-
-/* LCR1 (Loop Code Register 1) */
-
-#define LCR1_EPRM      0x80
-#define        LCR1_XPRBS      0x40
-
-/* SIC1 (System Interface Control 1) */
-#define SIC1_SRSC      0x80
-#define SIC1_RBS1      0x20
-#define SIC1_RBS0      0x10
-#define SIC1_SXSC      0x08
-#define SIC1_XBS1      0x02
-#define SIC1_XBS0      0x01
-
-/* DEC (Disable Error Counter)
-   ------------------ E1 & T1 ---------------------------- */
-
-#define DEC_DCEC3       0x20
-#define DEC_DBEC        0x10
-#define DEC_DCEC1       0x08
-#define DEC_DCEC        0x08
-#define DEC_DEBC        0x04
-#define DEC_DCVC        0x02
-#define DEC_DFEC        0x01
-
-
-/* FALC Register Bits (Receive Mode)
-   ---------------------------------------------------------------------------- */
-
-
-/* FRS0/1 (Framer Receive Status Register 0/1)
-   ----------------- E1 & T1 ---------------------------------- */
-
-#define FRS0_LOS        0x80
-#define FRS0_AIS        0x40
-#define FRS0_LFA        0x20
-#define FRS0_RRA        0x10
-#define FRS0_API        0x08
-#define FRS0_NMF        0x04
-#define FRS0_LMFA       0x02
-#define FRS0_FSRF       0x01
-
-#define FRS1_TS16RA     0x40
-#define FRS1_TS16LOS    0x20
-#define FRS1_TS16AIS    0x10
-#define FRS1_TS16LFA    0x08
-#define FRS1_EXZD       0x80
-#define FRS1_LLBDD      0x10
-#define FRS1_LLBAD      0x08
-#define FRS1_XLS        0x02
-#define FRS1_XLO        0x01
-#define FRS1_PDEN      0x40
-
-/* FRS2/3 (Framer Receive Status Register 2/3)
-   ----------------- T1 ---------------------------------- */
-
-#define FRS2_ESC2       0x80
-#define FRS2_ESC1       0x40
-#define FRS2_ESC0       0x20
-
-#define FRS3_FEH5       0x20
-#define FRS3_FEH4       0x10
-#define FRS3_FEH3       0x08
-#define FRS3_FEH2       0x04
-#define FRS3_FEH1       0x02
-#define FRS3_FEH0       0x01
-
-
-/* RSW (Receive Service Word Pulseframe)
-   ----------------- E1 ------------------------------ */
-
-#define RSW_RSI         0x80
-#define RSW_RRA         0x20
-#define RSW_RYO         0x10
-#define RSW_RY1         0x08
-#define RSW_RY2         0x04
-#define RSW_RY3         0x02
-#define RSW_RY4         0x01
-
-
-/* RSP (Receive Spare Bits / Additional Status)
-   ---------------- E1 ------------------------------- */
-
-#define RSP_SI1         0x80
-#define RSP_SI2         0x40
-#define RSP_LLBDD      0x10
-#define RSP_LLBAD      0x08
-#define RSP_RSIF        0x04
-#define RSP_RS13        0x02
-#define RSP_RS15        0x01
-
-
-/* FECL (Framing Error Counter)
-   ---------------- E1 & T1 -------------------------- */
-
-#define FECL_FE7        0x80
-#define FECL_FE6        0x40
-#define FECL_FE5        0x20
-#define FECL_FE4        0x10
-#define FECL_FE3        0x08
-#define FECL_FE2        0x04
-#define FECL_FE1        0x02
-#define FECL_FE0        0x01
-
-#define FECH_FE15       0x80
-#define FECH_FE14       0x40
-#define FECH_FE13       0x20
-#define FECH_FE12       0x10
-#define FECH_FE11       0x08
-#define FECH_FE10       0x04
-#define FECH_FE9        0x02
-#define FECH_FE8        0x01
-
-
-/* CVCl (Code Violation Counter)
-   ----------------- E1 ------------------------- */
-
-#define CVCL_CV7        0x80
-#define CVCL_CV6        0x40
-#define CVCL_CV5        0x20
-#define CVCL_CV4        0x10
-#define CVCL_CV3        0x08
-#define CVCL_CV2        0x04
-#define CVCL_CV1        0x02
-#define CVCL_CV0        0x01
-
-#define CVCH_CV15       0x80
-#define CVCH_CV14       0x40
-#define CVCH_CV13       0x20
-#define CVCH_CV12       0x10
-#define CVCH_CV11       0x08
-#define CVCH_CV10       0x04
-#define CVCH_CV9        0x02
-#define CVCH_CV8        0x01
-
-
-/* CEC1-3L (CRC Error Counter)
-   ------------------ E1 ----------------------------- */
-
-#define CEC1L_CR7       0x80
-#define CEC1L_CR6       0x40
-#define CEC1L_CR5       0x20
-#define CEC1L_CR4       0x10
-#define CEC1L_CR3       0x08
-#define CEC1L_CR2       0x04
-#define CEC1L_CR1       0x02
-#define CEC1L_CR0       0x01
-
-#define CEC1H_CR15      0x80
-#define CEC1H_CR14      0x40
-#define CEC1H_CR13      0x20
-#define CEC1H_CR12      0x10
-#define CEC1H_CR11      0x08
-#define CEC1H_CR10      0x04
-#define CEC1H_CR9       0x02
-#define CEC1H_CR8       0x01
-
-#define CEC2L_CR7       0x80
-#define CEC2L_CR6       0x40
-#define CEC2L_CR5       0x20
-#define CEC2L_CR4       0x10
-#define CEC2L_CR3       0x08
-#define CEC2L_CR2       0x04
-#define CEC2L_CR1       0x02
-#define CEC2L_CR0       0x01
-
-#define CEC2H_CR15      0x80
-#define CEC2H_CR14      0x40
-#define CEC2H_CR13      0x20
-#define CEC2H_CR12      0x10
-#define CEC2H_CR11      0x08
-#define CEC2H_CR10      0x04
-#define CEC2H_CR9       0x02
-#define CEC2H_CR8       0x01
-
-#define CEC3L_CR7       0x80
-#define CEC3L_CR6       0x40
-#define CEC3L_CR5       0x20
-#define CEC3L_CR4       0x10
-#define CEC3L_CR3       0x08
-#define CEC3L_CR2       0x04
-#define CEC3L_CR1       0x02
-#define CEC3L_CR0       0x01
-
-#define CEC3H_CR15      0x80
-#define CEC3H_CR14      0x40
-#define CEC3H_CR13      0x20
-#define CEC3H_CR12      0x10
-#define CEC3H_CR11      0x08
-#define CEC3H_CR10      0x04
-#define CEC3H_CR9       0x02
-#define CEC3H_CR8       0x01
-
-
-/* CECL (CRC Error Counter)
-
-   ------------------ T1 ----------------------------- */
-
-#define CECL_CR7        0x80
-#define CECL_CR6        0x40
-#define CECL_CR5        0x20
-#define CECL_CR4        0x10
-#define CECL_CR3        0x08
-#define CECL_CR2        0x04
-#define CECL_CR1        0x02
-#define CECL_CR0        0x01
-
-#define CECH_CR15       0x80
-#define CECH_CR14       0x40
-#define CECH_CR13       0x20
-#define CECH_CR12       0x10
-#define CECH_CR11       0x08
-#define CECH_CR10       0x04
-#define CECH_CR9        0x02
-#define CECH_CR8        0x01
-
-/* EBCL (E Bit Error Counter)
-   ------------------- E1 & T1 ------------------------- */
-
-#define EBCL_EB7        0x80
-#define EBCL_EB6        0x40
-#define EBCL_EB5        0x20
-#define EBCL_EB4        0x10
-#define EBCL_EB3        0x08
-#define EBCL_EB2        0x04
-#define EBCL_EB1        0x02
-#define EBCL_EB0        0x01
-
-#define EBCH_EB15       0x80
-#define EBCH_EB14       0x40
-#define EBCH_EB13       0x20
-#define EBCH_EB12       0x10
-#define EBCH_EB11       0x08
-#define EBCH_EB10       0x04
-#define EBCH_EB9        0x02
-#define EBCH_EB8        0x01
-
-
-/* RSA4-8 (Receive Sa4-8-Bit Register)
-   -------------------- E1 --------------------------- */
-
-#define RSA4_RS47       0x80
-#define RSA4_RS46       0x40
-#define RSA4_RS45       0x20
-#define RSA4_RS44       0x10
-#define RSA4_RS43       0x08
-#define RSA4_RS42       0x04
-#define RSA4_RS41       0x02
-#define RSA4_RS40       0x01
-
-#define RSA5_RS57       0x80
-#define RSA5_RS56       0x40
-#define RSA5_RS55       0x20
-#define RSA5_RS54       0x10
-#define RSA5_RS53       0x08
-#define RSA5_RS52       0x04
-#define RSA5_RS51       0x02
-#define RSA5_RS50       0x01
-
-#define RSA6_RS67       0x80
-#define RSA6_RS66       0x40
-#define RSA6_RS65       0x20
-#define RSA6_RS64       0x10
-#define RSA6_RS63       0x08
-#define RSA6_RS62       0x04
-#define RSA6_RS61       0x02
-#define RSA6_RS60       0x01
-
-#define RSA7_RS77       0x80
-#define RSA7_RS76       0x40
-#define RSA7_RS75       0x20
-#define RSA7_RS74       0x10
-#define RSA7_RS73       0x08
-#define RSA7_RS72       0x04
-#define RSA7_RS71       0x02
-#define RSA7_RS70       0x01
-
-#define RSA8_RS87       0x80
-#define RSA8_RS86       0x40
-#define RSA8_RS85       0x20
-#define RSA8_RS84       0x10
-#define RSA8_RS83       0x08
-#define RSA8_RS82       0x04
-#define RSA8_RS81       0x02
-#define RSA8_RS80       0x01
-
-/* RSA6S (Receive Sa6 Bit Status Register)
-   ------------------------ T1 ------------------------- */
-
-#define RSA6S_SX        0x20
-#define RSA6S_SF        0x10
-#define RSA6S_SE        0x08
-#define RSA6S_SC        0x04
-#define RSA6S_SA        0x02
-#define RSA6S_S8        0x01
-
-
-/* RDL1-3 Receive DL-Bit Register1-3)
-   ------------------------ T1 ------------------------- */
-
-#define RDL1_RDL17      0x80
-#define RDL1_RDL16      0x40
-#define RDL1_RDL15      0x20
-#define RDL1_RDL14      0x10
-#define RDL1_RDL13      0x08
-#define RDL1_RDL12      0x04
-#define RDL1_RDL11      0x02
-#define RDL1_RDL10      0x01
-
-#define RDL2_RDL27      0x80
-#define RDL2_RDL26      0x40
-#define RDL2_RDL25      0x20
-#define RDL2_RDL24      0x10
-#define RDL2_RDL23      0x08
-#define RDL2_RDL22      0x04
-#define RDL2_RDL21      0x02
-#define RDL2_RDL20      0x01
-
-#define RDL3_RDL37      0x80
-#define RDL3_RDL36      0x40
-#define RDL3_RDL35      0x20
-#define RDL3_RDL34      0x10
-#define RDL3_RDL33      0x08
-#define RDL3_RDL32      0x04
-#define RDL3_RDL31      0x02
-#define RDL3_RDL30      0x01
-
-
-/* SIS (Signaling Status Register)
-
-   -------------------- E1 & T1 -------------------------- */
-
-#define SIS_XDOV        0x80
-#define SIS_XFW         0x40
-#define SIS_XREP        0x20
-#define SIS_RLI         0x08
-#define SIS_CEC         0x04
-#define SIS_BOM         0x01
-
-
-/* RSIS (Receive Signaling Status Register)
-
-   -------------------- E1 & T1 --------------------------- */
-
-#define RSIS_VFR        0x80
-#define RSIS_RDO        0x40
-#define RSIS_CRC16      0x20
-#define RSIS_RAB        0x10
-#define RSIS_HA1        0x08
-#define RSIS_HA0        0x04
-#define RSIS_HFR        0x02
-#define RSIS_LA         0x01
-
-
-/* RBCL/H (Receive Byte Count Low/High)
-
-   ------------------- E1 & T1 ----------------------- */
-
-#define RBCL_RBC7       0x80
-#define RBCL_RBC6       0x40
-#define RBCL_RBC5       0x20
-#define RBCL_RBC4       0x10
-#define RBCL_RBC3       0x08
-#define RBCL_RBC2       0x04
-#define RBCL_RBC1       0x02
-#define RBCL_RBC0       0x01
-
-#define RBCH_OV         0x10
-#define RBCH_RBC11      0x08
-#define RBCH_RBC10      0x04
-#define RBCH_RBC9       0x02
-#define RBCH_RBC8       0x01
-
-
-/* ISR1-3  (Interrupt Status Register 1-3)
-
-   ------------------ E1 & T1 ------------------------------ */
-
-#define  FISR0_RME     0x80
-#define  FISR0_RFS     0x40
-#define  FISR0_T8MS    0x20
-#define  FISR0_ISF     0x20
-#define  FISR0_RMB     0x10
-#define  FISR0_CASC    0x08
-#define  FISR0_RSC     0x08
-#define  FISR0_CRC6    0x04
-#define  FISR0_CRC4    0x04
-#define  FISR0_PDEN    0x02
-#define  FISR0_RPF     0x01
-
-#define  FISR1_CASE    0x80
-#define  FISR1_LLBSC   0x80
-#define  FISR1_RDO     0x40
-#define  FISR1_ALLS    0x20
-#define  FISR1_XDU     0x10
-#define  FISR1_XMB     0x08
-#define  FISR1_XLSC    0x02
-#define  FISR1_XPR     0x01
-
-#define  FISR2_FAR     0x80
-#define  FISR2_LFA     0x40
-#define  FISR2_MFAR    0x20
-#define  FISR2_T400MS  0x10
-#define  FISR2_LMFA    0x10
-#define  FISR2_AIS     0x08
-#define  FISR2_LOS     0x04
-#define  FISR2_RAR     0x02
-#define  FISR2_RA      0x01
-
-#define  FISR3_ES      0x80
-#define  FISR3_SEC     0x40
-#define  FISR3_LMFA16  0x20
-#define  FISR3_AIS16   0x10
-#define  FISR3_RA16    0x08
-#define  FISR3_API     0x04
-#define  FISR3_XSLP    0x20
-#define  FISR3_XSLN    0x10
-#define  FISR3_LLBSC   0x08
-#define  FISR3_XRS     0x04
-#define  FISR3_SLN     0x02
-#define  FISR3_SLP     0x01
-
-
-/* GIS  (Global Interrupt Status Register)
-
-   --------------------- E1 & T1 --------------------- */
-
-#define  GIS_ISR3      0x08
-#define  GIS_ISR2      0x04
-#define  GIS_ISR1      0x02
-#define  GIS_ISR0      0x01
-
-
-/* VSTR  (Version Status Register)
-
-   --------------------- E1 & T1 --------------------- */
-
-#define  VSTR_VN3      0x08
-#define  VSTR_VN2      0x04
-#define  VSTR_VN1      0x02
-#define  VSTR_VN0      0x01
-
-
-/*>>>>>>>>>>>>>>>>>>>>>  Local Control Structures  <<<<<<<<<<<<<<<<<<<<<<<<< */
-
-/* Write-only Registers (E1/T1 control mode write registers) */
-#define XFIFOH 0x00            /* Tx FIFO High Byte */
-#define XFIFOL 0x01            /* Tx FIFO Low Byte */
-#define CMDR   0x02            /* Command Reg */
-#define DEC    0x60            /* Disable Error Counter */
-#define TEST2  0x62            /* Manuf. Test Reg 2 */
-#define XS(nbr)        (0x70 + (nbr))  /* Tx CAS Reg (0 to 15) */
-
-/* Read-write Registers (E1/T1 status mode read registers) */
-#define MODE   0x03    /* Mode Reg */
-#define RAH1   0x04    /* Receive Address High 1 */
-#define RAH2   0x05    /* Receive Address High 2 */
-#define RAL1   0x06    /* Receive Address Low 1 */
-#define RAL2   0x07    /* Receive Address Low 2 */
-#define IPC    0x08    /* Interrupt Port Configuration */
-#define CCR1   0x09    /* Common Configuration Reg 1 */
-#define CCR3   0x0A    /* Common Configuration Reg 3 */
-#define PRE    0x0B    /* Preamble Reg */
-#define RTR1   0x0C    /* Receive Timeslot Reg 1 */
-#define RTR2   0x0D    /* Receive Timeslot Reg 2 */
-#define RTR3   0x0E    /* Receive Timeslot Reg 3 */
-#define RTR4   0x0F    /* Receive Timeslot Reg 4 */
-#define TTR1   0x10    /* Transmit Timeslot Reg 1 */
-#define TTR2   0x11    /* Transmit Timeslot Reg 2 */
-#define TTR3   0x12    /* Transmit Timeslot Reg 3 */
-#define TTR4   0x13    /* Transmit Timeslot Reg 4 */
-#define IMR0   0x14    /* Interrupt Mask Reg 0 */
-#define IMR1   0x15    /* Interrupt Mask Reg 1 */
-#define IMR2   0x16    /* Interrupt Mask Reg 2 */
-#define IMR3   0x17    /* Interrupt Mask Reg 3 */
-#define IMR4   0x18    /* Interrupt Mask Reg 4 */
-#define IMR5   0x19    /* Interrupt Mask Reg 5 */
-#define FMR0   0x1A    /* Framer Mode Reigster 0 */
-#define FMR1   0x1B    /* Framer Mode Reigster 1 */
-#define FMR2   0x1C    /* Framer Mode Reigster 2 */
-#define LOOP   0x1D    /* Channel Loop Back */
-#define XSW    0x1E    /* Transmit Service Word */
-#define FMR4   0x1E    /* Framer Mode Reg 4 */
-#define XSP    0x1F    /* Transmit Spare Bits */
-#define FMR5   0x1F    /* Framer Mode Reg 5 */
-#define XC0    0x20    /* Transmit Control 0 */
-#define XC1    0x21    /* Transmit Control 1 */
-#define RC0    0x22    /* Receive Control 0 */
-#define RC1    0x23    /* Receive Control 1 */
-#define XPM0   0x24    /* Transmit Pulse Mask 0 */
-#define XPM1   0x25    /* Transmit Pulse Mask 1 */
-#define XPM2   0x26    /* Transmit Pulse Mask 2 */
-#define TSWM   0x27    /* Transparent Service Word Mask */
-#define TEST1  0x28    /* Manuf. Test Reg 1 */
-#define IDLE   0x29    /* Idle Channel Code */
-#define XSA4    0x2A   /* Transmit SA4 Bit Reg */
-#define XDL1   0x2A    /* Transmit DL-Bit Reg 2 */
-#define XSA5    0x2B   /* Transmit SA4 Bit Reg */
-#define XDL2   0x2B    /* Transmit DL-Bit Reg 2 */
-#define XSA6    0x2C   /* Transmit SA4 Bit Reg */
-#define XDL3   0x2C    /* Transmit DL-Bit Reg 2 */
-#define XSA7    0x2D   /* Transmit SA4 Bit Reg */
-#define CCB1   0x2D    /* Clear Channel Reg 1 */
-#define XSA8    0x2E   /* Transmit SA4 Bit Reg */
-#define CCB2   0x2E    /* Clear Channel Reg 2 */
-#define FMR3   0x2F    /* Framer Mode Reg. 3 */
-#define CCB3   0x2F    /* Clear Channel Reg 3 */
-#define ICB1   0x30    /* Idle Channel Reg 1 */
-#define ICB2   0x31    /* Idle Channel Reg 2 */
-#define ICB3   0x32    /* Idle Channel Reg 3 */
-#define ICB4   0x33    /* Idle Channel Reg 4 */
-#define LIM0   0x34    /* Line Interface Mode 0 */
-#define LIM1   0x35    /* Line Interface Mode 1 */
-#define PCDR   0x36    /* Pulse Count Detection */
-#define PCRR   0x37    /* Pulse Count Recovery */
-#define LIM2   0x38    /* Line Interface Mode Reg 2 */
-#define LCR1   0x39    /* Loop Code Reg 1 */
-#define LCR2   0x3A    /* Loop Code Reg 2 */
-#define LCR3   0x3B    /* Loop Code Reg 3 */
-#define SIC1   0x3C    /* System Interface Control 1 */
-
-/* Read-only Registers (E1/T1 control mode read registers) */
-#define RFIFOH 0x00            /* Receive FIFO */
-#define RFIFOL 0x01            /* Receive FIFO */
-#define FRS0   0x4C            /* Framer Receive Status 0 */
-#define FRS1   0x4D            /* Framer Receive Status 1 */
-#define RSW    0x4E            /* Receive Service Word */
-#define FRS2   0x4E            /* Framer Receive Status 2 */
-#define RSP    0x4F            /* Receive Spare Bits */
-#define FRS3   0x4F            /* Framer Receive Status 3 */
-#define FECL   0x50            /* Framing Error Counter */
-#define FECH   0x51            /* Framing Error Counter */
-#define CVCL   0x52            /* Code Violation Counter */
-#define CVCH   0x53            /* Code Violation Counter */
-#define CECL   0x54            /* CRC Error Counter 1 */
-#define CECH   0x55            /* CRC Error Counter 1 */
-#define EBCL   0x56            /* E-Bit Error Counter */
-#define EBCH   0x57            /* E-Bit Error Counter */
-#define BECL   0x58            /* Bit Error Counter Low */
-#define BECH   0x59            /* Bit Error Counter Low */
-#define CEC3   0x5A            /* CRC Error Counter 3 (16-bit) */
-#define RSA4   0x5C            /* Receive SA4 Bit Reg */
-#define RDL1   0x5C            /* Receive DL-Bit Reg 1 */
-#define RSA5   0x5D            /* Receive SA5 Bit Reg */
-#define RDL2   0x5D            /* Receive DL-Bit Reg 2 */
-#define RSA6   0x5E            /* Receive SA6 Bit Reg */
-#define RDL3   0x5E            /* Receive DL-Bit Reg 3 */
-#define RSA7   0x5F            /* Receive SA7 Bit Reg */
-#define RSA8   0x60            /* Receive SA8 Bit Reg */
-#define RSA6S  0x61            /* Receive SA6 Bit Status Reg */
-#define TSR0   0x62            /* Manuf. Test Reg 0 */
-#define TSR1   0x63            /* Manuf. Test Reg 1 */
-#define SIS    0x64            /* Signaling Status Reg */
-#define RSIS   0x65            /* Receive Signaling Status Reg */
-#define RBCL   0x66            /* Receive Byte Control */
-#define RBCH   0x67            /* Receive Byte Control */
-#define FISR0  0x68            /* Interrupt Status Reg 0 */
-#define FISR1  0x69            /* Interrupt Status Reg 1 */
-#define FISR2  0x6A            /* Interrupt Status Reg 2 */
-#define FISR3  0x6B            /* Interrupt Status Reg 3 */
-#define GIS    0x6E            /* Global Interrupt Status */
-#define VSTR   0x6F            /* Version Status */
-#define RS(nbr)        (0x70 + (nbr))  /* Rx CAS Reg (0 to 15) */
-
-#endif /* _FALC_LH_H */
-
 
+++ /dev/null
-/*
- * pc300.h     Cyclades-PC300(tm) Kernel API Definitions.
- *
- * Author:     Ivan Passos <ivan@cyclades.com>
- *
- * Copyright:  (c) 1999-2002 Cyclades Corp.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *
- * $Log: pc300.h,v $
- * Revision 3.12  2002/03/07 14:17:09  henrique
- * License data fixed
- *
- * Revision 3.11  2002/01/28 21:09:39  daniela
- * Included ';' after pc300hw.bus.
- *
- * Revision 3.10  2002/01/17 17:58:52  ivan
- * Support for PC300-TE/M (PMC).
- *
- * Revision 3.9  2001/09/28 13:30:53  daniela
- * Renamed dma_start routine to rx_dma_start.
- *
- * Revision 3.8  2001/09/24 13:03:45  daniela
- * Fixed BOF interrupt treatment. Created dma_start routine.
- *
- * Revision 3.7  2001/08/10 17:19:58  daniela
- * Fixed IOCTLs defines.
- *
- * Revision 3.6  2001/07/18 19:24:42  daniela
- * Included kernel version.
- *
- * Revision 3.5  2001/07/05 18:38:08  daniela
- * DMA transmission bug fix.
- *
- * Revision 3.4  2001/06/26 17:10:40  daniela
- * New configuration parameters (line code, CRC calculation and clock).
- *
- * Revision 3.3  2001/06/22 13:13:02  regina
- * MLPPP implementation
- *
- * Revision 3.2  2001/06/18 17:56:09  daniela
- * Increased DEF_MTU and TX_QUEUE_LEN.
- *
- * Revision 3.1  2001/06/15 12:41:10  regina
- * upping major version number
- *
- * Revision 1.1.1.1  2001/06/13 20:25:06  daniela
- * PC300 initial CVS version (3.4.0-pre1)
- *
- * Revision 2.3 2001/03/05 daniela
- * Created struct pc300conf, to provide the hardware information to pc300util.
- * Inclusion of 'alloc_ramsize' field on structure 'pc300hw'.
- * 
- * Revision 2.2 2000/12/22 daniela
- * Structures and defines to support pc300util: statistics, status, 
- * loopback tests, trace.
- * 
- * Revision 2.1 2000/09/28 ivan
- * Inclusion of 'iophys' and 'iosize' fields on structure 'pc300hw', to 
- * allow release of I/O region at module unload.
- * Changed location of include files.
- *
- * Revision 2.0 2000/03/27 ivan
- * Added support for the PC300/TE cards.
- *
- * Revision 1.1 2000/01/31 ivan
- * Replaced 'pc300[drv|sca].h' former PC300 driver include files.
- *
- * Revision 1.0 1999/12/16 ivan
- * First official release.
- * Inclusion of 'nchan' field on structure 'pc300hw', to allow variable 
- * number of ports per card.
- * Inclusion of 'if_ptr' field on structure 'pc300dev'.
- *
- * Revision 0.6 1999/11/17 ivan
- * Changed X.25-specific function names to comply with adopted convention.
- *
- * Revision 0.5 1999/11/16 Daniela Squassoni
- * X.25 support.
- *
- * Revision 0.4 1999/11/15 ivan
- * Inclusion of 'clock' field on structure 'pc300hw'.
- *
- * Revision 0.3 1999/11/10 ivan
- * IOCTL name changing.
- * Inclusion of driver function prototypes.
- *
- * Revision 0.2 1999/11/03 ivan
- * Inclusion of 'tx_skb' and union 'ifu' on structure 'pc300dev'.
- *
- * Revision 0.1 1999/01/15 ivan
- * Initial version.
- *
- */
-
-#ifndef        _PC300_H
-#define        _PC300_H
-
-#include <linux/hdlc.h>
-#include "hd64572.h"
-#include "pc300-falc-lh.h"
-
-#define PC300_PROTO_MLPPP 1
-
-#define        PC300_MAXCHAN   2       /* Number of channels per card */
-
-#define        PC300_RAMSIZE   0x40000 /* RAM window size (256Kb) */
-#define        PC300_FALCSIZE  0x400   /* FALC window size (1Kb) */
-
-#define PC300_OSC_CLOCK        24576000
-#define PC300_PCI_CLOCK        33000000
-
-#define BD_DEF_LEN     0x0800  /* DMA buffer length (2KB) */
-#define DMA_TX_MEMSZ   0x8000  /* Total DMA Tx memory size (32KB/ch) */
-#define DMA_RX_MEMSZ   0x10000 /* Total DMA Rx memory size (64KB/ch) */
-
-#define N_DMA_TX_BUF   (DMA_TX_MEMSZ / BD_DEF_LEN)     /* DMA Tx buffers */
-#define N_DMA_RX_BUF   (DMA_RX_MEMSZ / BD_DEF_LEN)     /* DMA Rx buffers */
-
-/* DMA Buffer Offsets */
-#define DMA_TX_BASE    ((N_DMA_TX_BUF + N_DMA_RX_BUF) *        \
-                        PC300_MAXCHAN * sizeof(pcsca_bd_t))
-#define DMA_RX_BASE    (DMA_TX_BASE + PC300_MAXCHAN*DMA_TX_MEMSZ)
-
-/* DMA Descriptor Offsets */
-#define DMA_TX_BD_BASE 0x0000
-#define DMA_RX_BD_BASE (DMA_TX_BD_BASE + ((PC300_MAXCHAN*DMA_TX_MEMSZ / \
-                               BD_DEF_LEN) * sizeof(pcsca_bd_t)))
-
-/* DMA Descriptor Macros */
-#define TX_BD_ADDR(chan, n)    (DMA_TX_BD_BASE + \
-                                ((N_DMA_TX_BUF*chan) + n) * sizeof(pcsca_bd_t))
-#define RX_BD_ADDR(chan, n)    (DMA_RX_BD_BASE + \
-                                ((N_DMA_RX_BUF*chan) + n) * sizeof(pcsca_bd_t))
-
-/* Macro to access the FALC registers (TE only) */
-#define F_REG(reg, chan)       (0x200*(chan) + ((reg)<<2))
-
-/***************************************
- * Memory access functions/macros      *
- * (required to support Alpha systems) *
- ***************************************/
-#define cpc_writeb(port,val)   {writeb((u8)(val),(port)); mb();}
-#define cpc_writew(port,val)   {writew((ushort)(val),(port)); mb();}
-#define cpc_writel(port,val)   {writel((u32)(val),(port)); mb();}
-
-#define cpc_readb(port)                readb(port)
-#define cpc_readw(port)                readw(port)
-#define cpc_readl(port)                readl(port)
-
-/****** Data Structures *****************************************************/
-
-/*
- *      RUNTIME_9050 - PLX PCI9050-1 local configuration and shared runtime
- *      registers. This structure can be used to access the 9050 registers
- *      (memory mapped).
- */
-struct RUNTIME_9050 {
-       u32 loc_addr_range[4];  /* 00-0Ch : Local Address Ranges */
-       u32 loc_rom_range;      /* 10h : Local ROM Range */
-       u32 loc_addr_base[4];   /* 14-20h : Local Address Base Addrs */
-       u32 loc_rom_base;       /* 24h : Local ROM Base */
-       u32 loc_bus_descr[4];   /* 28-34h : Local Bus Descriptors */
-       u32 rom_bus_descr;      /* 38h : ROM Bus Descriptor */
-       u32 cs_base[4];         /* 3C-48h : Chip Select Base Addrs */
-       u32 intr_ctrl_stat;     /* 4Ch : Interrupt Control/Status */
-       u32 init_ctrl;          /* 50h : EEPROM ctrl, Init Ctrl, etc */
-};
-
-#define PLX_9050_LINT1_ENABLE  0x01
-#define PLX_9050_LINT1_POL     0x02
-#define PLX_9050_LINT1_STATUS  0x04
-#define PLX_9050_LINT2_ENABLE  0x08
-#define PLX_9050_LINT2_POL     0x10
-#define PLX_9050_LINT2_STATUS  0x20
-#define PLX_9050_INTR_ENABLE   0x40
-#define PLX_9050_SW_INTR       0x80
-
-/* Masks to access the init_ctrl PLX register */
-#define        PC300_CLKSEL_MASK               (0x00000004UL)
-#define        PC300_CHMEDIA_MASK(chan)        (0x00000020UL<<(chan*3))
-#define        PC300_CTYPE_MASK                (0x00000800UL)
-
-/* CPLD Registers (base addr = falcbase, TE only) */
-/* CPLD v. 0 */
-#define CPLD_REG1      0x140   /* Chip resets, DCD/CTS status */
-#define CPLD_REG2      0x144   /* Clock enable , LED control */
-/* CPLD v. 2 or higher */
-#define CPLD_V2_REG1   0x100   /* Chip resets, DCD/CTS status */
-#define CPLD_V2_REG2   0x104   /* Clock enable , LED control */
-#define CPLD_ID_REG    0x108   /* CPLD version */
-
-/* CPLD Register bit description: for the FALC bits, they should always be 
-   set based on the channel (use (bit<<(2*ch)) to access the correct bit for 
-   that channel) */
-#define CPLD_REG1_FALC_RESET   0x01
-#define CPLD_REG1_SCA_RESET    0x02
-#define CPLD_REG1_GLOBAL_CLK   0x08
-#define CPLD_REG1_FALC_DCD     0x10
-#define CPLD_REG1_FALC_CTS     0x20
-
-#define CPLD_REG2_FALC_TX_CLK  0x01
-#define CPLD_REG2_FALC_RX_CLK  0x02
-#define CPLD_REG2_FALC_LED1    0x10
-#define CPLD_REG2_FALC_LED2    0x20
-
-/* Structure with FALC-related fields (TE only) */
-#define PC300_FALC_MAXLOOP     0x0000ffff      /* for falc_issue_cmd() */
-
-typedef struct falc {
-       u8 sync;        /* If true FALC is synchronized */
-       u8 active;      /* if TRUE then already active */
-       u8 loop_active; /* if TRUE a line loopback UP was received */
-       u8 loop_gen;    /* if TRUE a line loopback UP was issued */
-
-       u8 num_channels;
-       u8 offset;      /* 1 for T1, 0 for E1 */
-       u8 full_bandwidth;
-
-       u8 xmb_cause;
-       u8 multiframe_mode;
-
-       /* Statistics */
-       u16 pden;       /* Pulse Density violation count */
-       u16 los;        /* Loss of Signal count */
-       u16 losr;       /* Loss of Signal recovery count */
-       u16 lfa;        /* Loss of frame alignment count */
-       u16 farec;      /* Frame Alignment Recovery count */
-       u16 lmfa;       /* Loss of multiframe alignment count */
-       u16 ais;        /* Remote Alarm indication Signal count */
-       u16 sec;        /* One-second timer */
-       u16 es;         /* Errored second */
-       u16 rai;        /* remote alarm received */
-       u16 bec;
-       u16 fec;
-       u16 cvc;
-       u16 cec;
-       u16 ebc;
-
-       /* Status */
-       u8 red_alarm;
-       u8 blue_alarm;
-       u8 loss_fa;
-       u8 yellow_alarm;
-       u8 loss_mfa;
-       u8 prbs;
-} falc_t;
-
-typedef struct falc_status {
-       u8 sync;        /* If true FALC is synchronized */
-       u8 red_alarm;
-       u8 blue_alarm;
-       u8 loss_fa;
-       u8 yellow_alarm;
-       u8 loss_mfa;
-       u8 prbs;
-} falc_status_t;
-
-typedef struct rsv_x21_status {
-       u8 dcd;
-       u8 dsr;
-       u8 cts;
-       u8 rts;
-       u8 dtr;
-} rsv_x21_status_t;
-
-typedef struct pc300stats {
-       int hw_type;
-       u32 line_on;
-       u32 line_off;
-       struct net_device_stats gen_stats;
-       falc_t te_stats;
-} pc300stats_t;
-
-typedef struct pc300status {
-       int hw_type;
-       rsv_x21_status_t gen_status;
-       falc_status_t te_status;
-} pc300status_t;
-
-typedef struct pc300loopback {
-       char loop_type;
-       char loop_on;
-} pc300loopback_t;
-
-typedef struct pc300patterntst {
-       char patrntst_on;       /* 0 - off; 1 - on; 2 - read num_errors */
-       u16 num_errors;
-} pc300patterntst_t;
-
-typedef struct pc300dev {
-       struct pc300ch *chan;
-       u8 trace_on;
-       u32 line_on;            /* DCD(X.21, RSV) / sync(TE) change counters */
-       u32 line_off;
-       char name[16];
-       struct net_device *dev;
-#ifdef CONFIG_PC300_MLPPP
-       void *cpc_tty;  /* information to PC300 TTY driver */
-#endif
-}pc300dev_t;
-
-typedef struct pc300hw {
-       int type;               /* RSV, X21, etc. */
-       int bus;                /* Bus (PCI, PMC, etc.) */
-       int nchan;              /* number of channels */
-       int irq;                /* interrupt request level */
-       u32 clock;              /* Board clock */
-       u8 cpld_id;             /* CPLD ID (TE only) */
-       u16 cpld_reg1;          /* CPLD reg 1 (TE only) */
-       u16 cpld_reg2;          /* CPLD reg 2 (TE only) */
-       u16 gpioc_reg;          /* PLX GPIOC reg */
-       u16 intctl_reg;         /* PLX Int Ctrl/Status reg */
-       u32 iophys;             /* PLX registers I/O base */
-       u32 iosize;             /* PLX registers I/O size */
-       u32 plxphys;            /* PLX registers MMIO base (physical) */
-       void __iomem * plxbase; /* PLX registers MMIO base (virtual) */
-       u32 plxsize;            /* PLX registers MMIO size */
-       u32 scaphys;            /* SCA registers MMIO base (physical) */
-       void __iomem * scabase; /* SCA registers MMIO base (virtual) */
-       u32 scasize;            /* SCA registers MMIO size */
-       u32 ramphys;            /* On-board RAM MMIO base (physical) */
-       void __iomem * rambase; /* On-board RAM MMIO base (virtual) */
-       u32 alloc_ramsize;      /* RAM MMIO size allocated by the PCI bridge */
-       u32 ramsize;            /* On-board RAM MMIO size */
-       u32 falcphys;           /* FALC registers MMIO base (physical) */
-       void __iomem * falcbase;/* FALC registers MMIO base (virtual) */
-       u32 falcsize;           /* FALC registers MMIO size */
-} pc300hw_t;
-
-typedef struct pc300chconf {
-       sync_serial_settings    phys_settings;  /* Clock type/rate (in bps),
-                                                  loopback mode */
-       raw_hdlc_proto          proto_settings; /* Encoding, parity (CRC) */
-       u32 media;              /* HW media (RS232, V.35, etc.) */
-       u32 proto;              /* Protocol (PPP, X.25, etc.) */
-
-       /* TE-specific parameters */
-       u8 lcode;               /* Line Code (AMI, B8ZS, etc.) */
-       u8 fr_mode;             /* Frame Mode (ESF, D4, etc.) */
-       u8 lbo;                 /* Line Build Out */
-       u8 rx_sens;             /* Rx Sensitivity (long- or short-haul) */
-       u32 tslot_bitmap;       /* bit[i]=1  =>  timeslot _i_ is active */
-} pc300chconf_t;
-
-typedef struct pc300ch {
-       struct pc300 *card;
-       int channel;
-       pc300dev_t d;
-       pc300chconf_t conf;
-       u8 tx_first_bd; /* First TX DMA block descr. w/ data */
-       u8 tx_next_bd;  /* Next free TX DMA block descriptor */
-       u8 rx_first_bd; /* First free RX DMA block descriptor */
-       u8 rx_last_bd;  /* Last free RX DMA block descriptor */
-       u8 nfree_tx_bd; /* Number of free TX DMA block descriptors */
-       falc_t falc;    /* FALC structure (TE only) */
-} pc300ch_t;
-
-typedef struct pc300 {
-       pc300hw_t hw;                   /* hardware config. */
-       pc300ch_t chan[PC300_MAXCHAN];
-       spinlock_t card_lock;
-} pc300_t;
-
-typedef struct pc300conf {
-       pc300hw_t hw;
-       pc300chconf_t conf;
-} pc300conf_t;
-
-/* DEV ioctl() commands */
-#define        N_SPPP_IOCTLS   2
-
-enum pc300_ioctl_cmds {
-       SIOCCPCRESERVED = (SIOCDEVPRIVATE + N_SPPP_IOCTLS),
-       SIOCGPC300CONF,
-       SIOCSPC300CONF,
-       SIOCGPC300STATUS,
-       SIOCGPC300FALCSTATUS,
-       SIOCGPC300UTILSTATS,
-       SIOCGPC300UTILSTATUS,
-       SIOCSPC300TRACE,
-       SIOCSPC300LOOPBACK,
-       SIOCSPC300PATTERNTEST,
-};
-
-/* Loopback types - PC300/TE boards */
-enum pc300_loopback_cmds {
-       PC300LOCLOOP = 1,
-       PC300REMLOOP,
-       PC300PAYLOADLOOP,
-       PC300GENLOOPUP,
-       PC300GENLOOPDOWN,
-};
-
-/* Control Constant Definitions */
-#define        PC300_RSV       0x01
-#define        PC300_X21       0x02
-#define        PC300_TE        0x03
-
-#define        PC300_PCI       0x00
-#define        PC300_PMC       0x01
-
-#define PC300_LC_AMI   0x01
-#define PC300_LC_B8ZS  0x02
-#define PC300_LC_NRZ   0x03
-#define PC300_LC_HDB3  0x04
-
-/* Framing (T1) */
-#define PC300_FR_ESF           0x01
-#define PC300_FR_D4            0x02
-#define PC300_FR_ESF_JAPAN     0x03
-
-/* Framing (E1) */
-#define PC300_FR_MF_CRC4       0x04
-#define PC300_FR_MF_NON_CRC4   0x05
-#define PC300_FR_UNFRAMED      0x06
-
-#define PC300_LBO_0_DB         0x00
-#define PC300_LBO_7_5_DB       0x01
-#define PC300_LBO_15_DB                0x02
-#define PC300_LBO_22_5_DB      0x03
-
-#define PC300_RX_SENS_SH       0x01
-#define PC300_RX_SENS_LH       0x02
-
-#define PC300_TX_TIMEOUT       (2*HZ)
-#define PC300_TX_QUEUE_LEN     100
-#define        PC300_DEF_MTU           1600
-
-/* Function Prototypes */
-int cpc_open(struct net_device *dev);
-
-#endif /* _PC300_H */
 
+++ /dev/null
-#define        USE_PCI_CLOCK
-static const char rcsid[] =
-"Revision: 3.4.5 Date: 2002/03/07 ";
-
-/*
- * pc300.c     Cyclades-PC300(tm) Driver.
- *
- * Author:     Ivan Passos <ivan@cyclades.com>
- * Maintainer: PC300 Maintainer <pc300@cyclades.com>
- *
- * Copyright:  (c) 1999-2003 Cyclades Corp.
- *
- *     This program is free software; you can redistribute it and/or
- *     modify it under the terms of the GNU General Public License
- *     as published by the Free Software Foundation; either version
- *     2 of the License, or (at your option) any later version.
- *     
- *     Using tabstop = 4.
- * 
- * $Log: pc300_drv.c,v $
- * Revision 3.23  2002/03/20 13:58:40  henrique
- * Fixed ortographic mistakes
- *
- * Revision 3.22  2002/03/13 16:56:56  henrique
- * Take out the debug messages
- *
- * Revision 3.21  2002/03/07 14:17:09  henrique
- * License data fixed
- *
- * Revision 3.20  2002/01/17 17:58:52  ivan
- * Support for PC300-TE/M (PMC).
- *
- * Revision 3.19  2002/01/03 17:08:47  daniela
- * Enables DMA reception when the SCA-II disables it improperly.
- *
- * Revision 3.18  2001/12/03 18:47:50  daniela
- * Esthetic changes.
- *
- * Revision 3.17  2001/10/19 16:50:13  henrique
- * Patch to kernel 2.4.12 and new generic hdlc.
- *
- * Revision 3.16  2001/10/16 15:12:31  regina
- * clear statistics
- *
- * Revision 3.11 to 3.15  2001/10/11 20:26:04  daniela
- * More DMA fixes for noisy lines.
- * Return the size of bad frames in dma_get_rx_frame_size, so that the Rx buffer
- * descriptors can be cleaned by dma_buf_read (called in cpc_net_rx).
- * Renamed dma_start routine to rx_dma_start. Improved Rx statistics.
- * Fixed BOF interrupt treatment. Created dma_start routine.
- * Changed min and max to cpc_min and cpc_max.
- *
- * Revision 3.10  2001/08/06 12:01:51  regina
- * Fixed problem in DSR_DE bit.
- *
- * Revision 3.9  2001/07/18 19:27:26  daniela
- * Added some history comments.
- *
- * Revision 3.8  2001/07/12 13:11:19  regina
- * bug fix - DCD-OFF in pc300 tty driver
- *
- * Revision 3.3 to 3.7  2001/07/06 15:00:20  daniela
- * Removing kernel 2.4.3 and previous support.
- * DMA transmission bug fix.
- * MTU check in cpc_net_rx fixed.
- * Boot messages reviewed.
- * New configuration parameters (line code, CRC calculation and clock).
- *
- * Revision 3.2 2001/06/22 13:13:02  regina
- * MLPPP implementation. Changed the header of message trace to include
- * the device name. New format : "hdlcX[R/T]: ".
- * Default configuration changed.
- *
- * Revision 3.1 2001/06/15 regina
- * in cpc_queue_xmit, netif_stop_queue is called if don't have free descriptor
- * upping major version number
- *
- * Revision 1.1.1.1  2001/06/13 20:25:04  daniela
- * PC300 initial CVS version (3.4.0-pre1)
- *
- * Revision 3.0.1.2 2001/06/08 daniela
- * Did some changes in the DMA programming implementation to avoid the 
- * occurrence of a SCA-II bug when CDA is accessed during a DMA transfer.
- *
- * Revision 3.0.1.1 2001/05/02 daniela
- * Added kernel 2.4.3 support.
- * 
- * Revision 3.0.1.0 2001/03/13 daniela, henrique
- * Added Frame Relay Support.
- * Driver now uses HDLC generic driver to provide protocol support.
- * 
- * Revision 3.0.0.8 2001/03/02 daniela
- * Fixed ram size detection. 
- * Changed SIOCGPC300CONF ioctl, to give hw information to pc300util.
- * 
- * Revision 3.0.0.7 2001/02/23 daniela
- * netif_stop_queue called before the SCA-II transmition commands in 
- * cpc_queue_xmit, and with interrupts disabled to avoid race conditions with 
- * transmition interrupts.
- * Fixed falc_check_status for Unframed E1.
- * 
- * Revision 3.0.0.6 2000/12/13 daniela
- * Implemented pc300util support: trace, statistics, status and loopback
- * tests for the PC300 TE boards.
- * 
- * Revision 3.0.0.5 2000/12/12 ivan
- * Added support for Unframed E1.
- * Implemented monitor mode.
- * Fixed DCD sensitivity on the second channel.
- * Driver now complies with new PCI kernel architecture.
- *
- * Revision 3.0.0.4 2000/09/28 ivan
- * Implemented DCD sensitivity.
- * Moved hardware-specific open to the end of cpc_open, to avoid race
- * conditions with early reception interrupts.
- * Included code for [request|release]_mem_region().
- * Changed location of pc300.h .
- * Minor code revision (contrib. of Jeff Garzik).
- *
- * Revision 3.0.0.3 2000/07/03 ivan
- * Previous bugfix for the framing errors with external clock made X21
- * boards stop working. This version fixes it.
- *
- * Revision 3.0.0.2 2000/06/23 ivan
- * Revisited cpc_queue_xmit to prevent race conditions on Tx DMA buffer
- * handling when Tx timeouts occur.
- * Revisited Rx statistics.
- * Fixed a bug in the SCA-II programming that would cause framing errors
- * when external clock was configured.
- *
- * Revision 3.0.0.1 2000/05/26 ivan
- * Added logic in the SCA interrupt handler so that no board can monopolize
- * the driver.
- * Request PLX I/O region, although driver doesn't use it, to avoid
- * problems with other drivers accessing it.
- *
- * Revision 3.0.0.0 2000/05/15 ivan
- * Did some changes in the DMA programming implementation to avoid the
- * occurrence of a SCA-II bug in the second channel.
- * Implemented workaround for PLX9050 bug that would cause a system lockup
- * in certain systems, depending on the MMIO addresses allocated to the
- * board.
- * Fixed the FALC chip programming to avoid synchronization problems in the
- * second channel (TE only).
- * Implemented a cleaner and faster Tx DMA descriptor cleanup procedure in
- * cpc_queue_xmit().
- * Changed the built-in driver implementation so that the driver can use the
- * general 'hdlcN' naming convention instead of proprietary device names.
- * Driver load messages are now device-centric, instead of board-centric.
- * Dynamic allocation of net_device structures.
- * Code is now compliant with the new module interface (module_[init|exit]).
- * Make use of the PCI helper functions to access PCI resources.
- *
- * Revision 2.0.0.0 2000/04/15 ivan
- * Added support for the PC300/TE boards (T1/FT1/E1/FE1).
- *
- * Revision 1.1.0.0 2000/02/28 ivan
- * Major changes in the driver architecture.
- * Softnet compliancy implemented.
- * Driver now reports physical instead of virtual memory addresses.
- * Added cpc_change_mtu function.
- *
- * Revision 1.0.0.0 1999/12/16 ivan
- * First official release.
- * Support for 1- and 2-channel boards (which use distinct PCI Device ID's).
- * Support for monolythic installation (i.e., drv built into the kernel).
- * X.25 additional checking when lapb_[dis]connect_request returns an error.
- * SCA programming now covers X.21 as well.
- *
- * Revision 0.3.1.0 1999/11/18 ivan
- * Made X.25 support configuration-dependent (as it depends on external 
- * modules to work).
- * Changed X.25-specific function names to comply with adopted convention.
- * Fixed typos in X.25 functions that would cause compile errors (Daniela).
- * Fixed bug in ch_config that would disable interrupts on a previously 
- * enabled channel if the other channel on the same board was enabled later.
- *
- * Revision 0.3.0.0 1999/11/16 daniela
- * X.25 support.
- *
- * Revision 0.2.3.0 1999/11/15 ivan
- * Function cpc_ch_status now provides more detailed information.
- * Added support for X.21 clock configuration.
- * Changed TNR1 setting in order to prevent Tx FIFO overaccesses by the SCA.
- * Now using PCI clock instead of internal oscillator clock for the SCA.
- *
- * Revision 0.2.2.0 1999/11/10 ivan
- * Changed the *_dma_buf_check functions so that they would print only 
- * the useful info instead of the whole buffer descriptor bank.
- * Fixed bug in cpc_queue_xmit that would eventually crash the system 
- * in case of a packet drop.
- * Implemented TX underrun handling.
- * Improved SCA fine tuning to boost up its performance.
- *
- * Revision 0.2.1.0 1999/11/03 ivan
- * Added functions *dma_buf_pt_init to allow independent initialization 
- * of the next-descr. and DMA buffer pointers on the DMA descriptors.
- * Kernel buffer release and tbusy clearing is now done in the interrupt 
- * handler.
- * Fixed bug in cpc_open that would cause an interface reopen to fail.
- * Added a protocol-specific code section in cpc_net_rx.
- * Removed printk level defs (they might be added back after the beta phase).
- *
- * Revision 0.2.0.0 1999/10/28 ivan
- * Revisited the code so that new protocols can be easily added / supported. 
- *
- * Revision 0.1.0.1 1999/10/20 ivan
- * Mostly "esthetic" changes.
- *
- * Revision 0.1.0.0 1999/10/11 ivan
- * Initial version.
- *
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/net.h>
-#include <linux/skbuff.h>
-#include <linux/if_arp.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/spinlock.h>
-#include <linux/if.h>
-#include <linux/slab.h>
-#include <net/arp.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "pc300.h"
-
-#define        CPC_LOCK(card,flags)            \
-               do {                                            \
-               spin_lock_irqsave(&card->card_lock, flags);     \
-               } while (0)
-
-#define CPC_UNLOCK(card,flags)                 \
-               do {                                                    \
-               spin_unlock_irqrestore(&card->card_lock, flags);        \
-               } while (0)
-
-#undef PC300_DEBUG_PCI
-#undef PC300_DEBUG_INTR
-#undef PC300_DEBUG_TX
-#undef PC300_DEBUG_RX
-#undef PC300_DEBUG_OTHER
-
-static DEFINE_PCI_DEVICE_TABLE(cpc_pci_dev_id) = {
-       /* PC300/RSV or PC300/X21, 2 chan */
-       {0x120e, 0x300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x300},
-       /* PC300/RSV or PC300/X21, 1 chan */
-       {0x120e, 0x301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x301},
-       /* PC300/TE, 2 chan */
-       {0x120e, 0x310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x310},
-       /* PC300/TE, 1 chan */
-       {0x120e, 0x311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x311},
-       /* PC300/TE-M, 2 chan */
-       {0x120e, 0x320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x320},
-       /* PC300/TE-M, 1 chan */
-       {0x120e, 0x321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x321},
-       /* End of table */
-       {0,},
-};
-MODULE_DEVICE_TABLE(pci, cpc_pci_dev_id);
-
-#ifndef cpc_min
-#define        cpc_min(a,b)    (((a)<(b))?(a):(b))
-#endif
-#ifndef cpc_max
-#define        cpc_max(a,b)    (((a)>(b))?(a):(b))
-#endif
-
-/* prototypes */
-static void tx_dma_buf_pt_init(pc300_t *, int);
-static void tx_dma_buf_init(pc300_t *, int);
-static void rx_dma_buf_pt_init(pc300_t *, int);
-static void rx_dma_buf_init(pc300_t *, int);
-static void tx_dma_buf_check(pc300_t *, int);
-static void rx_dma_buf_check(pc300_t *, int);
-static irqreturn_t cpc_intr(int, void *);
-static int clock_rate_calc(u32, u32, int *);
-static u32 detect_ram(pc300_t *);
-static void plx_init(pc300_t *);
-static void cpc_trace(struct net_device *, struct sk_buff *, char);
-static int cpc_attach(struct net_device *, unsigned short, unsigned short);
-static int cpc_close(struct net_device *dev);
-
-#ifdef CONFIG_PC300_MLPPP
-void cpc_tty_init(pc300dev_t * dev);
-void cpc_tty_unregister_service(pc300dev_t * pc300dev);
-void cpc_tty_receive(pc300dev_t * pc300dev);
-void cpc_tty_trigger_poll(pc300dev_t * pc300dev);
-#endif
-
-/************************/
-/***   DMA Routines   ***/
-/************************/
-static void tx_dma_buf_pt_init(pc300_t * card, int ch)
-{
-       int i;
-       int ch_factor = ch * N_DMA_TX_BUF;
-       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
-                                      + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
-
-       for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
-               cpc_writel(&ptdescr->next, (u32)(DMA_TX_BD_BASE +
-                       (ch_factor + ((i + 1) & (N_DMA_TX_BUF - 1))) * sizeof(pcsca_bd_t)));
-               cpc_writel(&ptdescr->ptbuf,
-                          (u32)(DMA_TX_BASE + (ch_factor + i) * BD_DEF_LEN));
-       }
-}
-
-static void tx_dma_buf_init(pc300_t * card, int ch)
-{
-       int i;
-       int ch_factor = ch * N_DMA_TX_BUF;
-       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
-                              + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
-
-       for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
-               memset_io(ptdescr, 0, sizeof(pcsca_bd_t));
-               cpc_writew(&ptdescr->len, 0);
-               cpc_writeb(&ptdescr->status, DST_OSB);
-       }
-       tx_dma_buf_pt_init(card, ch);
-}
-
-static void rx_dma_buf_pt_init(pc300_t * card, int ch)
-{
-       int i;
-       int ch_factor = ch * N_DMA_RX_BUF;
-       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
-                                      + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
-
-       for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
-               cpc_writel(&ptdescr->next, (u32)(DMA_RX_BD_BASE +
-                       (ch_factor + ((i + 1) & (N_DMA_RX_BUF - 1))) * sizeof(pcsca_bd_t)));
-               cpc_writel(&ptdescr->ptbuf,
-                          (u32)(DMA_RX_BASE + (ch_factor + i) * BD_DEF_LEN));
-       }
-}
-
-static void rx_dma_buf_init(pc300_t * card, int ch)
-{
-       int i;
-       int ch_factor = ch * N_DMA_RX_BUF;
-       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
-                                      + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
-
-       for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
-               memset_io(ptdescr, 0, sizeof(pcsca_bd_t));
-               cpc_writew(&ptdescr->len, 0);
-               cpc_writeb(&ptdescr->status, 0);
-       }
-       rx_dma_buf_pt_init(card, ch);
-}
-
-static void tx_dma_buf_check(pc300_t * card, int ch)
-{
-       volatile pcsca_bd_t __iomem *ptdescr;
-       int i;
-       u16 first_bd = card->chan[ch].tx_first_bd;
-       u16 next_bd = card->chan[ch].tx_next_bd;
-
-       printk("#CH%d: f_bd = %d(0x%08zx), n_bd = %d(0x%08zx)\n", ch,
-              first_bd, TX_BD_ADDR(ch, first_bd),
-              next_bd, TX_BD_ADDR(ch, next_bd));
-       for (i = first_bd,
-            ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, first_bd));
-            i != ((next_bd + 1) & (N_DMA_TX_BUF - 1));
-            i = (i + 1) & (N_DMA_TX_BUF - 1), 
-                ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i))) {
-               printk("\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d",
-                      ch, i, cpc_readl(&ptdescr->next),
-                      cpc_readl(&ptdescr->ptbuf),
-                      cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len));
-       }
-       printk("\n");
-}
-
-#ifdef PC300_DEBUG_OTHER
-/* Show all TX buffer descriptors */
-static void tx1_dma_buf_check(pc300_t * card, int ch)
-{
-       volatile pcsca_bd_t __iomem *ptdescr;
-       int i;
-       u16 first_bd = card->chan[ch].tx_first_bd;
-       u16 next_bd = card->chan[ch].tx_next_bd;
-       u32 scabase = card->hw.scabase;
-
-       printk ("\nnfree_tx_bd = %d\n", card->chan[ch].nfree_tx_bd);
-       printk("#CH%d: f_bd = %d(0x%08x), n_bd = %d(0x%08x)\n", ch,
-              first_bd, TX_BD_ADDR(ch, first_bd),
-              next_bd, TX_BD_ADDR(ch, next_bd));
-       printk("TX_CDA=0x%08x, TX_EDA=0x%08x\n",
-              cpc_readl(scabase + DTX_REG(CDAL, ch)),
-              cpc_readl(scabase + DTX_REG(EDAL, ch)));
-       for (i = 0; i < N_DMA_TX_BUF; i++) {
-               ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i));
-               printk("\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d",
-                      ch, i, cpc_readl(&ptdescr->next),
-                      cpc_readl(&ptdescr->ptbuf),
-                      cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len));
-       }
-       printk("\n");
-}
-#endif
-
-static void rx_dma_buf_check(pc300_t * card, int ch)
-{
-       volatile pcsca_bd_t __iomem *ptdescr;
-       int i;
-       u16 first_bd = card->chan[ch].rx_first_bd;
-       u16 last_bd = card->chan[ch].rx_last_bd;
-       int ch_factor;
-
-       ch_factor = ch * N_DMA_RX_BUF;
-       printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd);
-       for (i = 0, ptdescr = (card->hw.rambase +
-                                             DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
-            i < N_DMA_RX_BUF; i++, ptdescr++) {
-               if (cpc_readb(&ptdescr->status) & DST_OSB)
-                       printk ("\n CH%d RX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d",
-                                ch, i, cpc_readl(&ptdescr->next),
-                                cpc_readl(&ptdescr->ptbuf),
-                                cpc_readb(&ptdescr->status),
-                                cpc_readw(&ptdescr->len));
-       }
-       printk("\n");
-}
-
-static int dma_get_rx_frame_size(pc300_t * card, int ch)
-{
-       volatile pcsca_bd_t __iomem *ptdescr;
-       u16 first_bd = card->chan[ch].rx_first_bd;
-       int rcvd = 0;
-       volatile u8 status;
-
-       ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, first_bd));
-       while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
-               rcvd += cpc_readw(&ptdescr->len);
-               first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1);
-               if ((status & DST_EOM) || (first_bd == card->chan[ch].rx_last_bd)) {
-                       /* Return the size of a good frame or incomplete bad frame 
-                       * (dma_buf_read will clean the buffer descriptors in this case). */
-                       return rcvd;
-               }
-               ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
-       }
-       return -1;
-}
-
-/*
- * dma_buf_write: writes a frame to the Tx DMA buffers
- * NOTE: this function writes one frame at a time.
- */
-static int dma_buf_write(pc300_t *card, int ch, u8 *ptdata, int len)
-{
-       int i, nchar;
-       volatile pcsca_bd_t __iomem *ptdescr;
-       int tosend = len;
-       u8 nbuf = ((len - 1) / BD_DEF_LEN) + 1;
-
-       if (nbuf >= card->chan[ch].nfree_tx_bd) {
-               return -ENOMEM;
-       }
-
-       for (i = 0; i < nbuf; i++) {
-               ptdescr = (card->hw.rambase +
-                                         TX_BD_ADDR(ch, card->chan[ch].tx_next_bd));
-               nchar = cpc_min(BD_DEF_LEN, tosend);
-               if (cpc_readb(&ptdescr->status) & DST_OSB) {
-                       memcpy_toio((card->hw.rambase + cpc_readl(&ptdescr->ptbuf)),
-                                   &ptdata[len - tosend], nchar);
-                       cpc_writew(&ptdescr->len, nchar);
-                       card->chan[ch].nfree_tx_bd--;
-                       if ((i + 1) == nbuf) {
-                               /* This must be the last BD to be used */
-                               cpc_writeb(&ptdescr->status, DST_EOM);
-                       } else {
-                               cpc_writeb(&ptdescr->status, 0);
-                       }
-               } else {
-                       return -ENOMEM;
-               }
-               tosend -= nchar;
-               card->chan[ch].tx_next_bd =
-                       (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1);
-       }
-       /* If it gets to here, it means we have sent the whole frame */
-       return 0;
-}
-
-/*
- * dma_buf_read: reads a frame from the Rx DMA buffers
- * NOTE: this function reads one frame at a time.
- */
-static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
-{
-       int nchar;
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       volatile pcsca_bd_t __iomem *ptdescr;
-       int rcvd = 0;
-       volatile u8 status;
-
-       ptdescr = (card->hw.rambase +
-                                 RX_BD_ADDR(ch, chan->rx_first_bd));
-       while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
-               nchar = cpc_readw(&ptdescr->len);
-               if ((status & (DST_OVR | DST_CRC | DST_RBIT | DST_SHRT | DST_ABT)) ||
-                   (nchar > BD_DEF_LEN)) {
-
-                       if (nchar > BD_DEF_LEN)
-                               status |= DST_RBIT;
-                       rcvd = -status;
-                       /* Discard remaining descriptors used by the bad frame */
-                       while (chan->rx_first_bd != chan->rx_last_bd) {
-                               cpc_writeb(&ptdescr->status, 0);
-                               chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1);
-                               if (status & DST_EOM)
-                                       break;
-                               ptdescr = (card->hw.rambase +
-                                                         cpc_readl(&ptdescr->next));
-                               status = cpc_readb(&ptdescr->status);
-                       }
-                       break;
-               }
-               if (nchar != 0) {
-                       if (skb) {
-                               memcpy_fromio(skb_put(skb, nchar),
-                                (card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar);
-                       }
-                       rcvd += nchar;
-               }
-               cpc_writeb(&ptdescr->status, 0);
-               cpc_writeb(&ptdescr->len, 0);
-               chan->rx_first_bd = (chan->rx_first_bd + 1) & (N_DMA_RX_BUF - 1);
-
-               if (status & DST_EOM)
-                       break;
-
-               ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
-       }
-
-       if (rcvd != 0) {
-               /* Update pointer */
-               chan->rx_last_bd = (chan->rx_first_bd - 1) & (N_DMA_RX_BUF - 1);
-               /* Update EDA */
-               cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch),
-                          RX_BD_ADDR(ch, chan->rx_last_bd));
-       }
-       return rcvd;
-}
-
-static void tx_dma_stop(pc300_t * card, int ch)
-{
-       void __iomem *scabase = card->hw.scabase;
-       u8 drr_ena_bit = 1 << (5 + 2 * ch);
-       u8 drr_rst_bit = 1 << (1 + 2 * ch);
-
-       /* Disable DMA */
-       cpc_writeb(scabase + DRR, drr_ena_bit);
-       cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
-}
-
-static void rx_dma_stop(pc300_t * card, int ch)
-{
-       void __iomem *scabase = card->hw.scabase;
-       u8 drr_ena_bit = 1 << (4 + 2 * ch);
-       u8 drr_rst_bit = 1 << (2 * ch);
-
-       /* Disable DMA */
-       cpc_writeb(scabase + DRR, drr_ena_bit);
-       cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
-}
-
-static void rx_dma_start(pc300_t * card, int ch)
-{
-       void __iomem *scabase = card->hw.scabase;
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       
-       /* Start DMA */
-       cpc_writel(scabase + DRX_REG(CDAL, ch),
-                  RX_BD_ADDR(ch, chan->rx_first_bd));
-       if (cpc_readl(scabase + DRX_REG(CDAL,ch)) !=
-                                 RX_BD_ADDR(ch, chan->rx_first_bd)) {
-               cpc_writel(scabase + DRX_REG(CDAL, ch),
-                                  RX_BD_ADDR(ch, chan->rx_first_bd));
-       }
-       cpc_writel(scabase + DRX_REG(EDAL, ch),
-                  RX_BD_ADDR(ch, chan->rx_last_bd));
-       cpc_writew(scabase + DRX_REG(BFLL, ch), BD_DEF_LEN);
-       cpc_writeb(scabase + DSR_RX(ch), DSR_DE);
-       if (!(cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
-       cpc_writeb(scabase + DSR_RX(ch), DSR_DE);
-       }
-}
-
-/*************************/
-/***   FALC Routines   ***/
-/*************************/
-static void falc_issue_cmd(pc300_t *card, int ch, u8 cmd)
-{
-       void __iomem *falcbase = card->hw.falcbase;
-       unsigned long i = 0;
-
-       while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) {
-               if (i++ >= PC300_FALC_MAXLOOP) {
-                       printk("%s: FALC command locked(cmd=0x%x).\n",
-                              card->chan[ch].d.name, cmd);
-                       break;
-               }
-       }
-       cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
-}
-
-static void falc_intr_enable(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       /* Interrupt pins are open-drain */
-       cpc_writeb(falcbase + F_REG(IPC, ch),
-                  cpc_readb(falcbase + F_REG(IPC, ch)) & ~IPC_IC0);
-       /* Conters updated each second */
-       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_ECM);
-       /* Enable SEC and ES interrupts  */
-       cpc_writeb(falcbase + F_REG(IMR3, ch),
-                  cpc_readb(falcbase + F_REG(IMR3, ch)) & ~(IMR3_SEC | IMR3_ES));
-       if (conf->fr_mode == PC300_FR_UNFRAMED) {
-               cpc_writeb(falcbase + F_REG(IMR4, ch),
-                          cpc_readb(falcbase + F_REG(IMR4, ch)) & ~(IMR4_LOS));
-       } else {
-               cpc_writeb(falcbase + F_REG(IMR4, ch),
-                          cpc_readb(falcbase + F_REG(IMR4, ch)) &
-                          ~(IMR4_LFA | IMR4_AIS | IMR4_LOS | IMR4_SLIP));
-       }
-       if (conf->media == IF_IFACE_T1) {
-               cpc_writeb(falcbase + F_REG(IMR3, ch),
-                          cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC);
-       } else {
-               cpc_writeb(falcbase + F_REG(IPC, ch),
-                          cpc_readb(falcbase + F_REG(IPC, ch)) | IPC_SCI);
-               if (conf->fr_mode == PC300_FR_UNFRAMED) {
-                       cpc_writeb(falcbase + F_REG(IMR2, ch),
-                                  cpc_readb(falcbase + F_REG(IMR2, ch)) & ~(IMR2_LOS));
-               } else {
-                       cpc_writeb(falcbase + F_REG(IMR2, ch),
-                                  cpc_readb(falcbase + F_REG(IMR2, ch)) &
-                                  ~(IMR2_FAR | IMR2_LFA | IMR2_AIS | IMR2_LOS));
-                       if (pfalc->multiframe_mode) {
-                               cpc_writeb(falcbase + F_REG(IMR2, ch),
-                                          cpc_readb(falcbase + F_REG(IMR2, ch)) & 
-                                          ~(IMR2_T400MS | IMR2_MFAR));
-                       } else {
-                               cpc_writeb(falcbase + F_REG(IMR2, ch),
-                                          cpc_readb(falcbase + F_REG(IMR2, ch)) | 
-                                          IMR2_T400MS | IMR2_MFAR);
-                       }
-               }
-       }
-}
-
-static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
-{
-       void __iomem *falcbase = card->hw.falcbase;
-       u8 tshf = card->chan[ch].falc.offset;
-
-       cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
-                  cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch)) & 
-                       ~(0x80 >> ((timeslot - tshf) & 0x07)));
-       cpc_writeb(falcbase + F_REG((TTR1 + timeslot / 8), ch),
-                  cpc_readb(falcbase + F_REG((TTR1 + timeslot / 8), ch)) | 
-                       (0x80 >> (timeslot & 0x07)));
-       cpc_writeb(falcbase + F_REG((RTR1 + timeslot / 8), ch),
-                  cpc_readb(falcbase + F_REG((RTR1 + timeslot / 8), ch)) | 
-                       (0x80 >> (timeslot & 0x07)));
-}
-
-static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
-{
-       void __iomem *falcbase = card->hw.falcbase;
-       u8 tshf = card->chan[ch].falc.offset;
-
-       cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
-                  cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch)) | 
-                  (0x80 >> ((timeslot - tshf) & 0x07)));
-       cpc_writeb(falcbase + F_REG((TTR1 + timeslot / 8), ch),
-                  cpc_readb(falcbase + F_REG((TTR1 + timeslot / 8), ch)) & 
-                  ~(0x80 >> (timeslot & 0x07)));
-       cpc_writeb(falcbase + F_REG((RTR1 + timeslot / 8), ch),
-                  cpc_readb(falcbase + F_REG((RTR1 + timeslot / 8), ch)) & 
-                  ~(0x80 >> (timeslot & 0x07)));
-}
-
-static void falc_close_all_timeslots(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff);
-       cpc_writeb(falcbase + F_REG(TTR1, ch), 0);
-       cpc_writeb(falcbase + F_REG(RTR1, ch), 0);
-       cpc_writeb(falcbase + F_REG(ICB2, ch), 0xff);
-       cpc_writeb(falcbase + F_REG(TTR2, ch), 0);
-       cpc_writeb(falcbase + F_REG(RTR2, ch), 0);
-       cpc_writeb(falcbase + F_REG(ICB3, ch), 0xff);
-       cpc_writeb(falcbase + F_REG(TTR3, ch), 0);
-       cpc_writeb(falcbase + F_REG(RTR3, ch), 0);
-       if (conf->media == IF_IFACE_E1) {
-               cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff);
-               cpc_writeb(falcbase + F_REG(TTR4, ch), 0);
-               cpc_writeb(falcbase + F_REG(RTR4, ch), 0);
-       }
-}
-
-static void falc_open_all_timeslots(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       cpc_writeb(falcbase + F_REG(ICB1, ch), 0);
-       if (conf->fr_mode == PC300_FR_UNFRAMED) {
-               cpc_writeb(falcbase + F_REG(TTR1, ch), 0xff);
-               cpc_writeb(falcbase + F_REG(RTR1, ch), 0xff);
-       } else {
-               /* Timeslot 0 is never enabled */
-               cpc_writeb(falcbase + F_REG(TTR1, ch), 0x7f);
-               cpc_writeb(falcbase + F_REG(RTR1, ch), 0x7f);
-       }
-       cpc_writeb(falcbase + F_REG(ICB2, ch), 0);
-       cpc_writeb(falcbase + F_REG(TTR2, ch), 0xff);
-       cpc_writeb(falcbase + F_REG(RTR2, ch), 0xff);
-       cpc_writeb(falcbase + F_REG(ICB3, ch), 0);
-       cpc_writeb(falcbase + F_REG(TTR3, ch), 0xff);
-       cpc_writeb(falcbase + F_REG(RTR3, ch), 0xff);
-       if (conf->media == IF_IFACE_E1) {
-               cpc_writeb(falcbase + F_REG(ICB4, ch), 0);
-               cpc_writeb(falcbase + F_REG(TTR4, ch), 0xff);
-               cpc_writeb(falcbase + F_REG(RTR4, ch), 0xff);
-       } else {
-               cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff);
-               cpc_writeb(falcbase + F_REG(TTR4, ch), 0x80);
-               cpc_writeb(falcbase + F_REG(RTR4, ch), 0x80);
-       }
-}
-
-static void falc_init_timeslot(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       int tslot;
-
-       for (tslot = 0; tslot < pfalc->num_channels; tslot++) {
-               if (conf->tslot_bitmap & (1 << tslot)) {
-                       // Channel enabled
-                       falc_open_timeslot(card, ch, tslot + 1);
-               } else {
-                       // Channel disabled
-                       falc_close_timeslot(card, ch, tslot + 1);
-               }
-       }
-}
-
-static void falc_enable_comm(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-
-       if (pfalc->full_bandwidth) {
-               falc_open_all_timeslots(card, ch);
-       } else {
-               falc_init_timeslot(card, ch);
-       }
-       // CTS/DCD ON
-       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
-                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) &
-                  ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
-}
-
-static void falc_disable_comm(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-
-       if (pfalc->loop_active != 2) {
-               falc_close_all_timeslots(card, ch);
-       }
-       // CTS/DCD OFF
-       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
-                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) |
-                  ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
-}
-
-static void falc_init_t1(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-       u8 dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
-
-       /* Switch to T1 mode (PCM 24) */
-       cpc_writeb(falcbase + F_REG(FMR1, ch), FMR1_PMOD);
-
-       /* Wait 20 us for setup */
-       udelay(20);
-
-       /* Transmit Buffer Size (1 frame) */
-       cpc_writeb(falcbase + F_REG(SIC1, ch), SIC1_XBS0);
-
-       /* Clock mode */
-       if (conf->phys_settings.clock_type == CLOCK_INT) { /* Master mode */
-               cpc_writeb(falcbase + F_REG(LIM0, ch),
-                          cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS);
-       } else { /* Slave mode */
-               cpc_writeb(falcbase + F_REG(LIM0, ch),
-                          cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS);
-               cpc_writeb(falcbase + F_REG(LOOP, ch),
-                          cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_RTM);
-       }
-
-       cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI);
-       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                  cpc_readb(falcbase + F_REG(FMR0, ch)) &
-                  ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1));
-
-       switch (conf->lcode) {
-               case PC300_LC_AMI:
-                       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                                  cpc_readb(falcbase + F_REG(FMR0, ch)) |
-                                  FMR0_XC1 | FMR0_RC1);
-                       /* Clear Channel register to ON for all channels */
-                       cpc_writeb(falcbase + F_REG(CCB1, ch), 0xff);
-                       cpc_writeb(falcbase + F_REG(CCB2, ch), 0xff);
-                       cpc_writeb(falcbase + F_REG(CCB3, ch), 0xff);
-                       break;
-
-               case PC300_LC_B8ZS:
-                       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                                  cpc_readb(falcbase + F_REG(FMR0, ch)) |
-                                  FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1);
-                       break;
-
-               case PC300_LC_NRZ:
-                       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                                  cpc_readb(falcbase + F_REG(FMR0, ch)) | 0x00);
-                       break;
-       }
-
-       cpc_writeb(falcbase + F_REG(LIM0, ch),
-                  cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_ELOS);
-       cpc_writeb(falcbase + F_REG(LIM0, ch),
-                  cpc_readb(falcbase + F_REG(LIM0, ch)) & ~(LIM0_SCL1 | LIM0_SCL0));
-       /* Set interface mode to 2 MBPS */
-       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD);
-
-       switch (conf->fr_mode) {
-               case PC300_FR_ESF:
-                       pfalc->multiframe_mode = 0;
-                       cpc_writeb(falcbase + F_REG(FMR4, ch),
-                                  cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_FM1);
-                       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | 
-                                  FMR1_CRC | FMR1_EDL);
-                       cpc_writeb(falcbase + F_REG(XDL1, ch), 0);
-                       cpc_writeb(falcbase + F_REG(XDL2, ch), 0);
-                       cpc_writeb(falcbase + F_REG(XDL3, ch), 0);
-                       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                                  cpc_readb(falcbase + F_REG(FMR0, ch)) & ~FMR0_SRAF);
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2,ch)) | FMR2_MCSP | FMR2_SSP);
-                       break;
-
-               case PC300_FR_D4:
-                       pfalc->multiframe_mode = 1;
-                       cpc_writeb(falcbase + F_REG(FMR4, ch),
-                                  cpc_readb(falcbase + F_REG(FMR4, ch)) &
-                                  ~(FMR4_FM1 | FMR4_FM0));
-                       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                                  cpc_readb(falcbase + F_REG(FMR0, ch)) | FMR0_SRAF);
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_SSP);
-                       break;
-       }
-
-       /* Enable Automatic Resynchronization */
-       cpc_writeb(falcbase + F_REG(FMR4, ch),
-                  cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_AUTO);
-
-       /* Transmit Automatic Remote Alarm */
-       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA);
-
-       /* Channel translation mode 1 : one to one */
-       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_CTM);
-
-       /* No signaling */
-       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_SIGM);
-       cpc_writeb(falcbase + F_REG(FMR5, ch),
-                  cpc_readb(falcbase + F_REG(FMR5, ch)) &
-                  ~(FMR5_EIBR | FMR5_SRS));
-       cpc_writeb(falcbase + F_REG(CCR1, ch), 0);
-
-       cpc_writeb(falcbase + F_REG(LIM1, ch),
-                  cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1);
-
-       switch (conf->lbo) {
-                       /* Provides proper Line Build Out */
-               case PC300_LBO_0_DB:
-                       cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja));
-                       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x5a);
-                       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x8f);
-                       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
-                       break;
-               case PC300_LBO_7_5_DB:
-                       cpc_writeb(falcbase + F_REG(LIM2, ch), (0x40 | LIM2_LOS1 | dja));
-                       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x11);
-                       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x02);
-                       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
-                       break;
-               case PC300_LBO_15_DB:
-                       cpc_writeb(falcbase + F_REG(LIM2, ch), (0x80 | LIM2_LOS1 | dja));
-                       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x8e);
-                       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01);
-                       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
-                       break;
-               case PC300_LBO_22_5_DB:
-                       cpc_writeb(falcbase + F_REG(LIM2, ch), (0xc0 | LIM2_LOS1 | dja));
-                       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x09);
-                       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01);
-                       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
-                       break;
-       }
-
-       /* Transmit Clock-Slot Offset */
-       cpc_writeb(falcbase + F_REG(XC0, ch),
-                  cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01);
-       /* Transmit Time-slot Offset */
-       cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e);
-       /* Receive  Clock-Slot offset */
-       cpc_writeb(falcbase + F_REG(RC0, ch), 0x05);
-       /* Receive  Time-slot offset */
-       cpc_writeb(falcbase + F_REG(RC1, ch), 0x00);
-
-       /* LOS Detection after 176 consecutive 0s */
-       cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a);
-       /* LOS Recovery after 22 ones in the time window of PCD */
-       cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15);
-
-       cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f);
-
-       if (conf->fr_mode == PC300_FR_ESF_JAPAN) {
-               cpc_writeb(falcbase + F_REG(RC1, ch),
-                          cpc_readb(falcbase + F_REG(RC1, ch)) | 0x80);
-       }
-
-       falc_close_all_timeslots(card, ch);
-}
-
-static void falc_init_e1(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-       u8 dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
-
-       /* Switch to E1 mode (PCM 30) */
-       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_PMOD);
-
-       /* Clock mode */
-       if (conf->phys_settings.clock_type == CLOCK_INT) { /* Master mode */
-               cpc_writeb(falcbase + F_REG(LIM0, ch),
-                          cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS);
-       } else { /* Slave mode */
-               cpc_writeb(falcbase + F_REG(LIM0, ch),
-                          cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS);
-       }
-       cpc_writeb(falcbase + F_REG(LOOP, ch),
-                  cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_SFM);
-
-       cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI);
-       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                  cpc_readb(falcbase + F_REG(FMR0, ch)) &
-                  ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1));
-
-       switch (conf->lcode) {
-               case PC300_LC_AMI:
-                       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                                  cpc_readb(falcbase + F_REG(FMR0, ch)) |
-                                  FMR0_XC1 | FMR0_RC1);
-                       break;
-
-               case PC300_LC_HDB3:
-                       cpc_writeb(falcbase + F_REG(FMR0, ch),
-                                  cpc_readb(falcbase + F_REG(FMR0, ch)) |
-                                  FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1);
-                       break;
-
-               case PC300_LC_NRZ:
-                       break;
-       }
-
-       cpc_writeb(falcbase + F_REG(LIM0, ch),
-                  cpc_readb(falcbase + F_REG(LIM0, ch)) & ~(LIM0_SCL1 | LIM0_SCL0));
-       /* Set interface mode to 2 MBPS */
-       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD);
-
-       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x18);
-       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x03);
-       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x00);
-
-       switch (conf->fr_mode) {
-               case PC300_FR_MF_CRC4:
-                       pfalc->multiframe_mode = 1;
-                       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_XFS);
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_RFS1);
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS0);
-                       cpc_writeb(falcbase + F_REG(FMR3, ch),
-                                  cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_EXTIW);
-
-                       /* MultiFrame Resynchronization */
-                       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_MFCS);
-
-                       /* Automatic Loss of Multiframe > 914 CRC errors */
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_ALMF);
-
-                       /* S1 and SI1/SI2 spare Bits set to 1 */
-                       cpc_writeb(falcbase + F_REG(XSP, ch),
-                                  cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_AXS);
-                       cpc_writeb(falcbase + F_REG(XSP, ch),
-                                  cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_EBP);
-                       cpc_writeb(falcbase + F_REG(XSP, ch),
-                                  cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_XS13 | XSP_XS15);
-
-                       /* Automatic Force Resynchronization */
-                       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_AFR);
-
-                       /* Transmit Automatic Remote Alarm */
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA);
-
-                       /* Transmit Spare Bits for National Use (Y, Sn, Sa) */
-                       cpc_writeb(falcbase + F_REG(XSW, ch),
-                                  cpc_readb(falcbase + F_REG(XSW, ch)) |
-                                  XSW_XY0 | XSW_XY1 | XSW_XY2 | XSW_XY3 | XSW_XY4);
-                       break;
-
-               case PC300_FR_MF_NON_CRC4:
-               case PC300_FR_D4:
-                       pfalc->multiframe_mode = 0;
-                       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_XFS);
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & 
-                                  ~(FMR2_RFS1 | FMR2_RFS0));
-                       cpc_writeb(falcbase + F_REG(XSW, ch),
-                                  cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XSIS);
-                       cpc_writeb(falcbase + F_REG(XSP, ch),
-                                  cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_XSIF);
-
-                       /* Automatic Force Resynchronization */
-                       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_AFR);
-
-                       /* Transmit Automatic Remote Alarm */
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA);
-
-                       /* Transmit Spare Bits for National Use (Y, Sn, Sa) */
-                       cpc_writeb(falcbase + F_REG(XSW, ch),
-                                  cpc_readb(falcbase + F_REG(XSW, ch)) |
-                                  XSW_XY0 | XSW_XY1 | XSW_XY2 | XSW_XY3 | XSW_XY4);
-                       break;
-
-               case PC300_FR_UNFRAMED:
-                       pfalc->multiframe_mode = 0;
-                       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_XFS);
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & 
-                                  ~(FMR2_RFS1 | FMR2_RFS0));
-                       cpc_writeb(falcbase + F_REG(XSP, ch),
-                                  cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_TT0);
-                       cpc_writeb(falcbase + F_REG(XSW, ch),
-                                  cpc_readb(falcbase + F_REG(XSW, ch)) & 
-                                  ~(XSW_XTM|XSW_XY0|XSW_XY1|XSW_XY2|XSW_XY3|XSW_XY4));
-                       cpc_writeb(falcbase + F_REG(TSWM, ch), 0xff);
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) |
-                                  (FMR2_RTM | FMR2_DAIS));
-                       cpc_writeb(falcbase + F_REG(FMR2, ch),
-                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_AXRA);
-                       cpc_writeb(falcbase + F_REG(FMR1, ch),
-                                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_AFR);
-                       pfalc->sync = 1;
-                       cpc_writeb(falcbase + card->hw.cpld_reg2,
-                                  cpc_readb(falcbase + card->hw.cpld_reg2) |
-                                  (CPLD_REG2_FALC_LED2 << (2 * ch)));
-                       break;
-       }
-
-       /* No signaling */
-       cpc_writeb(falcbase + F_REG(XSP, ch),
-                  cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_CASEN);
-       cpc_writeb(falcbase + F_REG(CCR1, ch), 0);
-
-       cpc_writeb(falcbase + F_REG(LIM1, ch),
-                  cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1);
-       cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja));
-
-       /* Transmit Clock-Slot Offset */
-       cpc_writeb(falcbase + F_REG(XC0, ch),
-                  cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01);
-       /* Transmit Time-slot Offset */
-       cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e);
-       /* Receive  Clock-Slot offset */
-       cpc_writeb(falcbase + F_REG(RC0, ch), 0x05);
-       /* Receive  Time-slot offset */
-       cpc_writeb(falcbase + F_REG(RC1, ch), 0x00);
-
-       /* LOS Detection after 176 consecutive 0s */
-       cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a);
-       /* LOS Recovery after 22 ones in the time window of PCD */
-       cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15);
-
-       cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f);
-
-       falc_close_all_timeslots(card, ch);
-}
-
-static void falc_init_hdlc(pc300_t * card, int ch)
-{
-       void __iomem *falcbase = card->hw.falcbase;
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-
-       /* Enable transparent data transfer */
-       if (conf->fr_mode == PC300_FR_UNFRAMED) {
-               cpc_writeb(falcbase + F_REG(MODE, ch), 0);
-       } else {
-               cpc_writeb(falcbase + F_REG(MODE, ch),
-                          cpc_readb(falcbase + F_REG(MODE, ch)) |
-                          (MODE_HRAC | MODE_MDS2));
-               cpc_writeb(falcbase + F_REG(RAH2, ch), 0xff);
-               cpc_writeb(falcbase + F_REG(RAH1, ch), 0xff);
-               cpc_writeb(falcbase + F_REG(RAL2, ch), 0xff);
-               cpc_writeb(falcbase + F_REG(RAL1, ch), 0xff);
-       }
-
-       /* Tx/Rx reset  */
-       falc_issue_cmd(card, ch, CMDR_RRES | CMDR_XRES | CMDR_SRES);
-
-       /* Enable interrupt sources */
-       falc_intr_enable(card, ch);
-}
-
-static void te_config(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-       u8 dummy;
-       unsigned long flags;
-
-       memset(pfalc, 0, sizeof(falc_t));
-       switch (conf->media) {
-               case IF_IFACE_T1:
-                       pfalc->num_channels = NUM_OF_T1_CHANNELS;
-                       pfalc->offset = 1;
-                       break;
-               case IF_IFACE_E1:
-                       pfalc->num_channels = NUM_OF_E1_CHANNELS;
-                       pfalc->offset = 0;
-                       break;
-       }
-       if (conf->tslot_bitmap == 0xffffffffUL)
-               pfalc->full_bandwidth = 1;
-       else
-               pfalc->full_bandwidth = 0;
-
-       CPC_LOCK(card, flags);
-       /* Reset the FALC chip */
-       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
-                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) |
-                  (CPLD_REG1_FALC_RESET << (2 * ch)));
-       udelay(10000);
-       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
-                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) &
-                  ~(CPLD_REG1_FALC_RESET << (2 * ch)));
-
-       if (conf->media == IF_IFACE_T1) {
-               falc_init_t1(card, ch);
-       } else {
-               falc_init_e1(card, ch);
-       }
-       falc_init_hdlc(card, ch);
-       if (conf->rx_sens == PC300_RX_SENS_SH) {
-               cpc_writeb(falcbase + F_REG(LIM0, ch),
-                          cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_EQON);
-       } else {
-               cpc_writeb(falcbase + F_REG(LIM0, ch),
-                          cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_EQON);
-       }
-       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
-                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) |
-                  ((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK) << (2 * ch)));
-
-       /* Clear all interrupt registers */
-       dummy = cpc_readb(falcbase + F_REG(FISR0, ch)) +
-               cpc_readb(falcbase + F_REG(FISR1, ch)) +
-               cpc_readb(falcbase + F_REG(FISR2, ch)) +
-               cpc_readb(falcbase + F_REG(FISR3, ch));
-       CPC_UNLOCK(card, flags);
-}
-
-static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       /* Verify LOS */
-       if (frs0 & FRS0_LOS) {
-               if (!pfalc->red_alarm) {
-                       pfalc->red_alarm = 1;
-                       pfalc->los++;
-                       if (!pfalc->blue_alarm) {
-                               // EVENT_FALC_ABNORMAL
-                               if (conf->media == IF_IFACE_T1) {
-                                       /* Disable this interrupt as it may otherwise interfere 
-                                        * with other working boards. */
-                                       cpc_writeb(falcbase + F_REG(IMR0, ch), 
-                                                  cpc_readb(falcbase + F_REG(IMR0, ch))
-                                                  | IMR0_PDEN);
-                               }
-                               falc_disable_comm(card, ch);
-                               // EVENT_FALC_ABNORMAL
-                       }
-               }
-       } else {
-               if (pfalc->red_alarm) {
-                       pfalc->red_alarm = 0;
-                       pfalc->losr++;
-               }
-       }
-
-       if (conf->fr_mode != PC300_FR_UNFRAMED) {
-               /* Verify AIS alarm */
-               if (frs0 & FRS0_AIS) {
-                       if (!pfalc->blue_alarm) {
-                               pfalc->blue_alarm = 1;
-                               pfalc->ais++;
-                               // EVENT_AIS
-                               if (conf->media == IF_IFACE_T1) {
-                                       /* Disable this interrupt as it may otherwise interfere with                       other working boards. */
-                                       cpc_writeb(falcbase + F_REG(IMR0, ch),
-                                                  cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
-                               }
-                               falc_disable_comm(card, ch);
-                               // EVENT_AIS
-                       }
-               } else {
-                       pfalc->blue_alarm = 0;
-               }
-
-               /* Verify LFA */
-               if (frs0 & FRS0_LFA) {
-                       if (!pfalc->loss_fa) {
-                               pfalc->loss_fa = 1;
-                               pfalc->lfa++;
-                               if (!pfalc->blue_alarm && !pfalc->red_alarm) {
-                                       // EVENT_FALC_ABNORMAL
-                                       if (conf->media == IF_IFACE_T1) {
-                                               /* Disable this interrupt as it may otherwise 
-                                                * interfere with other working boards. */
-                                               cpc_writeb(falcbase + F_REG(IMR0, ch),
-                                                          cpc_readb(falcbase + F_REG(IMR0, ch))
-                                                          | IMR0_PDEN);
-                                       }
-                                       falc_disable_comm(card, ch);
-                                       // EVENT_FALC_ABNORMAL
-                               }
-                       }
-               } else {
-                       if (pfalc->loss_fa) {
-                               pfalc->loss_fa = 0;
-                               pfalc->farec++;
-                       }
-               }
-
-               /* Verify LMFA */
-               if (pfalc->multiframe_mode && (frs0 & FRS0_LMFA)) {
-                       /* D4 or CRC4 frame mode */
-                       if (!pfalc->loss_mfa) {
-                               pfalc->loss_mfa = 1;
-                               pfalc->lmfa++;
-                               if (!pfalc->blue_alarm && !pfalc->red_alarm &&
-                                   !pfalc->loss_fa) {
-                                       // EVENT_FALC_ABNORMAL
-                                       if (conf->media == IF_IFACE_T1) {
-                                               /* Disable this interrupt as it may otherwise 
-                                                * interfere with other working boards. */
-                                               cpc_writeb(falcbase + F_REG(IMR0, ch),
-                                                          cpc_readb(falcbase + F_REG(IMR0, ch))
-                                                          | IMR0_PDEN);
-                                       }
-                                       falc_disable_comm(card, ch);
-                                       // EVENT_FALC_ABNORMAL
-                               }
-                       }
-               } else {
-                       pfalc->loss_mfa = 0;
-               }
-
-               /* Verify Remote Alarm */
-               if (frs0 & FRS0_RRA) {
-                       if (!pfalc->yellow_alarm) {
-                               pfalc->yellow_alarm = 1;
-                               pfalc->rai++;
-                               if (pfalc->sync) {
-                                       // EVENT_RAI
-                                       falc_disable_comm(card, ch);
-                                       // EVENT_RAI
-                               }
-                       }
-               } else {
-                       pfalc->yellow_alarm = 0;
-               }
-       } /* if !PC300_UNFRAMED */
-
-       if (pfalc->red_alarm || pfalc->loss_fa ||
-           pfalc->loss_mfa || pfalc->blue_alarm) {
-               if (pfalc->sync) {
-                       pfalc->sync = 0;
-                       chan->d.line_off++;
-                       cpc_writeb(falcbase + card->hw.cpld_reg2,
-                                  cpc_readb(falcbase + card->hw.cpld_reg2) &
-                                  ~(CPLD_REG2_FALC_LED2 << (2 * ch)));
-               }
-       } else {
-               if (!pfalc->sync) {
-                       pfalc->sync = 1;
-                       chan->d.line_on++;
-                       cpc_writeb(falcbase + card->hw.cpld_reg2,
-                                  cpc_readb(falcbase + card->hw.cpld_reg2) |
-                                  (CPLD_REG2_FALC_LED2 << (2 * ch)));
-               }
-       }
-
-       if (pfalc->sync && !pfalc->yellow_alarm) {
-               if (!pfalc->active) {
-                       // EVENT_FALC_NORMAL
-                       if (pfalc->loop_active) {
-                               return;
-                       }
-                       if (conf->media == IF_IFACE_T1) {
-                               cpc_writeb(falcbase + F_REG(IMR0, ch),
-                                          cpc_readb(falcbase + F_REG(IMR0, ch)) & ~IMR0_PDEN);
-                       }
-                       falc_enable_comm(card, ch);
-                       // EVENT_FALC_NORMAL
-                       pfalc->active = 1;
-               }
-       } else {
-               if (pfalc->active) {
-                       pfalc->active = 0;
-               }
-       }
-}
-
-static void falc_update_stats(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-       u16 counter;
-
-       counter = cpc_readb(falcbase + F_REG(FECL, ch));
-       counter |= cpc_readb(falcbase + F_REG(FECH, ch)) << 8;
-       pfalc->fec += counter;
-
-       counter = cpc_readb(falcbase + F_REG(CVCL, ch));
-       counter |= cpc_readb(falcbase + F_REG(CVCH, ch)) << 8;
-       pfalc->cvc += counter;
-
-       counter = cpc_readb(falcbase + F_REG(CECL, ch));
-       counter |= cpc_readb(falcbase + F_REG(CECH, ch)) << 8;
-       pfalc->cec += counter;
-
-       counter = cpc_readb(falcbase + F_REG(EBCL, ch));
-       counter |= cpc_readb(falcbase + F_REG(EBCH, ch)) << 8;
-       pfalc->ebc += counter;
-
-       if (cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) {
-               mdelay(10);
-               counter = cpc_readb(falcbase + F_REG(BECL, ch));
-               counter |= cpc_readb(falcbase + F_REG(BECH, ch)) << 8;
-               pfalc->bec += counter;
-
-               if (((conf->media == IF_IFACE_T1) &&
-                    (cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_LLBAD) &&
-                    (!(cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_PDEN))) ||
-                   ((conf->media == IF_IFACE_E1) &&
-                    (cpc_readb(falcbase + F_REG(RSP, ch)) & RSP_LLBAD))) {
-                       pfalc->prbs = 2;
-               } else {
-                       pfalc->prbs = 1;
-               }
-       }
-}
-
-/*----------------------------------------------------------------------------
- * falc_remote_loop
- *----------------------------------------------------------------------------
- * Description:        In the remote loopback mode the clock and data recovered
- *             from the line inputs RL1/2 or RDIP/RDIN are routed back
- *             to the line outputs XL1/2 or XDOP/XDON via the analog
- *             transmitter. As in normal mode they are processed by
- *             the synchronizer and then sent to the system interface.
- *----------------------------------------------------------------------------
- */
-static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (loop_on) {
-               // EVENT_FALC_ABNORMAL
-               if (conf->media == IF_IFACE_T1) {
-                       /* Disable this interrupt as it may otherwise interfere with 
-                        * other working boards. */
-                       cpc_writeb(falcbase + F_REG(IMR0, ch),
-                                  cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
-               }
-               falc_disable_comm(card, ch);
-               // EVENT_FALC_ABNORMAL
-               cpc_writeb(falcbase + F_REG(LIM1, ch),
-                          cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RL);
-               pfalc->loop_active = 1;
-       } else {
-               cpc_writeb(falcbase + F_REG(LIM1, ch),
-                          cpc_readb(falcbase + F_REG(LIM1, ch)) & ~LIM1_RL);
-               pfalc->sync = 0;
-               cpc_writeb(falcbase + card->hw.cpld_reg2,
-                          cpc_readb(falcbase + card->hw.cpld_reg2) &
-                          ~(CPLD_REG2_FALC_LED2 << (2 * ch)));
-               pfalc->active = 0;
-               falc_issue_cmd(card, ch, CMDR_XRES);
-               pfalc->loop_active = 0;
-       }
-}
-
-/*----------------------------------------------------------------------------
- * falc_local_loop
- *----------------------------------------------------------------------------
- * Description: The local loopback mode disconnects the receive lines 
- *             RL1/RL2 resp. RDIP/RDIN from the receiver. Instead of the
- *             signals coming from the line the data provided by system
- *             interface are routed through the analog receiver back to
- *             the system interface. The unipolar bit stream will be
- *             undisturbed transmitted on the line. Receiver and transmitter
- *             coding must be identical.
- *----------------------------------------------------------------------------
- */
-static void falc_local_loop(pc300_t * card, int ch, int loop_on)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (loop_on) {
-               cpc_writeb(falcbase + F_REG(LIM0, ch),
-                          cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_LL);
-               pfalc->loop_active = 1;
-       } else {
-               cpc_writeb(falcbase + F_REG(LIM0, ch),
-                          cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_LL);
-               pfalc->loop_active = 0;
-       }
-}
-
-/*----------------------------------------------------------------------------
- * falc_payload_loop
- *----------------------------------------------------------------------------
- * Description: This routine allows to enable/disable payload loopback.
- *             When the payload loop is activated, the received 192 bits
- *             of payload data will be looped back to the transmit
- *             direction. The framing bits, CRC6 and DL bits are not 
- *             looped. They are originated by the FALC-LH transmitter.
- *----------------------------------------------------------------------------
- */
-static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (loop_on) {
-               // EVENT_FALC_ABNORMAL
-               if (conf->media == IF_IFACE_T1) {
-                       /* Disable this interrupt as it may otherwise interfere with 
-                        * other working boards. */
-                       cpc_writeb(falcbase + F_REG(IMR0, ch),
-                                  cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
-               }
-               falc_disable_comm(card, ch);
-               // EVENT_FALC_ABNORMAL
-               cpc_writeb(falcbase + F_REG(FMR2, ch),
-                          cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_PLB);
-               if (conf->media == IF_IFACE_T1) {
-                       cpc_writeb(falcbase + F_REG(FMR4, ch),
-                                  cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_TM);
-               } else {
-                       cpc_writeb(falcbase + F_REG(FMR5, ch),
-                                  cpc_readb(falcbase + F_REG(FMR5, ch)) | XSP_TT0);
-               }
-               falc_open_all_timeslots(card, ch);
-               pfalc->loop_active = 2;
-       } else {
-               cpc_writeb(falcbase + F_REG(FMR2, ch),
-                          cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_PLB);
-               if (conf->media == IF_IFACE_T1) {
-                       cpc_writeb(falcbase + F_REG(FMR4, ch),
-                                  cpc_readb(falcbase + F_REG(FMR4, ch)) & ~FMR4_TM);
-               } else {
-                       cpc_writeb(falcbase + F_REG(FMR5, ch),
-                                  cpc_readb(falcbase + F_REG(FMR5, ch)) & ~XSP_TT0);
-               }
-               pfalc->sync = 0;
-               cpc_writeb(falcbase + card->hw.cpld_reg2,
-                          cpc_readb(falcbase + card->hw.cpld_reg2) &
-                          ~(CPLD_REG2_FALC_LED2 << (2 * ch)));
-               pfalc->active = 0;
-               falc_issue_cmd(card, ch, CMDR_XRES);
-               pfalc->loop_active = 0;
-       }
-}
-
-/*----------------------------------------------------------------------------
- * turn_off_xlu
- *----------------------------------------------------------------------------
- * Description:        Turns XLU bit off in the proper register
- *----------------------------------------------------------------------------
- */
-static void turn_off_xlu(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (conf->media == IF_IFACE_T1) {
-               cpc_writeb(falcbase + F_REG(FMR5, ch),
-                          cpc_readb(falcbase + F_REG(FMR5, ch)) & ~FMR5_XLU);
-       } else {
-               cpc_writeb(falcbase + F_REG(FMR3, ch),
-                          cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_XLU);
-       }
-}
-
-/*----------------------------------------------------------------------------
- * turn_off_xld
- *----------------------------------------------------------------------------
- * Description: Turns XLD bit off in the proper register
- *----------------------------------------------------------------------------
- */
-static void turn_off_xld(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (conf->media == IF_IFACE_T1) {
-               cpc_writeb(falcbase + F_REG(FMR5, ch),
-                          cpc_readb(falcbase + F_REG(FMR5, ch)) & ~FMR5_XLD);
-       } else {
-               cpc_writeb(falcbase + F_REG(FMR3, ch),
-                          cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_XLD);
-       }
-}
-
-/*----------------------------------------------------------------------------
- * falc_generate_loop_up_code
- *----------------------------------------------------------------------------
- * Description:        This routine writes the proper FALC chip register in order
- *             to generate a LOOP activation code over a T1/E1 line.
- *----------------------------------------------------------------------------
- */
-static void falc_generate_loop_up_code(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (conf->media == IF_IFACE_T1) {
-               cpc_writeb(falcbase + F_REG(FMR5, ch),
-                          cpc_readb(falcbase + F_REG(FMR5, ch)) | FMR5_XLU);
-       } else {
-               cpc_writeb(falcbase + F_REG(FMR3, ch),
-                          cpc_readb(falcbase + F_REG(FMR3, ch)) | FMR3_XLU);
-       }
-       // EVENT_FALC_ABNORMAL
-       if (conf->media == IF_IFACE_T1) {
-               /* Disable this interrupt as it may otherwise interfere with 
-                * other working boards. */
-               cpc_writeb(falcbase + F_REG(IMR0, ch),
-                          cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
-       }
-       falc_disable_comm(card, ch);
-       // EVENT_FALC_ABNORMAL
-       pfalc->loop_gen = 1;
-}
-
-/*----------------------------------------------------------------------------
- * falc_generate_loop_down_code
- *----------------------------------------------------------------------------
- * Description:        This routine writes the proper FALC chip register in order
- *             to generate a LOOP deactivation code over a T1/E1 line.
- *----------------------------------------------------------------------------
- */
-static void falc_generate_loop_down_code(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (conf->media == IF_IFACE_T1) {
-               cpc_writeb(falcbase + F_REG(FMR5, ch),
-                          cpc_readb(falcbase + F_REG(FMR5, ch)) | FMR5_XLD);
-       } else {
-               cpc_writeb(falcbase + F_REG(FMR3, ch),
-                          cpc_readb(falcbase + F_REG(FMR3, ch)) | FMR3_XLD);
-       }
-       pfalc->sync = 0;
-       cpc_writeb(falcbase + card->hw.cpld_reg2,
-                  cpc_readb(falcbase + card->hw.cpld_reg2) &
-                  ~(CPLD_REG2_FALC_LED2 << (2 * ch)));
-       pfalc->active = 0;
-//?    falc_issue_cmd(card, ch, CMDR_XRES);
-       pfalc->loop_gen = 0;
-}
-
-/*----------------------------------------------------------------------------
- * falc_pattern_test
- *----------------------------------------------------------------------------
- * Description:        This routine generates a pattern code and checks
- *             it on the reception side.
- *----------------------------------------------------------------------------
- */
-static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (activate) {
-               pfalc->prbs = 1;
-               pfalc->bec = 0;
-               if (conf->media == IF_IFACE_T1) {
-                       /* Disable local loop activation/deactivation detect */
-                       cpc_writeb(falcbase + F_REG(IMR3, ch),
-                                  cpc_readb(falcbase + F_REG(IMR3, ch)) | IMR3_LLBSC);
-               } else {
-                       /* Disable local loop activation/deactivation detect */
-                       cpc_writeb(falcbase + F_REG(IMR1, ch),
-                                  cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_LLBSC);
-               }
-               /* Activates generation and monitoring of PRBS 
-                * (Pseudo Random Bit Sequence) */
-               cpc_writeb(falcbase + F_REG(LCR1, ch),
-                          cpc_readb(falcbase + F_REG(LCR1, ch)) | LCR1_EPRM | LCR1_XPRBS);
-       } else {
-               pfalc->prbs = 0;
-               /* Deactivates generation and monitoring of PRBS 
-                * (Pseudo Random Bit Sequence) */
-               cpc_writeb(falcbase + F_REG(LCR1, ch),
-                          cpc_readb(falcbase+F_REG(LCR1,ch)) & ~(LCR1_EPRM | LCR1_XPRBS));
-               if (conf->media == IF_IFACE_T1) {
-                       /* Enable local loop activation/deactivation detect */
-                       cpc_writeb(falcbase + F_REG(IMR3, ch),
-                                  cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC);
-               } else {
-                       /* Enable local loop activation/deactivation detect */
-                       cpc_writeb(falcbase + F_REG(IMR1, ch),
-                                  cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_LLBSC);
-               }
-       }
-}
-
-/*----------------------------------------------------------------------------
- * falc_pattern_test_error
- *----------------------------------------------------------------------------
- * Description:        This routine returns the bit error counter value
- *----------------------------------------------------------------------------
- */
-static u16 falc_pattern_test_error(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-
-       return pfalc->bec;
-}
-
-/**********************************/
-/***   Net Interface Routines   ***/
-/**********************************/
-
-static void
-cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx)
-{
-       struct sk_buff *skb;
-
-       if ((skb = dev_alloc_skb(10 + skb_main->len)) == NULL) {
-               printk("%s: out of memory\n", dev->name);
-               return;
-       }
-       skb_put(skb, 10 + skb_main->len);
-
-       skb->dev = dev;
-       skb->protocol = htons(ETH_P_CUST);
-       skb_reset_mac_header(skb);
-       skb->pkt_type = PACKET_HOST;
-       skb->len = 10 + skb_main->len;
-
-       skb_copy_to_linear_data(skb, dev->name, 5);
-       skb->data[5] = '[';
-       skb->data[6] = rx_tx;
-       skb->data[7] = ']';
-       skb->data[8] = ':';
-       skb->data[9] = ' ';
-       skb_copy_from_linear_data(skb_main, &skb->data[10], skb_main->len);
-
-       netif_rx(skb);
-}
-
-static void cpc_tx_timeout(struct net_device *dev)
-{
-       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       int ch = chan->channel;
-       unsigned long flags;
-       u8 ilar;
-
-       dev->stats.tx_errors++;
-       dev->stats.tx_aborted_errors++;
-       CPC_LOCK(card, flags);
-       if ((ilar = cpc_readb(card->hw.scabase + ILAR)) != 0) {
-               printk("%s: ILAR=0x%x\n", dev->name, ilar);
-               cpc_writeb(card->hw.scabase + ILAR, ilar);
-               cpc_writeb(card->hw.scabase + DMER, 0x80);
-       }
-       if (card->hw.type == PC300_TE) {
-               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
-                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) &
-                          ~(CPLD_REG2_FALC_LED1 << (2 * ch)));
-       }
-       dev->trans_start = jiffies; /* prevent tx timeout */
-       CPC_UNLOCK(card, flags);
-       netif_wake_queue(dev);
-}
-
-static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
-{
-       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       int ch = chan->channel;
-       unsigned long flags;
-#ifdef PC300_DEBUG_TX
-       int i;
-#endif
-
-       if (!netif_carrier_ok(dev)) {
-               /* DCD must be OFF: drop packet */
-               dev_kfree_skb(skb);
-               dev->stats.tx_errors++;
-               dev->stats.tx_carrier_errors++;
-               return 0;
-       } else if (cpc_readb(card->hw.scabase + M_REG(ST3, ch)) & ST3_DCD) {
-               printk("%s: DCD is OFF. Going administrative down.\n", dev->name);
-               dev->stats.tx_errors++;
-               dev->stats.tx_carrier_errors++;
-               dev_kfree_skb(skb);
-               netif_carrier_off(dev);
-               CPC_LOCK(card, flags);
-               cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR);
-               if (card->hw.type == PC300_TE) {
-                       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
-                                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & 
-                                                       ~(CPLD_REG2_FALC_LED1 << (2 * ch)));
-               }
-               CPC_UNLOCK(card, flags);
-               netif_wake_queue(dev);
-               return 0;
-       }
-
-       /* Write buffer to DMA buffers */
-       if (dma_buf_write(card, ch, (u8 *)skb->data, skb->len) != 0) {
-//             printk("%s: write error. Dropping TX packet.\n", dev->name);
-               netif_stop_queue(dev);
-               dev_kfree_skb(skb);
-               dev->stats.tx_errors++;
-               dev->stats.tx_dropped++;
-               return 0;
-       }
-#ifdef PC300_DEBUG_TX
-       printk("%s T:", dev->name);
-       for (i = 0; i < skb->len; i++)
-               printk(" %02x", *(skb->data + i));
-       printk("\n");
-#endif
-
-       if (d->trace_on) {
-               cpc_trace(dev, skb, 'T');
-       }
-
-       /* Start transmission */
-       CPC_LOCK(card, flags);
-       /* verify if it has more than one free descriptor */
-       if (card->chan[ch].nfree_tx_bd <= 1) {
-               /* don't have so stop the queue */
-               netif_stop_queue(dev);
-       }
-       cpc_writel(card->hw.scabase + DTX_REG(EDAL, ch),
-                  TX_BD_ADDR(ch, chan->tx_next_bd));
-       cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA);
-       cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE);
-       if (card->hw.type == PC300_TE) {
-               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
-                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) |
-                          (CPLD_REG2_FALC_LED1 << (2 * ch)));
-       }
-       CPC_UNLOCK(card, flags);
-       dev_kfree_skb(skb);
-
-       return 0;
-}
-
-static void cpc_net_rx(struct net_device *dev)
-{
-       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       int ch = chan->channel;
-#ifdef PC300_DEBUG_RX
-       int i;
-#endif
-       int rxb;
-       struct sk_buff *skb;
-
-       while (1) {
-               if ((rxb = dma_get_rx_frame_size(card, ch)) == -1)
-                       return;
-
-               if (!netif_carrier_ok(dev)) {
-                       /* DCD must be OFF: drop packet */
-                   printk("%s : DCD is OFF - drop %d rx bytes\n", dev->name, rxb); 
-                       skb = NULL;
-               } else {
-                       if (rxb > (dev->mtu + 40)) { /* add headers */
-                               printk("%s : MTU exceeded %d\n", dev->name, rxb); 
-                               skb = NULL;
-                       } else {
-                               skb = dev_alloc_skb(rxb);
-                               if (skb == NULL) {
-                                       printk("%s: Memory squeeze!!\n", dev->name);
-                                       return;
-                               }
-                               skb->dev = dev;
-                       }
-               }
-
-               if (((rxb = dma_buf_read(card, ch, skb)) <= 0) || (skb == NULL)) {
-#ifdef PC300_DEBUG_RX
-                       printk("%s: rxb = %x\n", dev->name, rxb);
-#endif
-                       if ((skb == NULL) && (rxb > 0)) {
-                               /* rxb > dev->mtu */
-                               dev->stats.rx_errors++;
-                               dev->stats.rx_length_errors++;
-                               continue;
-                       }
-
-                       if (rxb < 0) {  /* Invalid frame */
-                               rxb = -rxb;
-                               if (rxb & DST_OVR) {
-                                       dev->stats.rx_errors++;
-                                       dev->stats.rx_fifo_errors++;
-                               }
-                               if (rxb & DST_CRC) {
-                                       dev->stats.rx_errors++;
-                                       dev->stats.rx_crc_errors++;
-                               }
-                               if (rxb & (DST_RBIT | DST_SHRT | DST_ABT)) {
-                                       dev->stats.rx_errors++;
-                                       dev->stats.rx_frame_errors++;
-                               }
-                       }
-                       if (skb) {
-                               dev_kfree_skb_irq(skb);
-                       }
-                       continue;
-               }
-
-               dev->stats.rx_bytes += rxb;
-
-#ifdef PC300_DEBUG_RX
-               printk("%s R:", dev->name);
-               for (i = 0; i < skb->len; i++)
-                       printk(" %02x", *(skb->data + i));
-               printk("\n");
-#endif
-               if (d->trace_on) {
-                       cpc_trace(dev, skb, 'R');
-               }
-               dev->stats.rx_packets++;
-               skb->protocol = hdlc_type_trans(skb, dev);
-               netif_rx(skb);
-       }
-}
-
-/************************************/
-/***   PC300 Interrupt Routines   ***/
-/************************************/
-static void sca_tx_intr(pc300dev_t *dev)
-{
-       pc300ch_t *chan = (pc300ch_t *)dev->chan; 
-       pc300_t *card = (pc300_t *)chan->card; 
-       int ch = chan->channel; 
-       volatile pcsca_bd_t __iomem * ptdescr; 
-
-    /* Clean up descriptors from previous transmission */
-       ptdescr = (card->hw.rambase +
-                                               TX_BD_ADDR(ch,chan->tx_first_bd));
-       while ((cpc_readl(card->hw.scabase + DTX_REG(CDAL,ch)) !=
-               TX_BD_ADDR(ch,chan->tx_first_bd)) &&
-              (cpc_readb(&ptdescr->status) & DST_OSB)) {
-               dev->dev->stats.tx_packets++;
-               dev->dev->stats.tx_bytes += cpc_readw(&ptdescr->len);
-               cpc_writeb(&ptdescr->status, DST_OSB);
-               cpc_writew(&ptdescr->len, 0);
-               chan->nfree_tx_bd++;
-               chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1);
-               ptdescr = (card->hw.rambase + TX_BD_ADDR(ch,chan->tx_first_bd));
-    }
-
-#ifdef CONFIG_PC300_MLPPP
-       if (chan->conf.proto == PC300_PROTO_MLPPP) {
-                       cpc_tty_trigger_poll(dev);
-       } else {
-#endif
-       /* Tell the upper layer we are ready to transmit more packets */
-               netif_wake_queue(dev->dev);
-#ifdef CONFIG_PC300_MLPPP
-       }
-#endif
-}
-
-static void sca_intr(pc300_t * card)
-{
-       void __iomem *scabase = card->hw.scabase;
-       volatile u32 status;
-       int ch;
-       int intr_count = 0;
-       unsigned char dsr_rx;
-
-       while ((status = cpc_readl(scabase + ISR0)) != 0) {
-               for (ch = 0; ch < card->hw.nchan; ch++) {
-                       pc300ch_t *chan = &card->chan[ch];
-                       pc300dev_t *d = &chan->d;
-                       struct net_device *dev = d->dev;
-
-                       spin_lock(&card->card_lock);
-
-           /**** Reception ****/
-                       if (status & IR0_DRX((IR0_DMIA | IR0_DMIB), ch)) {
-                               u8 drx_stat = cpc_readb(scabase + DSR_RX(ch));
-
-                               /* Clear RX interrupts */
-                               cpc_writeb(scabase + DSR_RX(ch), drx_stat | DSR_DWE);
-
-#ifdef PC300_DEBUG_INTR
-                               printk ("sca_intr: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x)\n",
-                                        ch, status, drx_stat);
-#endif
-                               if (status & IR0_DRX(IR0_DMIA, ch)) {
-                                       if (drx_stat & DSR_BOF) {
-#ifdef CONFIG_PC300_MLPPP
-                                               if (chan->conf.proto == PC300_PROTO_MLPPP) {
-                                                       /* verify if driver is TTY */
-                                                       if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
-                                                               rx_dma_stop(card, ch);
-                                                       }
-                                                       cpc_tty_receive(d);
-                                                       rx_dma_start(card, ch);
-                                               } else 
-#endif
-                                               {
-                                                       if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
-                                                               rx_dma_stop(card, ch);
-                                                       }
-                                                       cpc_net_rx(dev);
-                                                       /* Discard invalid frames */
-                                                       dev->stats.rx_errors++;
-                                                       dev->stats.rx_over_errors++;
-                                                       chan->rx_first_bd = 0;
-                                                       chan->rx_last_bd = N_DMA_RX_BUF - 1;
-                                                       rx_dma_start(card, ch);
-                                               }
-                                       }
-                               }
-                               if (status & IR0_DRX(IR0_DMIB, ch)) {
-                                       if (drx_stat & DSR_EOM) {
-                                               if (card->hw.type == PC300_TE) {
-                                                       cpc_writeb(card->hw.falcbase +
-                                                                  card->hw.cpld_reg2,
-                                                                  cpc_readb (card->hw.falcbase +
-                                                                       card->hw.cpld_reg2) |
-                                                                  (CPLD_REG2_FALC_LED1 << (2 * ch)));
-                                               }
-#ifdef CONFIG_PC300_MLPPP
-                                               if (chan->conf.proto == PC300_PROTO_MLPPP) {
-                                                       /* verify if driver is TTY */
-                                                       cpc_tty_receive(d);
-                                               } else {
-                                                       cpc_net_rx(dev);
-                                               }
-#else
-                                               cpc_net_rx(dev);
-#endif
-                                               if (card->hw.type == PC300_TE) {
-                                                       cpc_writeb(card->hw.falcbase +
-                                                                  card->hw.cpld_reg2,
-                                                                  cpc_readb (card->hw.falcbase +
-                                                                               card->hw.cpld_reg2) &
-                                                                  ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
-                                               }
-                                       }
-                               }
-                               if (!(dsr_rx = cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
-#ifdef PC300_DEBUG_INTR
-               printk("%s: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x, dsr2=0x%02x)\n",
-                       dev->name, ch, status, drx_stat, dsr_rx);
-#endif
-                                       cpc_writeb(scabase + DSR_RX(ch), (dsr_rx | DSR_DE) & 0xfe);
-                               }
-                       }
-
-           /**** Transmission ****/
-                       if (status & IR0_DTX((IR0_EFT | IR0_DMIA | IR0_DMIB), ch)) {
-                               u8 dtx_stat = cpc_readb(scabase + DSR_TX(ch));
-
-                               /* Clear TX interrupts */
-                               cpc_writeb(scabase + DSR_TX(ch), dtx_stat | DSR_DWE);
-
-#ifdef PC300_DEBUG_INTR
-                               printk ("sca_intr: TX intr chan[%d] (st=0x%08lx, dsr=0x%02x)\n",
-                                        ch, status, dtx_stat);
-#endif
-                               if (status & IR0_DTX(IR0_EFT, ch)) {
-                                       if (dtx_stat & DSR_UDRF) {
-                                               if (cpc_readb (scabase + M_REG(TBN, ch)) != 0) {
-                                                       cpc_writeb(scabase + M_REG(CMD,ch), CMD_TX_BUF_CLR);
-                                               }
-                                               if (card->hw.type == PC300_TE) {
-                                                       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
-                                                                  cpc_readb (card->hw.falcbase + 
-                                                                                  card->hw.cpld_reg2) &
-                                                                  ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
-                                               }
-                                               dev->stats.tx_errors++;
-                                               dev->stats.tx_fifo_errors++;
-                                               sca_tx_intr(d);
-                                       }
-                               }
-                               if (status & IR0_DTX(IR0_DMIA, ch)) {
-                                       if (dtx_stat & DSR_BOF) {
-                                       }
-                               }
-                               if (status & IR0_DTX(IR0_DMIB, ch)) {
-                                       if (dtx_stat & DSR_EOM) {
-                                               if (card->hw.type == PC300_TE) {
-                                                       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
-                                                                  cpc_readb (card->hw.falcbase +
-                                                                                       card->hw.cpld_reg2) &
-                                                                  ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
-                                               }
-                                               sca_tx_intr(d);
-                                       }
-                               }
-                       }
-
-           /**** MSCI ****/
-                       if (status & IR0_M(IR0_RXINTA, ch)) {
-                               u8 st1 = cpc_readb(scabase + M_REG(ST1, ch));
-
-                               /* Clear MSCI interrupts */
-                               cpc_writeb(scabase + M_REG(ST1, ch), st1);
-
-#ifdef PC300_DEBUG_INTR
-                               printk("sca_intr: MSCI intr chan[%d] (st=0x%08lx, st1=0x%02x)\n",
-                                        ch, status, st1);
-#endif
-                               if (st1 & ST1_CDCD) {   /* DCD changed */
-                                       if (cpc_readb(scabase + M_REG(ST3, ch)) & ST3_DCD) {
-                                               printk ("%s: DCD is OFF. Going administrative down.\n",
-                                                        dev->name);
-#ifdef CONFIG_PC300_MLPPP
-                                               if (chan->conf.proto != PC300_PROTO_MLPPP) {
-                                                       netif_carrier_off(dev);
-                                               }
-#else
-                                               netif_carrier_off(dev);
-
-#endif
-                                               card->chan[ch].d.line_off++;
-                                       } else {        /* DCD = 1 */
-                                               printk ("%s: DCD is ON. Going administrative up.\n",
-                                                        dev->name);
-#ifdef CONFIG_PC300_MLPPP
-                                               if (chan->conf.proto != PC300_PROTO_MLPPP)
-                                                       /* verify if driver is not TTY */
-#endif
-                                                       netif_carrier_on(dev);
-                                               card->chan[ch].d.line_on++;
-                                       }
-                               }
-                       }
-                       spin_unlock(&card->card_lock);
-               }
-               if (++intr_count == 10)
-                       /* Too much work at this board. Force exit */
-                       break;
-       }
-}
-
-static void falc_t1_loop_detection(pc300_t *card, int ch, u8 frs1)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
-           !pfalc->loop_gen) {
-               if (frs1 & FRS1_LLBDD) {
-                       // A Line Loop Back Deactivation signal detected
-                       if (pfalc->loop_active) {
-                               falc_remote_loop(card, ch, 0);
-                       }
-               } else {
-                       if ((frs1 & FRS1_LLBAD) &&
-                           ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) {
-                               // A Line Loop Back Activation signal detected  
-                               if (!pfalc->loop_active) {
-                                       falc_remote_loop(card, ch, 1);
-                               }
-                       }
-               }
-       }
-}
-
-static void falc_e1_loop_detection(pc300_t *card, int ch, u8 rsp)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-
-       if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
-           !pfalc->loop_gen) {
-               if (rsp & RSP_LLBDD) {
-                       // A Line Loop Back Deactivation signal detected
-                       if (pfalc->loop_active) {
-                               falc_remote_loop(card, ch, 0);
-                       }
-               } else {
-                       if ((rsp & RSP_LLBAD) &&
-                           ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) {
-                               // A Line Loop Back Activation signal detected  
-                               if (!pfalc->loop_active) {
-                                       falc_remote_loop(card, ch, 1);
-                               }
-                       }
-               }
-       }
-}
-
-static void falc_t1_intr(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-       u8 isr0, isr3, gis;
-       u8 dummy;
-
-       while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) {
-               if (gis & GIS_ISR0) {
-                       isr0 = cpc_readb(falcbase + F_REG(FISR0, ch));
-                       if (isr0 & FISR0_PDEN) {
-                               /* Read the bit to clear the situation */
-                               if (cpc_readb(falcbase + F_REG(FRS1, ch)) &
-                                   FRS1_PDEN) {
-                                       pfalc->pden++;
-                               }
-                       }
-               }
-
-               if (gis & GIS_ISR1) {
-                       dummy = cpc_readb(falcbase + F_REG(FISR1, ch));
-               }
-
-               if (gis & GIS_ISR2) {
-                       dummy = cpc_readb(falcbase + F_REG(FISR2, ch));
-               }
-
-               if (gis & GIS_ISR3) {
-                       isr3 = cpc_readb(falcbase + F_REG(FISR3, ch));
-                       if (isr3 & FISR3_SEC) {
-                               pfalc->sec++;
-                               falc_update_stats(card, ch);
-                               falc_check_status(card, ch,
-                                                 cpc_readb(falcbase + F_REG(FRS0, ch)));
-                       }
-                       if (isr3 & FISR3_ES) {
-                               pfalc->es++;
-                       }
-                       if (isr3 & FISR3_LLBSC) {
-                               falc_t1_loop_detection(card, ch,
-                                                      cpc_readb(falcbase + F_REG(FRS1, ch)));
-                       }
-               }
-       }
-}
-
-static void falc_e1_intr(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       void __iomem *falcbase = card->hw.falcbase;
-       u8 isr1, isr2, isr3, gis, rsp;
-       u8 dummy;
-
-       while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) {
-               rsp = cpc_readb(falcbase + F_REG(RSP, ch));
-
-               if (gis & GIS_ISR0) {
-                       dummy = cpc_readb(falcbase + F_REG(FISR0, ch));
-               }
-               if (gis & GIS_ISR1) {
-                       isr1 = cpc_readb(falcbase + F_REG(FISR1, ch));
-                       if (isr1 & FISR1_XMB) {
-                               if ((pfalc->xmb_cause & 2) &&
-                                   pfalc->multiframe_mode) {
-                                       if (cpc_readb (falcbase + F_REG(FRS0, ch)) & 
-                                                                       (FRS0_LOS | FRS0_AIS | FRS0_LFA)) {
-                                               cpc_writeb(falcbase + F_REG(XSP, ch),
-                                                          cpc_readb(falcbase + F_REG(XSP, ch))
-                                                          & ~XSP_AXS);
-                                       } else {
-                                               cpc_writeb(falcbase + F_REG(XSP, ch),
-                                                          cpc_readb(falcbase + F_REG(XSP, ch))
-                                                          | XSP_AXS);
-                                       }
-                               }
-                               pfalc->xmb_cause = 0;
-                               cpc_writeb(falcbase + F_REG(IMR1, ch),
-                                          cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_XMB);
-                       }
-                       if (isr1 & FISR1_LLBSC) {
-                               falc_e1_loop_detection(card, ch, rsp);
-                       }
-               }
-               if (gis & GIS_ISR2) {
-                       isr2 = cpc_readb(falcbase + F_REG(FISR2, ch));
-                       if (isr2 & FISR2_T400MS) {
-                               cpc_writeb(falcbase + F_REG(XSW, ch),
-                                          cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XRA);
-                       }
-                       if (isr2 & FISR2_MFAR) {
-                               cpc_writeb(falcbase + F_REG(XSW, ch),
-                                          cpc_readb(falcbase + F_REG(XSW, ch)) & ~XSW_XRA);
-                       }
-                       if (isr2 & (FISR2_FAR | FISR2_LFA | FISR2_AIS | FISR2_LOS)) {
-                               pfalc->xmb_cause |= 2;
-                               cpc_writeb(falcbase + F_REG(IMR1, ch),
-                                          cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_XMB);
-                       }
-               }
-               if (gis & GIS_ISR3) {
-                       isr3 = cpc_readb(falcbase + F_REG(FISR3, ch));
-                       if (isr3 & FISR3_SEC) {
-                               pfalc->sec++;
-                               falc_update_stats(card, ch);
-                               falc_check_status(card, ch,
-                                                 cpc_readb(falcbase + F_REG(FRS0, ch)));
-                       }
-                       if (isr3 & FISR3_ES) {
-                               pfalc->es++;
-                       }
-               }
-       }
-}
-
-static void falc_intr(pc300_t * card)
-{
-       int ch;
-
-       for (ch = 0; ch < card->hw.nchan; ch++) {
-               pc300ch_t *chan = &card->chan[ch];
-               pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-
-               if (conf->media == IF_IFACE_T1) {
-                       falc_t1_intr(card, ch);
-               } else {
-                       falc_e1_intr(card, ch);
-               }
-       }
-}
-
-static irqreturn_t cpc_intr(int irq, void *dev_id)
-{
-       pc300_t *card = dev_id;
-       volatile u8 plx_status;
-
-       if (!card) {
-#ifdef PC300_DEBUG_INTR
-               printk("cpc_intr: spurious intr %d\n", irq);
-#endif
-               return IRQ_NONE;                /* spurious intr */
-       }
-
-       if (!card->hw.rambase) {
-#ifdef PC300_DEBUG_INTR
-               printk("cpc_intr: spurious intr2 %d\n", irq);
-#endif
-               return IRQ_NONE;                /* spurious intr */
-       }
-
-       switch (card->hw.type) {
-               case PC300_RSV:
-               case PC300_X21:
-                       sca_intr(card);
-                       break;
-
-               case PC300_TE:
-                       while ( (plx_status = (cpc_readb(card->hw.plxbase + card->hw.intctl_reg) &
-                                (PLX_9050_LINT1_STATUS | PLX_9050_LINT2_STATUS))) != 0) {
-                               if (plx_status & PLX_9050_LINT1_STATUS) {       /* SCA Interrupt */
-                                       sca_intr(card);
-                               }
-                               if (plx_status & PLX_9050_LINT2_STATUS) {       /* FALC Interrupt */
-                                       falc_intr(card);
-                               }
-                       }
-                       break;
-       }
-       return IRQ_HANDLED;
-}
-
-static void cpc_sca_status(pc300_t * card, int ch)
-{
-       u8 ilar;
-       void __iomem *scabase = card->hw.scabase;
-       unsigned long flags;
-
-       tx_dma_buf_check(card, ch);
-       rx_dma_buf_check(card, ch);
-       ilar = cpc_readb(scabase + ILAR);
-       printk ("ILAR=0x%02x, WCRL=0x%02x, PCR=0x%02x, BTCR=0x%02x, BOLR=0x%02x\n",
-                ilar, cpc_readb(scabase + WCRL), cpc_readb(scabase + PCR),
-                cpc_readb(scabase + BTCR), cpc_readb(scabase + BOLR));
-       printk("TX_CDA=0x%08x, TX_EDA=0x%08x\n",
-              cpc_readl(scabase + DTX_REG(CDAL, ch)),
-              cpc_readl(scabase + DTX_REG(EDAL, ch)));
-       printk("RX_CDA=0x%08x, RX_EDA=0x%08x, BFL=0x%04x\n",
-              cpc_readl(scabase + DRX_REG(CDAL, ch)),
-              cpc_readl(scabase + DRX_REG(EDAL, ch)),
-              cpc_readw(scabase + DRX_REG(BFLL, ch)));
-       printk("DMER=0x%02x, DSR_TX=0x%02x, DSR_RX=0x%02x\n",
-              cpc_readb(scabase + DMER), cpc_readb(scabase + DSR_TX(ch)),
-              cpc_readb(scabase + DSR_RX(ch)));
-       printk("DMR_TX=0x%02x, DMR_RX=0x%02x, DIR_TX=0x%02x, DIR_RX=0x%02x\n",
-              cpc_readb(scabase + DMR_TX(ch)), cpc_readb(scabase + DMR_RX(ch)),
-              cpc_readb(scabase + DIR_TX(ch)),
-              cpc_readb(scabase + DIR_RX(ch)));
-       printk("DCR_TX=0x%02x, DCR_RX=0x%02x, FCT_TX=0x%02x, FCT_RX=0x%02x\n",
-              cpc_readb(scabase + DCR_TX(ch)), cpc_readb(scabase + DCR_RX(ch)),
-              cpc_readb(scabase + FCT_TX(ch)),
-              cpc_readb(scabase + FCT_RX(ch)));
-       printk("MD0=0x%02x, MD1=0x%02x, MD2=0x%02x, MD3=0x%02x, IDL=0x%02x\n",
-              cpc_readb(scabase + M_REG(MD0, ch)),
-              cpc_readb(scabase + M_REG(MD1, ch)),
-              cpc_readb(scabase + M_REG(MD2, ch)),
-              cpc_readb(scabase + M_REG(MD3, ch)),
-              cpc_readb(scabase + M_REG(IDL, ch)));
-       printk("CMD=0x%02x, SA0=0x%02x, SA1=0x%02x, TFN=0x%02x, CTL=0x%02x\n",
-              cpc_readb(scabase + M_REG(CMD, ch)),
-              cpc_readb(scabase + M_REG(SA0, ch)),
-              cpc_readb(scabase + M_REG(SA1, ch)),
-              cpc_readb(scabase + M_REG(TFN, ch)),
-              cpc_readb(scabase + M_REG(CTL, ch)));
-       printk("ST0=0x%02x, ST1=0x%02x, ST2=0x%02x, ST3=0x%02x, ST4=0x%02x\n",
-              cpc_readb(scabase + M_REG(ST0, ch)),
-              cpc_readb(scabase + M_REG(ST1, ch)),
-              cpc_readb(scabase + M_REG(ST2, ch)),
-              cpc_readb(scabase + M_REG(ST3, ch)),
-              cpc_readb(scabase + M_REG(ST4, ch)));
-       printk ("CST0=0x%02x, CST1=0x%02x, CST2=0x%02x, CST3=0x%02x, FST=0x%02x\n",
-                cpc_readb(scabase + M_REG(CST0, ch)),
-                cpc_readb(scabase + M_REG(CST1, ch)),
-                cpc_readb(scabase + M_REG(CST2, ch)),
-                cpc_readb(scabase + M_REG(CST3, ch)),
-                cpc_readb(scabase + M_REG(FST, ch)));
-       printk("TRC0=0x%02x, TRC1=0x%02x, RRC=0x%02x, TBN=0x%02x, RBN=0x%02x\n",
-              cpc_readb(scabase + M_REG(TRC0, ch)),
-              cpc_readb(scabase + M_REG(TRC1, ch)),
-              cpc_readb(scabase + M_REG(RRC, ch)),
-              cpc_readb(scabase + M_REG(TBN, ch)),
-              cpc_readb(scabase + M_REG(RBN, ch)));
-       printk("TFS=0x%02x, TNR0=0x%02x, TNR1=0x%02x, RNR=0x%02x\n",
-              cpc_readb(scabase + M_REG(TFS, ch)),
-              cpc_readb(scabase + M_REG(TNR0, ch)),
-              cpc_readb(scabase + M_REG(TNR1, ch)),
-              cpc_readb(scabase + M_REG(RNR, ch)));
-       printk("TCR=0x%02x, RCR=0x%02x, TNR1=0x%02x, RNR=0x%02x\n",
-              cpc_readb(scabase + M_REG(TCR, ch)),
-              cpc_readb(scabase + M_REG(RCR, ch)),
-              cpc_readb(scabase + M_REG(TNR1, ch)),
-              cpc_readb(scabase + M_REG(RNR, ch)));
-       printk("TXS=0x%02x, RXS=0x%02x, EXS=0x%02x, TMCT=0x%02x, TMCR=0x%02x\n",
-              cpc_readb(scabase + M_REG(TXS, ch)),
-              cpc_readb(scabase + M_REG(RXS, ch)),
-              cpc_readb(scabase + M_REG(EXS, ch)),
-              cpc_readb(scabase + M_REG(TMCT, ch)),
-              cpc_readb(scabase + M_REG(TMCR, ch)));
-       printk("IE0=0x%02x, IE1=0x%02x, IE2=0x%02x, IE4=0x%02x, FIE=0x%02x\n",
-              cpc_readb(scabase + M_REG(IE0, ch)),
-              cpc_readb(scabase + M_REG(IE1, ch)),
-              cpc_readb(scabase + M_REG(IE2, ch)),
-              cpc_readb(scabase + M_REG(IE4, ch)),
-              cpc_readb(scabase + M_REG(FIE, ch)));
-       printk("IER0=0x%08x\n", cpc_readl(scabase + IER0));
-
-       if (ilar != 0) {
-               CPC_LOCK(card, flags);
-               cpc_writeb(scabase + ILAR, ilar);
-               cpc_writeb(scabase + DMER, 0x80);
-               CPC_UNLOCK(card, flags);
-       }
-}
-
-static void cpc_falc_status(pc300_t * card, int ch)
-{
-       pc300ch_t *chan = &card->chan[ch];
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       unsigned long flags;
-
-       CPC_LOCK(card, flags);
-       printk("CH%d:   %s %s  %d channels\n",
-              ch, (pfalc->sync ? "SYNC" : ""), (pfalc->active ? "ACTIVE" : ""),
-              pfalc->num_channels);
-
-       printk("        pden=%d,  los=%d,  losr=%d,  lfa=%d,  farec=%d\n",
-              pfalc->pden, pfalc->los, pfalc->losr, pfalc->lfa, pfalc->farec);
-       printk("        lmfa=%d,  ais=%d,  sec=%d,  es=%d,  rai=%d\n",
-              pfalc->lmfa, pfalc->ais, pfalc->sec, pfalc->es, pfalc->rai);
-       printk("        bec=%d,  fec=%d,  cvc=%d,  cec=%d,  ebc=%d\n",
-              pfalc->bec, pfalc->fec, pfalc->cvc, pfalc->cec, pfalc->ebc);
-
-       printk("\n");
-       printk("        STATUS: %s  %s  %s  %s  %s  %s\n",
-              (pfalc->red_alarm ? "RED" : ""),
-              (pfalc->blue_alarm ? "BLU" : ""),
-              (pfalc->yellow_alarm ? "YEL" : ""),
-              (pfalc->loss_fa ? "LFA" : ""),
-              (pfalc->loss_mfa ? "LMF" : ""), (pfalc->prbs ? "PRB" : ""));
-       CPC_UNLOCK(card, flags);
-}
-
-static int cpc_change_mtu(struct net_device *dev, int new_mtu)
-{
-       if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU))
-               return -EINVAL;
-       dev->mtu = new_mtu;
-       return 0;
-}
-
-static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       pc300conf_t conf_aux;
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       int ch = chan->channel;
-       void __user *arg = ifr->ifr_data;
-       struct if_settings *settings = &ifr->ifr_settings;
-       void __iomem *scabase = card->hw.scabase;
-
-       if (!capable(CAP_NET_ADMIN))
-               return -EPERM;
-
-       switch (cmd) {
-               case SIOCGPC300CONF:
-#ifdef CONFIG_PC300_MLPPP
-                       if (conf->proto != PC300_PROTO_MLPPP) {
-                               conf->proto = /* FIXME hdlc->proto.id */ 0;
-                       }
-#else
-                       conf->proto = /* FIXME hdlc->proto.id */ 0;
-#endif
-                       memcpy(&conf_aux.conf, conf, sizeof(pc300chconf_t));
-                       memcpy(&conf_aux.hw, &card->hw, sizeof(pc300hw_t));
-                       if (!arg || 
-                               copy_to_user(arg, &conf_aux, sizeof(pc300conf_t))) 
-                               return -EINVAL;
-                       return 0;
-               case SIOCSPC300CONF:
-                       if (!capable(CAP_NET_ADMIN))
-                               return -EPERM;
-                       if (!arg || 
-                               copy_from_user(&conf_aux.conf, arg, sizeof(pc300chconf_t)))
-                               return -EINVAL;
-                       if (card->hw.cpld_id < 0x02 &&
-                           conf_aux.conf.fr_mode == PC300_FR_UNFRAMED) {
-                               /* CPLD_ID < 0x02 doesn't support Unframed E1 */
-                               return -EINVAL;
-                       }
-#ifdef CONFIG_PC300_MLPPP
-                       if (conf_aux.conf.proto == PC300_PROTO_MLPPP) {
-                               if (conf->proto != PC300_PROTO_MLPPP) {
-                                       memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-                                       cpc_tty_init(d);        /* init TTY driver */
-                               }
-                       } else {
-                               if (conf_aux.conf.proto == 0xffff) {
-                                       if (conf->proto == PC300_PROTO_MLPPP){ 
-                                               /* ifdown interface */
-                                               cpc_close(dev);
-                                       }
-                               } else {
-                                       memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-                                       /* FIXME hdlc->proto.id = conf->proto; */
-                               }
-                       }
-#else
-                       memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
-                       /* FIXME hdlc->proto.id = conf->proto; */
-#endif
-                       return 0;
-               case SIOCGPC300STATUS:
-                       cpc_sca_status(card, ch);
-                       return 0;
-               case SIOCGPC300FALCSTATUS:
-                       cpc_falc_status(card, ch);
-                       return 0;
-
-               case SIOCGPC300UTILSTATS:
-                       {
-                               if (!arg) {     /* clear statistics */
-                                       memset(&dev->stats, 0, sizeof(dev->stats));
-                                       if (card->hw.type == PC300_TE) {
-                                               memset(&chan->falc, 0, sizeof(falc_t));
-                                       }
-                               } else {
-                                       pc300stats_t pc300stats;
-
-                                       memset(&pc300stats, 0, sizeof(pc300stats_t));
-                                       pc300stats.hw_type = card->hw.type;
-                                       pc300stats.line_on = card->chan[ch].d.line_on;
-                                       pc300stats.line_off = card->chan[ch].d.line_off;
-                                       memcpy(&pc300stats.gen_stats, &dev->stats,
-                                              sizeof(dev->stats));
-                                       if (card->hw.type == PC300_TE)
-                                               memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t));
-                                       if (copy_to_user(arg, &pc300stats, sizeof(pc300stats_t)))
-                                               return -EFAULT;
-                               }
-                               return 0;
-                       }
-
-               case SIOCGPC300UTILSTATUS:
-                       {
-                               struct pc300status pc300status;
-
-                               pc300status.hw_type = card->hw.type;
-                               if (card->hw.type == PC300_TE) {
-                                       pc300status.te_status.sync = chan->falc.sync;
-                                       pc300status.te_status.red_alarm = chan->falc.red_alarm;
-                                       pc300status.te_status.blue_alarm = chan->falc.blue_alarm;
-                                       pc300status.te_status.loss_fa = chan->falc.loss_fa;
-                                       pc300status.te_status.yellow_alarm =chan->falc.yellow_alarm;
-                                       pc300status.te_status.loss_mfa = chan->falc.loss_mfa;
-                                       pc300status.te_status.prbs = chan->falc.prbs;
-                               } else {
-                                       pc300status.gen_status.dcd =
-                                               !(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_DCD);
-                                       pc300status.gen_status.cts =
-                                               !(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_CTS);
-                                       pc300status.gen_status.rts =
-                                               !(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_RTS);
-                                       pc300status.gen_status.dtr =
-                                               !(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_DTR);
-                                       /* There is no DSR in HD64572 */
-                               }
-                               if (!arg ||
-                                   copy_to_user(arg, &pc300status, sizeof(pc300status_t)))
-                                       return -EINVAL;
-                               return 0;
-                       }
-
-               case SIOCSPC300TRACE:
-                       /* Sets/resets a trace_flag for the respective device */
-                       if (!arg || copy_from_user(&d->trace_on, arg,sizeof(unsigned char)))
-                                       return -EINVAL;
-                       return 0;
-
-               case SIOCSPC300LOOPBACK:
-                       {
-                               struct pc300loopback pc300loop;
-
-                               /* TE boards only */
-                               if (card->hw.type != PC300_TE)
-                                       return -EINVAL;
-
-                               if (!arg || 
-                                       copy_from_user(&pc300loop, arg, sizeof(pc300loopback_t)))
-                                               return -EINVAL;
-                               switch (pc300loop.loop_type) {
-                                       case PC300LOCLOOP:      /* Turn the local loop on/off */
-                                               falc_local_loop(card, ch, pc300loop.loop_on);
-                                               return 0;
-
-                                       case PC300REMLOOP:      /* Turn the remote loop on/off */
-                                               falc_remote_loop(card, ch, pc300loop.loop_on);
-                                               return 0;
-
-                                       case PC300PAYLOADLOOP:  /* Turn the payload loop on/off */
-                                               falc_payload_loop(card, ch, pc300loop.loop_on);
-                                               return 0;
-
-                                       case PC300GENLOOPUP:    /* Generate loop UP */
-                                               if (pc300loop.loop_on) {
-                                                       falc_generate_loop_up_code (card, ch);
-                                               } else {
-                                                       turn_off_xlu(card, ch);
-                                               }
-                                               return 0;
-
-                                       case PC300GENLOOPDOWN:  /* Generate loop DOWN */
-                                               if (pc300loop.loop_on) {
-                                                       falc_generate_loop_down_code (card, ch);
-                                               } else {
-                                                       turn_off_xld(card, ch);
-                                               }
-                                               return 0;
-
-                                       default:
-                                               return -EINVAL;
-                               }
-                       }
-
-               case SIOCSPC300PATTERNTEST:
-                       /* Turn the pattern test on/off and show the errors counter */
-                       {
-                               struct pc300patterntst pc300patrntst;
-
-                               /* TE boards only */
-                               if (card->hw.type != PC300_TE)
-                                       return -EINVAL;
-
-                               if (card->hw.cpld_id < 0x02) {
-                                       /* CPLD_ID < 0x02 doesn't support pattern test */
-                                       return -EINVAL;
-                               }
-
-                               if (!arg || 
-                                       copy_from_user(&pc300patrntst,arg,sizeof(pc300patterntst_t)))
-                                               return -EINVAL;
-                               if (pc300patrntst.patrntst_on == 2) {
-                                       if (chan->falc.prbs == 0) {
-                                               falc_pattern_test(card, ch, 1);
-                                       }
-                                       pc300patrntst.num_errors =
-                                               falc_pattern_test_error(card, ch);
-                                       if (copy_to_user(arg, &pc300patrntst,
-                                                        sizeof(pc300patterntst_t)))
-                                                       return -EINVAL;
-                               } else {
-                                       falc_pattern_test(card, ch, pc300patrntst.patrntst_on);
-                               }
-                               return 0;
-                       }
-
-               case SIOCWANDEV:
-                       switch (ifr->ifr_settings.type) {
-                               case IF_GET_IFACE:
-                               {
-                                       const size_t size = sizeof(sync_serial_settings);
-                                       ifr->ifr_settings.type = conf->media;
-                                       if (ifr->ifr_settings.size < size) {
-                                               /* data size wanted */
-                                               ifr->ifr_settings.size = size;
-                                               return -ENOBUFS;
-                                       }
-       
-                                       if (copy_to_user(settings->ifs_ifsu.sync,
-                                                        &conf->phys_settings, size)) {
-                                               return -EFAULT;
-                                       }
-                                       return 0;
-                               }
-
-                               case IF_IFACE_V35:
-                               case IF_IFACE_V24:
-                               case IF_IFACE_X21:
-                               {
-                                       const size_t size = sizeof(sync_serial_settings);
-
-                                       if (!capable(CAP_NET_ADMIN)) {
-                                               return -EPERM;
-                                       }
-                                       /* incorrect data len? */
-                                       if (ifr->ifr_settings.size != size) {
-                                               return -ENOBUFS;
-                                       }
-
-                                       if (copy_from_user(&conf->phys_settings, 
-                                                          settings->ifs_ifsu.sync, size)) {
-                                               return -EFAULT;
-                                       }
-
-                                       if (conf->phys_settings.loopback) {
-                                               cpc_writeb(card->hw.scabase + M_REG(MD2, ch),
-                                                       cpc_readb(card->hw.scabase + M_REG(MD2, ch)) | 
-                                                       MD2_LOOP_MIR);
-                                       }
-                                       conf->media = ifr->ifr_settings.type;
-                                       return 0;
-                               }
-
-                               case IF_IFACE_T1:
-                               case IF_IFACE_E1:
-                               {
-                                       const size_t te_size = sizeof(te1_settings);
-                                       const size_t size = sizeof(sync_serial_settings);
-
-                                       if (!capable(CAP_NET_ADMIN)) {
-                                               return -EPERM;
-                                       }
-
-                                       /* incorrect data len? */
-                                       if (ifr->ifr_settings.size != te_size) {
-                                               return -ENOBUFS;
-                                       }
-
-                                       if (copy_from_user(&conf->phys_settings, 
-                                                          settings->ifs_ifsu.te1, size)) {
-                                               return -EFAULT;
-                                       }/* Ignoring HDLC slot_map for a while */
-                                       
-                                       if (conf->phys_settings.loopback) {
-                                               cpc_writeb(card->hw.scabase + M_REG(MD2, ch),
-                                                       cpc_readb(card->hw.scabase + M_REG(MD2, ch)) | 
-                                                       MD2_LOOP_MIR);
-                                       }
-                                       conf->media = ifr->ifr_settings.type;
-                                       return 0;
-                               }
-                               default:
-                                       return hdlc_ioctl(dev, ifr, cmd);
-                       }
-
-               default:
-                       return hdlc_ioctl(dev, ifr, cmd);
-       }
-}
-
-static int clock_rate_calc(u32 rate, u32 clock, int *br_io)
-{
-       int br, tc;
-       int br_pwr, error;
-
-       *br_io = 0;
-
-       if (rate == 0)
-               return 0;
-
-       for (br = 0, br_pwr = 1; br <= 9; br++, br_pwr <<= 1) {
-               if ((tc = clock / br_pwr / rate) <= 0xff) {
-                       *br_io = br;
-                       break;
-               }
-       }
-
-       if (tc <= 0xff) {
-               error = ((rate - (clock / br_pwr / rate)) / rate) * 1000;
-               /* Errors bigger than +/- 1% won't be tolerated */
-               if (error < -10 || error > 10)
-                       return -1;
-               else
-                       return tc;
-       } else {
-               return -1;
-       }
-}
-
-static int ch_config(pc300dev_t * d)
-{
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
-       pc300_t *card = (pc300_t *) chan->card;
-       void __iomem *scabase = card->hw.scabase;
-       void __iomem *plxbase = card->hw.plxbase;
-       int ch = chan->channel;
-       u32 clkrate = chan->conf.phys_settings.clock_rate;
-       u32 clktype = chan->conf.phys_settings.clock_type;
-       u16 encoding = chan->conf.proto_settings.encoding;
-       u16 parity = chan->conf.proto_settings.parity;
-       u8 md0, md2;
-
-       /* Reset the channel */
-       cpc_writeb(scabase + M_REG(CMD, ch), CMD_CH_RST);
-
-       /* Configure the SCA registers */
-       switch (parity) {
-               case PARITY_NONE:
-                       md0 = MD0_BIT_SYNC;
-                       break;
-               case PARITY_CRC16_PR0:
-                       md0 = MD0_CRC16_0|MD0_CRCC0|MD0_BIT_SYNC;
-                       break;
-               case PARITY_CRC16_PR1:
-                       md0 = MD0_CRC16_1|MD0_CRCC0|MD0_BIT_SYNC;
-                       break;
-               case PARITY_CRC32_PR1_CCITT:
-                       md0 = MD0_CRC32|MD0_CRCC0|MD0_BIT_SYNC;
-                       break;
-               case PARITY_CRC16_PR1_CCITT:
-               default:
-                       md0 = MD0_CRC_CCITT|MD0_CRCC0|MD0_BIT_SYNC;
-                       break;
-       }
-       switch (encoding) {
-               case ENCODING_NRZI:
-                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_NRZI;
-                       break;
-               case ENCODING_FM_MARK:  /* FM1 */
-                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_FM1;
-                       break;
-               case ENCODING_FM_SPACE: /* FM0 */
-                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_FM0;
-                       break;
-               case ENCODING_MANCHESTER: /* It's not working... */
-                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_MANCH;
-                       break;
-               case ENCODING_NRZ:
-               default:
-                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_NRZ;
-                       break;
-       }
-       cpc_writeb(scabase + M_REG(MD0, ch), md0);
-       cpc_writeb(scabase + M_REG(MD1, ch), 0);
-       cpc_writeb(scabase + M_REG(MD2, ch), md2);
-       cpc_writeb(scabase + M_REG(IDL, ch), 0x7e);
-       cpc_writeb(scabase + M_REG(CTL, ch), CTL_URSKP | CTL_IDLC);
-
-       /* Configure HW media */
-       switch (card->hw.type) {
-               case PC300_RSV:
-                       if (conf->media == IF_IFACE_V35) {
-                               cpc_writel((plxbase + card->hw.gpioc_reg),
-                                          cpc_readl(plxbase + card->hw.gpioc_reg) | PC300_CHMEDIA_MASK(ch));
-                       } else {
-                               cpc_writel((plxbase + card->hw.gpioc_reg),
-                                          cpc_readl(plxbase + card->hw.gpioc_reg) & ~PC300_CHMEDIA_MASK(ch));
-                       }
-                       break;
-
-               case PC300_X21:
-                       break;
-
-               case PC300_TE:
-                       te_config(card, ch);
-                       break;
-       }
-
-       switch (card->hw.type) {
-               case PC300_RSV:
-               case PC300_X21:
-                       if (clktype == CLOCK_INT || clktype == CLOCK_TXINT) {
-                               int tmc, br;
-
-                               /* Calculate the clkrate parameters */
-                               tmc = clock_rate_calc(clkrate, card->hw.clock, &br);
-                               if (tmc < 0)
-                                       return -EIO;
-                               cpc_writeb(scabase + M_REG(TMCT, ch), tmc);
-                               cpc_writeb(scabase + M_REG(TXS, ch),
-                                          (TXS_DTRXC | TXS_IBRG | br));
-                               if (clktype == CLOCK_INT) {
-                                       cpc_writeb(scabase + M_REG(TMCR, ch), tmc);
-                                       cpc_writeb(scabase + M_REG(RXS, ch), 
-                                                  (RXS_IBRG | br));
-                               } else {
-                                       cpc_writeb(scabase + M_REG(TMCR, ch), 1);
-                                       cpc_writeb(scabase + M_REG(RXS, ch), 0);
-                               }
-                               if (card->hw.type == PC300_X21) {
-                                       cpc_writeb(scabase + M_REG(GPO, ch), 1);
-                                       cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1 | EXS_RES1);
-                               } else {
-                                       cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1);
-                               }
-                       } else {
-                               cpc_writeb(scabase + M_REG(TMCT, ch), 1);
-                               if (clktype == CLOCK_EXT) {
-                                       cpc_writeb(scabase + M_REG(TXS, ch), 
-                                                  TXS_DTRXC);
-                               } else {
-                                       cpc_writeb(scabase + M_REG(TXS, ch), 
-                                                  TXS_DTRXC|TXS_RCLK);
-                               }
-                               cpc_writeb(scabase + M_REG(TMCR, ch), 1);
-                               cpc_writeb(scabase + M_REG(RXS, ch), 0);
-                               if (card->hw.type == PC300_X21) {
-                                       cpc_writeb(scabase + M_REG(GPO, ch), 0);
-                                       cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1 | EXS_RES1);
-                               } else {
-                                       cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1);
-                               }
-                       }
-                       break;
-
-               case PC300_TE:
-                       /* SCA always receives clock from the FALC chip */
-                       cpc_writeb(scabase + M_REG(TMCT, ch), 1);
-                       cpc_writeb(scabase + M_REG(TXS, ch), 0);
-                       cpc_writeb(scabase + M_REG(TMCR, ch), 1);
-                       cpc_writeb(scabase + M_REG(RXS, ch), 0);
-                       cpc_writeb(scabase + M_REG(EXS, ch), 0);
-                       break;
-       }
-
-       /* Enable Interrupts */
-       cpc_writel(scabase + IER0,
-                  cpc_readl(scabase + IER0) |
-                  IR0_M(IR0_RXINTA, ch) |
-                  IR0_DRX(IR0_EFT | IR0_DMIA | IR0_DMIB, ch) |
-                  IR0_DTX(IR0_EFT | IR0_DMIA | IR0_DMIB, ch));
-       cpc_writeb(scabase + M_REG(IE0, ch),
-                  cpc_readl(scabase + M_REG(IE0, ch)) | IE0_RXINTA);
-       cpc_writeb(scabase + M_REG(IE1, ch),
-                  cpc_readl(scabase + M_REG(IE1, ch)) | IE1_CDCD);
-
-       return 0;
-}
-
-static int rx_config(pc300dev_t * d)
-{
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       void __iomem *scabase = card->hw.scabase;
-       int ch = chan->channel;
-
-       cpc_writeb(scabase + DSR_RX(ch), 0);
-
-       /* General RX settings */
-       cpc_writeb(scabase + M_REG(RRC, ch), 0);
-       cpc_writeb(scabase + M_REG(RNR, ch), 16);
-
-       /* Enable reception */
-       cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_CRC_INIT);
-       cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_ENA);
-
-       /* Initialize DMA stuff */
-       chan->rx_first_bd = 0;
-       chan->rx_last_bd = N_DMA_RX_BUF - 1;
-       rx_dma_buf_init(card, ch);
-       cpc_writeb(scabase + DCR_RX(ch), DCR_FCT_CLR);
-       cpc_writeb(scabase + DMR_RX(ch), (DMR_TMOD | DMR_NF));
-       cpc_writeb(scabase + DIR_RX(ch), (DIR_EOM | DIR_BOF));
-
-       /* Start DMA */
-       rx_dma_start(card, ch);
-
-       return 0;
-}
-
-static int tx_config(pc300dev_t * d)
-{
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       void __iomem *scabase = card->hw.scabase;
-       int ch = chan->channel;
-
-       cpc_writeb(scabase + DSR_TX(ch), 0);
-
-       /* General TX settings */
-       cpc_writeb(scabase + M_REG(TRC0, ch), 0);
-       cpc_writeb(scabase + M_REG(TFS, ch), 32);
-       cpc_writeb(scabase + M_REG(TNR0, ch), 20);
-       cpc_writeb(scabase + M_REG(TNR1, ch), 48);
-       cpc_writeb(scabase + M_REG(TCR, ch), 8);
-
-       /* Enable transmission */
-       cpc_writeb(scabase + M_REG(CMD, ch), CMD_TX_CRC_INIT);
-
-       /* Initialize DMA stuff */
-       chan->tx_first_bd = 0;
-       chan->tx_next_bd = 0;
-       tx_dma_buf_init(card, ch);
-       cpc_writeb(scabase + DCR_TX(ch), DCR_FCT_CLR);
-       cpc_writeb(scabase + DMR_TX(ch), (DMR_TMOD | DMR_NF));
-       cpc_writeb(scabase + DIR_TX(ch), (DIR_EOM | DIR_BOF | DIR_UDRF));
-       cpc_writel(scabase + DTX_REG(CDAL, ch), TX_BD_ADDR(ch, chan->tx_first_bd));
-       cpc_writel(scabase + DTX_REG(EDAL, ch), TX_BD_ADDR(ch, chan->tx_next_bd));
-
-       return 0;
-}
-
-static int cpc_attach(struct net_device *dev, unsigned short encoding,
-                     unsigned short parity)
-{
-       pc300dev_t *d = (pc300dev_t *)dev_to_hdlc(dev)->priv;
-       pc300ch_t *chan = (pc300ch_t *)d->chan;
-       pc300_t *card = (pc300_t *)chan->card;
-       pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
-
-       if (card->hw.type == PC300_TE) {
-               if (encoding != ENCODING_NRZ && encoding != ENCODING_NRZI) {
-                       return -EINVAL;
-               }
-       } else {
-               if (encoding != ENCODING_NRZ && encoding != ENCODING_NRZI &&
-                   encoding != ENCODING_FM_MARK && encoding != ENCODING_FM_SPACE) {
-                       /* Driver doesn't support ENCODING_MANCHESTER yet */
-                       return -EINVAL;
-               }
-       }
-
-       if (parity != PARITY_NONE && parity != PARITY_CRC16_PR0 &&
-           parity != PARITY_CRC16_PR1 && parity != PARITY_CRC32_PR1_CCITT &&
-           parity != PARITY_CRC16_PR1_CCITT) {
-               return -EINVAL;
-       }
-
-       conf->proto_settings.encoding = encoding;
-       conf->proto_settings.parity = parity;
-       return 0;
-}
-
-static int cpc_opench(pc300dev_t * d)
-{
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       int ch = chan->channel, rc;
-       void __iomem *scabase = card->hw.scabase;
-
-       rc = ch_config(d);
-       if (rc)
-               return rc;
-
-       rx_config(d);
-
-       tx_config(d);
-
-       /* Assert RTS and DTR */
-       cpc_writeb(scabase + M_REG(CTL, ch),
-                  cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
-
-       return 0;
-}
-
-static void cpc_closech(pc300dev_t * d)
-{
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       falc_t *pfalc = (falc_t *) & chan->falc;
-       int ch = chan->channel;
-
-       cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_CH_RST);
-       rx_dma_stop(card, ch);
-       tx_dma_stop(card, ch);
-
-       if (card->hw.type == PC300_TE) {
-               memset(pfalc, 0, sizeof(falc_t));
-               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
-                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) &
-                          ~((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK |
-                             CPLD_REG2_FALC_LED2) << (2 * ch)));
-               /* Reset the FALC chip */
-               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
-                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) |
-                          (CPLD_REG1_FALC_RESET << (2 * ch)));
-               udelay(10000);
-               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
-                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) &
-                          ~(CPLD_REG1_FALC_RESET << (2 * ch)));
-       }
-}
-
-int cpc_open(struct net_device *dev)
-{
-       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
-       struct ifreq ifr;
-       int result;
-
-#ifdef PC300_DEBUG_OTHER
-       printk("pc300: cpc_open");
-#endif
-
-       result = hdlc_open(dev);
-
-       if (result)
-               return result;
-
-       sprintf(ifr.ifr_name, "%s", dev->name);
-       result = cpc_opench(d);
-       if (result)
-               goto err_out;
-
-       netif_start_queue(dev);
-       return 0;
-
-err_out:
-       hdlc_close(dev);
-       return result;
-}
-
-static int cpc_close(struct net_device *dev)
-{
-       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
-       pc300ch_t *chan = (pc300ch_t *) d->chan;
-       pc300_t *card = (pc300_t *) chan->card;
-       unsigned long flags;
-
-#ifdef PC300_DEBUG_OTHER
-       printk("pc300: cpc_close");
-#endif
-
-       netif_stop_queue(dev);
-
-       CPC_LOCK(card, flags);
-       cpc_closech(d);
-       CPC_UNLOCK(card, flags);
-
-       hdlc_close(dev);
-
-#ifdef CONFIG_PC300_MLPPP
-       if (chan->conf.proto == PC300_PROTO_MLPPP) {
-               cpc_tty_unregister_service(d);
-               chan->conf.proto = 0xffff;
-       }
-#endif
-
-       return 0;
-}
-
-static u32 detect_ram(pc300_t * card)
-{
-       u32 i;
-       u8 data;
-       void __iomem *rambase = card->hw.rambase;
-
-       card->hw.ramsize = PC300_RAMSIZE;
-       /* Let's find out how much RAM is present on this board */
-       for (i = 0; i < card->hw.ramsize; i++) {
-               data = (u8)(i & 0xff);
-               cpc_writeb(rambase + i, data);
-               if (cpc_readb(rambase + i) != data) {
-                       break;
-               }
-       }
-       return i;
-}
-
-static void plx_init(pc300_t * card)
-{
-       struct RUNTIME_9050 __iomem *plx_ctl = card->hw.plxbase;
-
-       /* Reset PLX */
-       cpc_writel(&plx_ctl->init_ctrl,
-                  cpc_readl(&plx_ctl->init_ctrl) | 0x40000000);
-       udelay(10000L);
-       cpc_writel(&plx_ctl->init_ctrl,
-                  cpc_readl(&plx_ctl->init_ctrl) & ~0x40000000);
-
-       /* Reload Config. Registers from EEPROM */
-       cpc_writel(&plx_ctl->init_ctrl,
-                  cpc_readl(&plx_ctl->init_ctrl) | 0x20000000);
-       udelay(10000L);
-       cpc_writel(&plx_ctl->init_ctrl,
-                  cpc_readl(&plx_ctl->init_ctrl) & ~0x20000000);
-
-}
-
-static void show_version(void)
-{
-       char *rcsvers, *rcsdate, *tmp;
-
-       rcsvers = strchr(rcsid, ' ');
-       rcsvers++;
-       tmp = strchr(rcsvers, ' ');
-       *tmp++ = '\0';
-       rcsdate = strchr(tmp, ' ');
-       rcsdate++;
-       tmp = strrchr(rcsdate, ' ');
-       *tmp = '\0';
-       pr_info("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
-}                              /* show_version */
-
-static const struct net_device_ops cpc_netdev_ops = {
-       .ndo_open               = cpc_open,
-       .ndo_stop               = cpc_close,
-       .ndo_tx_timeout         = cpc_tx_timeout,
-       .ndo_set_mac_address    = NULL,
-       .ndo_change_mtu         = cpc_change_mtu,
-       .ndo_do_ioctl           = cpc_ioctl,
-       .ndo_validate_addr      = eth_validate_addr,
-};
-
-static void cpc_init_card(pc300_t * card)
-{
-       int i, devcount = 0;
-       static int board_nbr = 1;
-
-       /* Enable interrupts on the PCI bridge */
-       plx_init(card);
-       cpc_writew(card->hw.plxbase + card->hw.intctl_reg,
-                  cpc_readw(card->hw.plxbase + card->hw.intctl_reg) | 0x0040);
-
-#ifdef USE_PCI_CLOCK
-       /* Set board clock to PCI clock */
-       cpc_writel(card->hw.plxbase + card->hw.gpioc_reg,
-                  cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) | 0x00000004UL);
-       card->hw.clock = PC300_PCI_CLOCK;
-#else
-       /* Set board clock to internal oscillator clock */
-       cpc_writel(card->hw.plxbase + card->hw.gpioc_reg,
-                  cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) & ~0x00000004UL);
-       card->hw.clock = PC300_OSC_CLOCK;
-#endif
-
-       /* Detect actual on-board RAM size */
-       card->hw.ramsize = detect_ram(card);
-
-       /* Set Global SCA-II registers */
-       cpc_writeb(card->hw.scabase + PCR, PCR_PR2);
-       cpc_writeb(card->hw.scabase + BTCR, 0x10);
-       cpc_writeb(card->hw.scabase + WCRL, 0);
-       cpc_writeb(card->hw.scabase + DMER, 0x80);
-
-       if (card->hw.type == PC300_TE) {
-               u8 reg1;
-
-               /* Check CPLD version */
-               reg1 = cpc_readb(card->hw.falcbase + CPLD_REG1);
-               cpc_writeb(card->hw.falcbase + CPLD_REG1, (reg1 + 0x5a));
-               if (cpc_readb(card->hw.falcbase + CPLD_REG1) == reg1) {
-                       /* New CPLD */
-                       card->hw.cpld_id = cpc_readb(card->hw.falcbase + CPLD_ID_REG);
-                       card->hw.cpld_reg1 = CPLD_V2_REG1;
-                       card->hw.cpld_reg2 = CPLD_V2_REG2;
-               } else {
-                       /* old CPLD */
-                       card->hw.cpld_id = 0;
-                       card->hw.cpld_reg1 = CPLD_REG1;
-                       card->hw.cpld_reg2 = CPLD_REG2;
-                       cpc_writeb(card->hw.falcbase + CPLD_REG1, reg1);
-               }
-
-               /* Enable the board's global clock */
-               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
-                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) |
-                          CPLD_REG1_GLOBAL_CLK);
-
-       }
-
-       for (i = 0; i < card->hw.nchan; i++) {
-               pc300ch_t *chan = &card->chan[i];
-               pc300dev_t *d = &chan->d;
-               hdlc_device *hdlc;
-               struct net_device *dev;
-
-               chan->card = card;
-               chan->channel = i;
-               chan->conf.phys_settings.clock_rate = 0;
-               chan->conf.phys_settings.clock_type = CLOCK_EXT;
-               chan->conf.proto_settings.encoding = ENCODING_NRZ;
-               chan->conf.proto_settings.parity = PARITY_CRC16_PR1_CCITT;
-               switch (card->hw.type) {
-                       case PC300_TE:
-                               chan->conf.media = IF_IFACE_T1;
-                               chan->conf.lcode = PC300_LC_B8ZS;
-                               chan->conf.fr_mode = PC300_FR_ESF;
-                               chan->conf.lbo = PC300_LBO_0_DB;
-                               chan->conf.rx_sens = PC300_RX_SENS_SH;
-                               chan->conf.tslot_bitmap = 0xffffffffUL;
-                               break;
-
-                       case PC300_X21:
-                               chan->conf.media = IF_IFACE_X21;
-                               break;
-
-                       case PC300_RSV:
-                       default:
-                               chan->conf.media = IF_IFACE_V35;
-                               break;
-               }
-               chan->conf.proto = IF_PROTO_PPP;
-               chan->tx_first_bd = 0;
-               chan->tx_next_bd = 0;
-               chan->rx_first_bd = 0;
-               chan->rx_last_bd = N_DMA_RX_BUF - 1;
-               chan->nfree_tx_bd = N_DMA_TX_BUF;
-
-               d->chan = chan;
-               d->trace_on = 0;
-               d->line_on = 0;
-               d->line_off = 0;
-
-               dev = alloc_hdlcdev(d);
-               if (dev == NULL)
-                       continue;
-
-               hdlc = dev_to_hdlc(dev);
-               hdlc->xmit = cpc_queue_xmit;
-               hdlc->attach = cpc_attach;
-               d->dev = dev;
-               dev->mem_start = card->hw.ramphys;
-               dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1;
-               dev->irq = card->hw.irq;
-               dev->tx_queue_len = PC300_TX_QUEUE_LEN;
-               dev->mtu = PC300_DEF_MTU;
-
-               dev->netdev_ops = &cpc_netdev_ops;
-               dev->watchdog_timeo = PC300_TX_TIMEOUT;
-
-               if (register_hdlc_device(dev) == 0) {
-                       printk("%s: Cyclades-PC300/", dev->name);
-                       switch (card->hw.type) {
-                               case PC300_TE:
-                                       if (card->hw.bus == PC300_PMC) {
-                                               printk("TE-M");
-                                       } else {
-                                               printk("TE  ");
-                                       }
-                                       break;
-
-                               case PC300_X21:
-                                       printk("X21 ");
-                                       break;
-
-                               case PC300_RSV:
-                               default:
-                                       printk("RSV ");
-                                       break;
-                       }
-                       printk (" #%d, %dKB of RAM at 0x%08x, IRQ%d, channel %d.\n",
-                                board_nbr, card->hw.ramsize / 1024,
-                                card->hw.ramphys, card->hw.irq, i + 1);
-                       devcount++;
-               } else {
-                       printk ("Dev%d on card(0x%08x): unable to allocate i/f name.\n",
-                                i + 1, card->hw.ramphys);
-                       free_netdev(dev);
-                       continue;
-               }
-       }
-       spin_lock_init(&card->card_lock);
-
-       board_nbr++;
-}
-
-static int __devinit
-cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-       int err, eeprom_outdated = 0;
-       u16 device_id;
-       pc300_t *card;
-
-       if ((err = pci_enable_device(pdev)) < 0)
-               return err;
-
-       card = kzalloc(sizeof(pc300_t), GFP_KERNEL);
-       if (card == NULL) {
-               printk("PC300 found at RAM 0x%016llx, "
-                      "but could not allocate card structure.\n",
-                      (unsigned long long)pci_resource_start(pdev, 3));
-               err = -ENOMEM;
-               goto err_disable_dev;
-       }
-
-       err = -ENODEV;
-
-       /* read PCI configuration area */
-       device_id = ent->device;
-       card->hw.irq = pdev->irq;
-       card->hw.iophys = pci_resource_start(pdev, 1);
-       card->hw.iosize = pci_resource_len(pdev, 1);
-       card->hw.scaphys = pci_resource_start(pdev, 2);
-       card->hw.scasize = pci_resource_len(pdev, 2);
-       card->hw.ramphys = pci_resource_start(pdev, 3);
-       card->hw.alloc_ramsize = pci_resource_len(pdev, 3);
-       card->hw.falcphys = pci_resource_start(pdev, 4);
-       card->hw.falcsize = pci_resource_len(pdev, 4);
-       card->hw.plxphys = pci_resource_start(pdev, 5);
-       card->hw.plxsize = pci_resource_len(pdev, 5);
-
-       switch (device_id) {
-               case PCI_DEVICE_ID_PC300_RX_1:
-               case PCI_DEVICE_ID_PC300_TE_1:
-               case PCI_DEVICE_ID_PC300_TE_M_1:
-                       card->hw.nchan = 1;
-                       break;
-
-               case PCI_DEVICE_ID_PC300_RX_2:
-               case PCI_DEVICE_ID_PC300_TE_2:
-               case PCI_DEVICE_ID_PC300_TE_M_2:
-               default:
-                       card->hw.nchan = PC300_MAXCHAN;
-                       break;
-       }
-#ifdef PC300_DEBUG_PCI
-       printk("cpc (bus=0x0%x,pci_id=0x%x,", pdev->bus->number, pdev->devfn);
-       printk("rev_id=%d) IRQ%d\n", pdev->revision, card->hw.irq);
-       printk("cpc:found  ramaddr=0x%08lx plxaddr=0x%08lx "
-              "ctladdr=0x%08lx falcaddr=0x%08lx\n",
-              card->hw.ramphys, card->hw.plxphys, card->hw.scaphys,
-              card->hw.falcphys);
-#endif
-       /* Although we don't use this I/O region, we should
-        * request it from the kernel anyway, to avoid problems
-        * with other drivers accessing it. */
-       if (!request_region(card->hw.iophys, card->hw.iosize, "PLX Registers")) {
-               /* In case we can't allocate it, warn user */
-               printk("WARNING: couldn't allocate I/O region for PC300 board "
-                      "at 0x%08x!\n", card->hw.ramphys);
-       }
-
-       if (card->hw.plxphys) {
-               pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, card->hw.plxphys);
-       } else {
-               eeprom_outdated = 1;
-               card->hw.plxphys = pci_resource_start(pdev, 0);
-               card->hw.plxsize = pci_resource_len(pdev, 0);
-       }
-
-       if (!request_mem_region(card->hw.plxphys, card->hw.plxsize,
-                               "PLX Registers")) {
-               printk("PC300 found at RAM 0x%08x, "
-                      "but could not allocate PLX mem region.\n",
-                      card->hw.ramphys);
-               goto err_release_io;
-       }
-       if (!request_mem_region(card->hw.ramphys, card->hw.alloc_ramsize,
-                               "On-board RAM")) {
-               printk("PC300 found at RAM 0x%08x, "
-                      "but could not allocate RAM mem region.\n",
-                      card->hw.ramphys);
-               goto err_release_plx;
-       }
-       if (!request_mem_region(card->hw.scaphys, card->hw.scasize,
-                               "SCA-II Registers")) {
-               printk("PC300 found at RAM 0x%08x, "
-                      "but could not allocate SCA mem region.\n",
-                      card->hw.ramphys);
-               goto err_release_ram;
-       }
-
-       card->hw.plxbase = ioremap(card->hw.plxphys, card->hw.plxsize);
-       card->hw.rambase = ioremap(card->hw.ramphys, card->hw.alloc_ramsize);
-       card->hw.scabase = ioremap(card->hw.scaphys, card->hw.scasize);
-       switch (device_id) {
-               case PCI_DEVICE_ID_PC300_TE_1:
-               case PCI_DEVICE_ID_PC300_TE_2:
-               case PCI_DEVICE_ID_PC300_TE_M_1:
-               case PCI_DEVICE_ID_PC300_TE_M_2:
-                       request_mem_region(card->hw.falcphys, card->hw.falcsize,
-                                          "FALC Registers");
-                       card->hw.falcbase = ioremap(card->hw.falcphys, card->hw.falcsize);
-                       break;
-
-               case PCI_DEVICE_ID_PC300_RX_1:
-               case PCI_DEVICE_ID_PC300_RX_2:
-               default:
-                       card->hw.falcbase = NULL;
-                       break;
-       }
-
-#ifdef PC300_DEBUG_PCI
-       printk("cpc: relocate ramaddr=0x%08lx plxaddr=0x%08lx "
-              "ctladdr=0x%08lx falcaddr=0x%08lx\n",
-              card->hw.rambase, card->hw.plxbase, card->hw.scabase,
-              card->hw.falcbase);
-#endif
-
-       /* Set PCI drv pointer to the card structure */
-       pci_set_drvdata(pdev, card);
-
-       /* Set board type */
-       switch (device_id) {
-               case PCI_DEVICE_ID_PC300_TE_1:
-               case PCI_DEVICE_ID_PC300_TE_2:
-               case PCI_DEVICE_ID_PC300_TE_M_1:
-               case PCI_DEVICE_ID_PC300_TE_M_2:
-                       card->hw.type = PC300_TE;
-
-                       if ((device_id == PCI_DEVICE_ID_PC300_TE_M_1) ||
-                           (device_id == PCI_DEVICE_ID_PC300_TE_M_2)) {
-                               card->hw.bus = PC300_PMC;
-                               /* Set PLX register offsets */
-                               card->hw.gpioc_reg = 0x54;
-                               card->hw.intctl_reg = 0x4c;
-                       } else {
-                               card->hw.bus = PC300_PCI;
-                               /* Set PLX register offsets */
-                               card->hw.gpioc_reg = 0x50;
-                               card->hw.intctl_reg = 0x4c;
-                       }
-                       break;
-
-               case PCI_DEVICE_ID_PC300_RX_1:
-               case PCI_DEVICE_ID_PC300_RX_2:
-               default:
-                       card->hw.bus = PC300_PCI;
-                       /* Set PLX register offsets */
-                       card->hw.gpioc_reg = 0x50;
-                       card->hw.intctl_reg = 0x4c;
-
-                       if ((cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) & PC300_CTYPE_MASK)) {
-                               card->hw.type = PC300_X21;
-                       } else {
-                               card->hw.type = PC300_RSV;
-                       }
-                       break;
-       }
-
-       /* Allocate IRQ */
-       if (request_irq(card->hw.irq, cpc_intr, IRQF_SHARED, "Cyclades-PC300", card)) {
-               printk ("PC300 found at RAM 0x%08x, but could not allocate IRQ%d.\n",
-                        card->hw.ramphys, card->hw.irq);
-               goto err_io_unmap;
-       }
-
-       cpc_init_card(card);
-
-       if (eeprom_outdated)
-               printk("WARNING: PC300 with outdated EEPROM.\n");
-       return 0;
-
-err_io_unmap:
-       iounmap(card->hw.plxbase);
-       iounmap(card->hw.scabase);
-       iounmap(card->hw.rambase);
-       if (card->hw.type == PC300_TE) {
-               iounmap(card->hw.falcbase);
-               release_mem_region(card->hw.falcphys, card->hw.falcsize);
-       }
-       release_mem_region(card->hw.scaphys, card->hw.scasize);
-err_release_ram:
-       release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize);
-err_release_plx:
-       release_mem_region(card->hw.plxphys, card->hw.plxsize);
-err_release_io:
-       release_region(card->hw.iophys, card->hw.iosize);
-       kfree(card);
-err_disable_dev:
-       pci_disable_device(pdev);
-       return err;
-}
-
-static void __devexit cpc_remove_one(struct pci_dev *pdev)
-{
-       pc300_t *card = pci_get_drvdata(pdev);
-
-       if (card->hw.rambase) {
-               int i;
-
-               /* Disable interrupts on the PCI bridge */
-               cpc_writew(card->hw.plxbase + card->hw.intctl_reg,
-                          cpc_readw(card->hw.plxbase + card->hw.intctl_reg) & ~(0x0040));
-
-               for (i = 0; i < card->hw.nchan; i++) {
-                       unregister_hdlc_device(card->chan[i].d.dev);
-               }
-               iounmap(card->hw.plxbase);
-               iounmap(card->hw.scabase);
-               iounmap(card->hw.rambase);
-               release_mem_region(card->hw.plxphys, card->hw.plxsize);
-               release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize);
-               release_mem_region(card->hw.scaphys, card->hw.scasize);
-               release_region(card->hw.iophys, card->hw.iosize);
-               if (card->hw.type == PC300_TE) {
-                       iounmap(card->hw.falcbase);
-                       release_mem_region(card->hw.falcphys, card->hw.falcsize);
-               }
-               for (i = 0; i < card->hw.nchan; i++)
-                       if (card->chan[i].d.dev)
-                               free_netdev(card->chan[i].d.dev);
-               if (card->hw.irq)
-                       free_irq(card->hw.irq, card);
-               kfree(card);
-               pci_disable_device(pdev);
-       }
-}
-
-static struct pci_driver cpc_driver = {
-       .name           = "pc300",
-       .id_table       = cpc_pci_dev_id,
-       .probe          = cpc_init_one,
-       .remove         = __devexit_p(cpc_remove_one),
-};
-
-static int __init cpc_init(void)
-{
-       show_version();
-       return pci_register_driver(&cpc_driver);
-}
-
-static void __exit cpc_cleanup_module(void)
-{
-       pci_unregister_driver(&cpc_driver);
-}
-
-module_init(cpc_init);
-module_exit(cpc_cleanup_module);
-
-MODULE_DESCRIPTION("Cyclades-PC300 cards driver");
-MODULE_AUTHOR(  "Author: Ivan Passos <ivan@cyclades.com>\r\n"
-                "Maintainer: PC300 Maintainer <pc300@cyclades.com");
-MODULE_LICENSE("GPL");
-
 
+++ /dev/null
-/*
- * pc300_tty.c Cyclades-PC300(tm) TTY Driver.
- *
- * Author:     Regina Kodato <reginak@cyclades.com>
- *
- * Copyright:  (c) 1999-2002 Cyclades Corp.
- *
- *     This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- *   
- *  $Log: pc300_tty.c,v $
- *  Revision 3.7  2002/03/07 14:17:09  henrique
- *  License data fixed
- *
- *  Revision 3.6  2001/12/10 12:29:42  regina
- *  Fix the MLPPP bug
- *
- *  Revision 3.5  2001/10/31 11:20:05  regina
- *  automatic pppd starts
- *
- *  Revision 3.4  2001/08/06 12:01:51  regina
- *  problem in DSR_DE bit
- *
- *  Revision 3.3  2001/07/26 22:58:41  regina
- *  update EDA value
- *
- *  Revision 3.2  2001/07/12 13:11:20  regina
- *  bug fix - DCD-OFF in pc300 tty driver
- *
- *     DMA transmission bug fix
- *  
- *  Revision 3.1  2001/06/22 13:13:02  regina
- *  MLPPP implementation
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/netdevice.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/if.h>
-#include <linux/skbuff.h>
-/* TTY includes */
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "pc300.h"
-
-/* defines and macros */
-/* TTY Global definitions */
-#define        CPC_TTY_NPORTS  8       /* maximum number of the sync tty connections */
-#define        CPC_TTY_MAJOR   CYCLADES_MAJOR  
-#define CPC_TTY_MINOR_START    240     /* minor of the first PC300 interface */
-
-#define CPC_TTY_MAX_MTU        2000    
-
-/* tty interface state */
-#define        CPC_TTY_ST_IDLE 0
-#define CPC_TTY_ST_INIT        1       /* configured with MLPPP and up */
-#define CPC_TTY_ST_OPEN        2       /* opened by application */
-
-#define        CPC_TTY_LOCK(card,flags)\
-       do {\
-               spin_lock_irqsave(&card->card_lock, flags);     \
-       } while (0)
-
-#define CPC_TTY_UNLOCK(card,flags)     \
-       do {\
-               spin_unlock_irqrestore(&card->card_lock, flags);        \
-       } while (0)
-
-//#define      CPC_TTY_DBG(format,a...)        printk(format,##a)
-#define        CPC_TTY_DBG(format,a...)
-
-/* data structures */
-typedef struct _st_cpc_rx_buf {
-       struct _st_cpc_rx_buf   *next;
-       int             size;
-       unsigned char   data[1];
-} st_cpc_rx_buf;
-
-struct st_cpc_rx_list {
-       st_cpc_rx_buf   *first;
-       st_cpc_rx_buf   *last;
-};
-
-typedef        struct _st_cpc_tty_area {
-       int             state;          /* state of the TTY interface */
-       int             num_open;       
-       unsigned int    tty_minor;      /* minor this interface */
-       volatile struct st_cpc_rx_list buf_rx;  /* ptr. to reception buffer */
-       unsigned char*  buf_tx;         /* ptr. to transmission buffer */
-       pc300dev_t*     pc300dev;       /* ptr. to info struct in PC300 driver */
-       unsigned char   name[20];       /* interf. name + "-tty" */
-       struct tty_struct *tty;         
-       struct work_struct tty_tx_work; /* tx work - tx interrupt */
-       struct work_struct tty_rx_work; /* rx work - rx interrupt */
-       } st_cpc_tty_area;
-
-/* TTY data structures */
-static struct tty_driver serial_drv;
-
-/* local variables */
-static st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
-
-static int cpc_tty_cnt = 0;    /* number of intrfaces configured with MLPPP */
-static int cpc_tty_unreg_flag = 0;
-
-/* TTY functions prototype */
-static int cpc_tty_open(struct tty_struct *tty, struct file *flip);
-static void cpc_tty_close(struct tty_struct *tty, struct file *flip);
-static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int cpc_tty_write_room(struct tty_struct *tty);
-static int cpc_tty_chars_in_buffer(struct tty_struct *tty);
-static void cpc_tty_flush_buffer(struct tty_struct *tty);
-static void cpc_tty_hangup(struct tty_struct *tty);
-static void cpc_tty_rx_work(struct work_struct *work);
-static void cpc_tty_tx_work(struct work_struct *work);
-static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len);
-static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
-static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
-static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
-
-static int pc300_tiocmset(struct tty_struct *, unsigned int, unsigned int);
-static int pc300_tiocmget(struct tty_struct *);
-
-/* functions called by PC300 driver */
-void cpc_tty_init(pc300dev_t *dev);
-void cpc_tty_unregister_service(pc300dev_t *pc300dev);
-void cpc_tty_receive(pc300dev_t *pc300dev);
-void cpc_tty_trigger_poll(pc300dev_t *pc300dev);
-
-/*
- * PC300 TTY clear "signal"
- */
-static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char signal)
-{
-       pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; 
-       pc300_t *card = (pc300_t *) pc300chan->card; 
-       int ch = pc300chan->channel; 
-       unsigned long flags; 
-
-       CPC_TTY_DBG("%s-tty: Clear signal %x\n",
-               pc300dev->dev->name, signal);
-       CPC_TTY_LOCK(card, flags); 
-       cpc_writeb(card->hw.scabase + M_REG(CTL,ch), 
-               cpc_readb(card->hw.scabase+M_REG(CTL,ch))& signal);
-       CPC_TTY_UNLOCK(card,flags); 
-}
-
-/*
- * PC300 TTY set "signal" to ON
- */
-static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal)
-{
-       pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; 
-       pc300_t *card = (pc300_t *) pc300chan->card; 
-       int ch = pc300chan->channel; 
-       unsigned long flags; 
-
-       CPC_TTY_DBG("%s-tty: Set signal %x\n",
-               pc300dev->dev->name, signal);
-       CPC_TTY_LOCK(card, flags); 
-       cpc_writeb(card->hw.scabase + M_REG(CTL,ch), 
-               cpc_readb(card->hw.scabase+M_REG(CTL,ch))& ~signal);
-       CPC_TTY_UNLOCK(card,flags); 
-}
-
-
-static const struct tty_operations pc300_ops = {
-       .open = cpc_tty_open,
-       .close = cpc_tty_close,
-       .write = cpc_tty_write,
-       .write_room = cpc_tty_write_room,
-       .chars_in_buffer = cpc_tty_chars_in_buffer,
-       .tiocmset = pc300_tiocmset,
-       .tiocmget = pc300_tiocmget,
-       .flush_buffer = cpc_tty_flush_buffer,
-       .hangup = cpc_tty_hangup,
-};
-
-
-/*
- * PC300 TTY initialization routine
- *
- * This routine is called by the PC300 driver during board configuration 
- * (ioctl=SIOCSP300CONF). At this point the adapter is completely
- * initialized.
- * o verify kernel version (only 2.4.x)
- * o register TTY driver
- * o init cpc_tty_area struct
- */
-void cpc_tty_init(pc300dev_t *pc300dev)
-{
-       unsigned long port;
-       int aux;
-       st_cpc_tty_area * cpc_tty;
-
-       /* hdlcX - X=interface number */
-       port = pc300dev->dev->name[4] - '0';
-       if (port >= CPC_TTY_NPORTS) {
-               printk("%s-tty: invalid interface selected (0-%i): %li",
-                       pc300dev->dev->name,
-                       CPC_TTY_NPORTS-1,port);
-               return;
-       }
-
-       if (cpc_tty_cnt == 0) { /* first TTY connection -> register driver */
-               CPC_TTY_DBG("%s-tty: driver init, major:%i, minor range:%i=%i\n",
-                       pc300dev->dev->name,
-                       CPC_TTY_MAJOR, CPC_TTY_MINOR_START,
-                       CPC_TTY_MINOR_START+CPC_TTY_NPORTS);
-               /* initialize tty driver struct */
-               memset(&serial_drv,0,sizeof(struct tty_driver));
-               serial_drv.magic = TTY_DRIVER_MAGIC;
-               serial_drv.owner = THIS_MODULE;
-               serial_drv.driver_name = "pc300_tty";
-               serial_drv.name = "ttyCP";
-               serial_drv.major = CPC_TTY_MAJOR;
-               serial_drv.minor_start = CPC_TTY_MINOR_START;
-               serial_drv.num = CPC_TTY_NPORTS;
-               serial_drv.type = TTY_DRIVER_TYPE_SERIAL;
-               serial_drv.subtype = SERIAL_TYPE_NORMAL;
-
-               serial_drv.init_termios = tty_std_termios;
-               serial_drv.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-               serial_drv.flags = TTY_DRIVER_REAL_RAW;
-
-               /* interface routines from the upper tty layer to the tty driver */
-               tty_set_operations(&serial_drv, &pc300_ops);
-
-               /* register the TTY driver */
-               if (tty_register_driver(&serial_drv)) { 
-                       printk("%s-tty: Failed to register serial driver! ",
-                               pc300dev->dev->name);
-                       return;
-               } 
-
-               memset((void *)cpc_tty_area, 0,
-                                                               sizeof(st_cpc_tty_area) * CPC_TTY_NPORTS);
-       }
-
-       cpc_tty = &cpc_tty_area[port];
-       
-       if (cpc_tty->state != CPC_TTY_ST_IDLE) {
-               CPC_TTY_DBG("%s-tty: TTY port %i, already in use.\n",
-                               pc300dev->dev->name, port);
-               return;
-       }
-
-       cpc_tty_cnt++;
-       cpc_tty->state = CPC_TTY_ST_INIT; 
-       cpc_tty->num_open= 0;
-       cpc_tty->tty_minor = port + CPC_TTY_MINOR_START;
-       cpc_tty->pc300dev = pc300dev; 
-
-       INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work);
-       INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work);
-       
-       cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = NULL;
-
-       pc300dev->cpc_tty = (void *)cpc_tty; 
-       
-       aux = strlen(pc300dev->dev->name);
-       memcpy(cpc_tty->name, pc300dev->dev->name, aux);
-       memcpy(&cpc_tty->name[aux], "-tty", 5);
-       
-       cpc_open(pc300dev->dev);
-       cpc_tty_signal_off(pc300dev, CTL_DTR);
-
-       CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n",
-                       cpc_tty->name,CPC_TTY_MAJOR,cpc_tty->tty_minor); 
-       return; 
-} 
-
-/*
- * PC300 TTY OPEN routine
- *
- * This routine is called by the tty driver to open the interface 
- * o verify minor
- * o allocate buffer to Rx and Tx
- */
-static int cpc_tty_open(struct tty_struct *tty, struct file *flip)
-{
-       int port ;
-       st_cpc_tty_area *cpc_tty;
-
-       if (!tty) { 
-               return -ENODEV;
-       } 
-
-       port = tty->index;
-
-       if ((port < 0) || (port >= CPC_TTY_NPORTS)){ 
-               CPC_TTY_DBG("pc300_tty: open invalid port %d\n", port);
-               return -ENODEV;
-       } 
-
-       cpc_tty = &cpc_tty_area[port];
-       
-       if (cpc_tty->state == CPC_TTY_ST_IDLE){
-               CPC_TTY_DBG("%s: open - invalid interface, port=%d\n",
-                                       cpc_tty->name, tty->index);
-               return -ENODEV;
-       }
-
-       if (cpc_tty->num_open == 0) { /* first open of this tty */
-               if (!cpc_tty_area[port].buf_tx){
-                       cpc_tty_area[port].buf_tx = kmalloc(CPC_TTY_MAX_MTU,GFP_KERNEL);
-                       if (!cpc_tty_area[port].buf_tx) {
-                               CPC_TTY_DBG("%s: error in memory allocation\n",cpc_tty->name);
-                               return -ENOMEM;
-                       }
-               } 
-
-               if (cpc_tty_area[port].buf_rx.first) {
-                       unsigned char * aux;
-                       while (cpc_tty_area[port].buf_rx.first) {
-                               aux = (unsigned char *)cpc_tty_area[port].buf_rx.first;
-                               cpc_tty_area[port].buf_rx.first = cpc_tty_area[port].buf_rx.first->next;
-                               kfree(aux);
-                       }
-                       cpc_tty_area[port].buf_rx.first = NULL;
-                       cpc_tty_area[port].buf_rx.last = NULL;
-               }
-
-               cpc_tty_area[port].state = CPC_TTY_ST_OPEN;
-               cpc_tty_area[port].tty = tty;
-               tty->driver_data = &cpc_tty_area[port];
-
-               cpc_tty_signal_on(cpc_tty->pc300dev, CTL_DTR);
-       } 
-
-       cpc_tty->num_open++;
-
-       CPC_TTY_DBG("%s: opening TTY driver\n", cpc_tty->name);
-       
-       /* avisar driver PC300 */ 
-       return 0; 
-}
-
-/*
- * PC300 TTY CLOSE routine
- *
- * This routine is called by the tty driver to close the interface 
- * o call close channel in PC300 driver (cpc_closech)
- * o free Rx and Tx buffers
- */
-
-static void cpc_tty_close(struct tty_struct *tty, struct file *flip)
-{
-       st_cpc_tty_area    *cpc_tty;
-       unsigned long flags;
-       int res;
-
-       if (!tty || !tty->driver_data ) {
-               CPC_TTY_DBG("hdlx-tty: no TTY in close\n");
-               return;
-       }
-
-       cpc_tty = (st_cpc_tty_area *) tty->driver_data;
-
-       if ((cpc_tty->tty != tty)|| (cpc_tty->state != CPC_TTY_ST_OPEN)) {
-               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
-               return;
-       }
-       
-       if (!cpc_tty->num_open) {
-               CPC_TTY_DBG("%s: TTY is closed\n",cpc_tty->name);
-               return;
-       }
-
-       if (--cpc_tty->num_open > 0) {
-               CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name);
-               return;
-       }
-
-       cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
-
-       CPC_TTY_LOCK(cpc_tty->pc300dev->chan->card, flags);  /* lock irq */ 
-       cpc_tty->tty = NULL;
-       cpc_tty->state = CPC_TTY_ST_INIT;
-       CPC_TTY_UNLOCK(cpc_tty->pc300dev->chan->card, flags); /* unlock irq */ 
-       
-       if (cpc_tty->buf_rx.first) {
-               unsigned char * aux;
-               while (cpc_tty->buf_rx.first) {
-                       aux = (unsigned char *)cpc_tty->buf_rx.first;
-                       cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
-                       kfree(aux);
-               }
-               cpc_tty->buf_rx.first = NULL;
-               cpc_tty->buf_rx.last = NULL;
-       }
-       
-       kfree(cpc_tty->buf_tx);
-       cpc_tty->buf_tx = NULL;
-
-       CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name);
-       
-       if (!serial_drv.refcount && cpc_tty_unreg_flag) {
-               cpc_tty_unreg_flag = 0;
-               CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name);
-               if ((res=tty_unregister_driver(&serial_drv))) { 
-                       CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n",
-                                                       cpc_tty->name,res);
-               }
-       }
-       return; 
-} 
-
-/*
- * PC300 TTY WRITE routine
- *
- * This routine is called by the tty driver to write a series of characters
- * to the tty device. The characters may come from user or kernel space.
- * o verify the DCD signal
- * o send characters to board and start the transmission
- */
-static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-       st_cpc_tty_area    *cpc_tty; 
-       pc300ch_t *pc300chan; 
-       pc300_t *card; 
-       int ch; 
-       unsigned long flags; 
-       struct net_device_stats *stats; 
-
-       if (!tty || !tty->driver_data ) { 
-               CPC_TTY_DBG("hdlcX-tty: no TTY in write\n");
-               return -ENODEV;
-       } 
-
-       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
-
-       if ((cpc_tty->tty != tty) ||  (cpc_tty->state != CPC_TTY_ST_OPEN)) { 
-               CPC_TTY_DBG("%s: TTY is not opened\n", cpc_tty->name);
-               return -ENODEV; 
-       }
-
-       if (count > CPC_TTY_MAX_MTU) { 
-               CPC_TTY_DBG("%s: count is invalid\n",cpc_tty->name);
-               return -EINVAL;        /* frame too big */ 
-       }
-
-       CPC_TTY_DBG("%s: cpc_tty_write data len=%i\n",cpc_tty->name,count);
-       
-       pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; 
-       stats = &cpc_tty->pc300dev->dev->stats;
-       card = (pc300_t *) pc300chan->card;
-       ch = pc300chan->channel; 
-
-       /* verify DCD signal*/ 
-       if (cpc_readb(card->hw.scabase + M_REG(ST3,ch)) & ST3_DCD) { 
-               /* DCD is OFF */ 
-               CPC_TTY_DBG("%s : DCD is OFF\n", cpc_tty->name);
-               stats->tx_errors++;
-               stats->tx_carrier_errors++;
-               CPC_TTY_LOCK(card, flags); 
-               cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR); 
-               
-               if (card->hw.type == PC300_TE) { 
-                       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, 
-                               cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & 
-                               ~(CPLD_REG2_FALC_LED1 << (2 *ch))); 
-               }
-
-               CPC_TTY_UNLOCK(card, flags); 
-
-               return -EINVAL; 
-       }
-
-       if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*)buf, count)) { 
-          /* failed to send */
-          CPC_TTY_DBG("%s: trasmition error\n", cpc_tty->name);
-          return 0;
-       }
-       return count; 
-} 
-
-/*
- * PC300 TTY Write Room routine
- * 
- * This routine returns the numbers of characteres the tty driver will accept
- * for queuing to be written. 
- * o return MTU
- */
-static int cpc_tty_write_room(struct tty_struct *tty)
-{
-       st_cpc_tty_area    *cpc_tty; 
-
-       if (!tty || !tty->driver_data ) { 
-               CPC_TTY_DBG("hdlcX-tty: no TTY to write room\n");
-               return -ENODEV;
-       }
-
-       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
-
-       if ((cpc_tty->tty != tty) ||  (cpc_tty->state != CPC_TTY_ST_OPEN)) { 
-               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
-               return -ENODEV; 
-       }
-       
-       CPC_TTY_DBG("%s: write room\n",cpc_tty->name);
-       
-       return CPC_TTY_MAX_MTU;
-} 
-
-/*
- * PC300 TTY chars in buffer routine
- * 
- * This routine returns the chars number in the transmission buffer 
- * o returns 0
- */
-static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
-{
-       st_cpc_tty_area    *cpc_tty; 
-
-       if (!tty || !tty->driver_data ) {
-               CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n");
-               return -ENODEV; 
-       }
-
-       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
-
-       if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) { 
-               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
-               return -ENODEV; 
-       }
-   
-       return 0;
-} 
-
-static int pc300_tiocmset(struct tty_struct *tty,
-                         unsigned int set, unsigned int clear)
-{
-       st_cpc_tty_area    *cpc_tty; 
-
-       CPC_TTY_DBG("%s: set:%x clear:%x\n", __func__, set, clear);
-
-       if (!tty || !tty->driver_data ) {
-               CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n");  
-               return -ENODEV; 
-       }
-
-       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
-
-       if (set & TIOCM_RTS)
-               cpc_tty_signal_on(cpc_tty->pc300dev, CTL_RTS);
-       if (set & TIOCM_DTR)
-               cpc_tty_signal_on(cpc_tty->pc300dev, CTL_DTR);
-
-       if (clear & TIOCM_RTS)
-               cpc_tty_signal_off(cpc_tty->pc300dev, CTL_RTS);
-       if (clear & TIOCM_DTR)
-               cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
-
-       return 0;
-}
-
-static int pc300_tiocmget(struct tty_struct *tty)
-{
-       unsigned int result;
-       unsigned char status;
-       unsigned long flags;
-       st_cpc_tty_area  *cpc_tty = (st_cpc_tty_area *) tty->driver_data;
-       pc300dev_t *pc300dev = cpc_tty->pc300dev;
-       pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan;
-       pc300_t *card = (pc300_t *) pc300chan->card;
-       int ch = pc300chan->channel;
-
-       cpc_tty = (st_cpc_tty_area *) tty->driver_data;
-
-       CPC_TTY_DBG("%s-tty: tiocmget\n",
-               ((struct net_device*)(pc300dev->hdlc))->name);
-
-       CPC_TTY_LOCK(card, flags);
-       status = cpc_readb(card->hw.scabase+M_REG(CTL,ch));
-       CPC_TTY_UNLOCK(card,flags);
-
-       result = ((status & CTL_DTR) ? TIOCM_DTR : 0) |
-                ((status & CTL_RTS) ? TIOCM_RTS : 0);
-
-       return result;
-}
-
-/*
- * PC300 TTY Flush Buffer routine
- *
- * This routine resets the transmission buffer 
- */
-static void cpc_tty_flush_buffer(struct tty_struct *tty)
-{ 
-       st_cpc_tty_area    *cpc_tty; 
-       
-       if (!tty || !tty->driver_data ) {
-               CPC_TTY_DBG("hdlcX-tty: no TTY to flush buffer\n");     
-               return; 
-       }
-
-       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
-
-       if ((cpc_tty->tty != tty) ||  (cpc_tty->state != CPC_TTY_ST_OPEN)) { 
-               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
-               return; 
-       }
-
-       CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name);
-
-       tty_wakeup(tty);        
-       return; 
-} 
-
-/*
- * PC300 TTY Hangup routine
- *
- * This routine is called by the tty driver to hangup the interface 
- * o clear DTR signal
- */
-
-static void cpc_tty_hangup(struct tty_struct *tty)
-{ 
-       st_cpc_tty_area    *cpc_tty; 
-       int res;
-
-       if (!tty || !tty->driver_data ) {
-               CPC_TTY_DBG("hdlcX-tty: no TTY to hangup\n");   
-               return ; 
-       }
-
-       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
-
-       if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) {
-               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
-               return ;
-       }
-       if (!serial_drv.refcount && cpc_tty_unreg_flag) {
-               cpc_tty_unreg_flag = 0;
-               CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name);
-               if ((res=tty_unregister_driver(&serial_drv))) { 
-                       CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n",
-                                                       cpc_tty->name,res);
-               }
-       }
-       cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
-}
-
-/*
- * PC300 TTY RX work routine
- * This routine treats RX work
- * o verify read buffer
- * o call the line disc. read
- * o free memory
- */
-static void cpc_tty_rx_work(struct work_struct *work)
-{
-       st_cpc_tty_area *cpc_tty;
-       unsigned long port;
-       int i, j;
-       volatile st_cpc_rx_buf *buf;
-       char flags=0,flg_rx=1; 
-       struct tty_ldisc *ld;
-
-       if (cpc_tty_cnt == 0) return;
-       
-       for (i=0; (i < 4) && flg_rx ; i++) {
-               flg_rx = 0;
-
-               cpc_tty = container_of(work, st_cpc_tty_area, tty_rx_work);
-               port = cpc_tty - cpc_tty_area;
-
-               for (j=0; j < CPC_TTY_NPORTS; j++) {
-                       cpc_tty = &cpc_tty_area[port];
-               
-                       if ((buf=cpc_tty->buf_rx.first) != NULL) {
-                               if (cpc_tty->tty) {
-                                       ld = tty_ldisc_ref(cpc_tty->tty);
-                                       if (ld) {
-                                               if (ld->ops->receive_buf) {
-                                                       CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
-                                                       ld->ops->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size);
-                                               }
-                                               tty_ldisc_deref(ld);
-                                       }
-                               }       
-                               cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
-                               kfree((void *)buf);
-                               buf = cpc_tty->buf_rx.first;
-                               flg_rx = 1;
-                       }
-                       if (++port == CPC_TTY_NPORTS) port = 0;
-               }
-       }
-} 
-
-/*
- * PC300 TTY RX work routine
- *
- * This routine treats RX interrupt. 
- * o read all frames in card
- * o verify the frame size
- * o read the frame in rx buffer
- */
-static void cpc_tty_rx_disc_frame(pc300ch_t *pc300chan)
-{
-       volatile pcsca_bd_t __iomem * ptdescr; 
-       volatile unsigned char status; 
-       pc300_t *card = (pc300_t *)pc300chan->card; 
-       int ch = pc300chan->channel; 
-
-       /* dma buf read */ 
-       ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + 
-                               RX_BD_ADDR(ch, pc300chan->rx_first_bd)); 
-       while (pc300chan->rx_first_bd != pc300chan->rx_last_bd) { 
-               status = cpc_readb(&ptdescr->status); 
-               cpc_writeb(&ptdescr->status, 0); 
-               cpc_writeb(&ptdescr->len, 0); 
-               pc300chan->rx_first_bd = (pc300chan->rx_first_bd + 1) & 
-                                       (N_DMA_RX_BUF - 1); 
-               if (status & DST_EOM) { 
-                       break; /* end of message */
-               }
-               ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->next)); 
-       }
-}
-
-void cpc_tty_receive(pc300dev_t *pc300dev)
-{
-       st_cpc_tty_area *cpc_tty; 
-       pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; 
-       pc300_t *card = (pc300_t *)pc300chan->card; 
-       int ch = pc300chan->channel; 
-       volatile pcsca_bd_t  __iomem * ptdescr; 
-       struct net_device_stats *stats = &pc300dev->dev->stats;
-       int rx_len, rx_aux; 
-       volatile unsigned char status; 
-       unsigned short first_bd = pc300chan->rx_first_bd;
-       st_cpc_rx_buf *new = NULL;
-       unsigned char dsr_rx;
-
-       if (pc300dev->cpc_tty == NULL) { 
-               return; 
-       }
-
-       dsr_rx = cpc_readb(card->hw.scabase + DSR_RX(ch));
-
-       cpc_tty = pc300dev->cpc_tty;
-
-       while (1) { 
-               rx_len = 0;
-               ptdescr = (pcsca_bd_t  __iomem *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd));
-               while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
-                       rx_len += cpc_readw(&ptdescr->len);
-                       first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1);
-                       if (status & DST_EOM) {
-                               break;
-                       }
-                       ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase+cpc_readl(&ptdescr->next));
-               }
-                       
-               if (!rx_len) { 
-                       if (dsr_rx & DSR_BOF) {
-                               /* update EDA */ 
-                               cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), 
-                                               RX_BD_ADDR(ch, pc300chan->rx_last_bd)); 
-                       }
-                       kfree(new);
-                       return; 
-               }
-               
-               if (rx_len > CPC_TTY_MAX_MTU) { 
-                       /* Free RX descriptors */ 
-                       CPC_TTY_DBG("%s: frame size is invalid.\n",cpc_tty->name);
-                       stats->rx_errors++; 
-                       stats->rx_frame_errors++; 
-                       cpc_tty_rx_disc_frame(pc300chan);
-                       continue;
-               } 
-               
-               new = kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
-               if (!new) {
-                       cpc_tty_rx_disc_frame(pc300chan);
-                       continue;
-               }
-               
-               /* dma buf read */ 
-               ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + 
-                               RX_BD_ADDR(ch, pc300chan->rx_first_bd)); 
-
-               rx_len = 0;     /* counter frame size */
-               
-               while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
-                       rx_aux = cpc_readw(&ptdescr->len);
-                       if ((status & (DST_OVR | DST_CRC | DST_RBIT |  DST_SHRT | DST_ABT))
-                               || (rx_aux > BD_DEF_LEN)) {
-                               CPC_TTY_DBG("%s: reception error\n", cpc_tty->name);
-                               stats->rx_errors++; 
-                               if (status & DST_OVR) { 
-                                       stats->rx_fifo_errors++; 
-                               }
-                               if (status & DST_CRC) { 
-                                       stats->rx_crc_errors++; 
-                               }
-                               if ((status & (DST_RBIT | DST_SHRT | DST_ABT)) ||
-                                       (rx_aux > BD_DEF_LEN))  { 
-                                       stats->rx_frame_errors++; 
-                               } 
-                               /* discard remainig descriptors used by the bad frame */ 
-                               CPC_TTY_DBG("%s: reception error - discard descriptors",
-                                               cpc_tty->name);
-                               cpc_tty_rx_disc_frame(pc300chan);
-                               rx_len = 0;
-                               kfree(new);
-                               new = NULL;
-                               break; /* read next frame - while(1) */
-                       }
-
-                       if (cpc_tty->state != CPC_TTY_ST_OPEN) {
-                               /* Free RX descriptors */ 
-                               cpc_tty_rx_disc_frame(pc300chan);
-                               stats->rx_dropped++; 
-                               rx_len = 0; 
-                               kfree(new);
-                               new = NULL;
-                               break; /* read next frame - while(1) */
-                       }
-
-                       /* read the segment of the frame */
-                       if (rx_aux != 0) {
-                               memcpy_fromio((new->data + rx_len), 
-                                       (void __iomem *)(card->hw.rambase + 
-                                        cpc_readl(&ptdescr->ptbuf)), rx_aux);
-                               rx_len += rx_aux; 
-                       }
-                       cpc_writeb(&ptdescr->status,0); 
-                       cpc_writeb(&ptdescr->len, 0); 
-                       pc300chan->rx_first_bd = (pc300chan->rx_first_bd + 1) & 
-                                       (N_DMA_RX_BUF -1); 
-                       if (status & DST_EOM)break;
-                       
-                       ptdescr = (pcsca_bd_t __iomem *) (card->hw.rambase + 
-                                       cpc_readl(&ptdescr->next)); 
-               }
-               /* update pointer */ 
-               pc300chan->rx_last_bd = (pc300chan->rx_first_bd - 1) & 
-                                       (N_DMA_RX_BUF - 1) ; 
-               if (!(dsr_rx & DSR_BOF)) {
-                       /* update EDA */ 
-                       cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), 
-                                       RX_BD_ADDR(ch, pc300chan->rx_last_bd)); 
-               }
-               if (rx_len != 0) { 
-                       stats->rx_bytes += rx_len; 
-               
-                       if (pc300dev->trace_on) { 
-                               cpc_tty_trace(pc300dev, new->data,rx_len, 'R'); 
-                       } 
-                       new->size = rx_len;
-                       new->next = NULL;
-                       if (cpc_tty->buf_rx.first == NULL) {
-                               cpc_tty->buf_rx.first = new;
-                               cpc_tty->buf_rx.last = new;
-                       } else {
-                               cpc_tty->buf_rx.last->next = new;
-                               cpc_tty->buf_rx.last = new;
-                       }
-                       schedule_work(&(cpc_tty->tty_rx_work));
-                       stats->rx_packets++;
-               }
-       } 
-} 
-
-/*
- * PC300 TTY TX work routine
- * 
- * This routine treats TX interrupt. 
- * o if need call line discipline wakeup
- * o call wake_up_interruptible
- */
-static void cpc_tty_tx_work(struct work_struct *work)
-{
-       st_cpc_tty_area *cpc_tty =
-               container_of(work, st_cpc_tty_area, tty_tx_work);
-       struct tty_struct *tty; 
-
-       CPC_TTY_DBG("%s: cpc_tty_tx_work init\n",cpc_tty->name);
-       
-       if ((tty = cpc_tty->tty) == NULL) { 
-               CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name);
-               return; 
-       }
-       tty_wakeup(tty);
-}
-
-/*
- * PC300 TTY send to card routine
- * 
- * This routine send data to card. 
- * o clear descriptors
- * o write data to DMA buffers
- * o start the transmission
- */
-static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len)
-{
-       pc300ch_t *chan = (pc300ch_t *)dev->chan; 
-       pc300_t *card = (pc300_t *)chan->card; 
-       int ch = chan->channel; 
-       struct net_device_stats *stats = &dev->dev->stats;
-       unsigned long flags; 
-       volatile pcsca_bd_t __iomem *ptdescr; 
-       int i, nchar;
-       int tosend = len;
-       int nbuf = ((len - 1)/BD_DEF_LEN) + 1;
-       unsigned char *pdata=buf;
-
-       CPC_TTY_DBG("%s:cpc_tty_send_to_cars len=%i", 
-                       (st_cpc_tty_area *)dev->cpc_tty->name,len);     
-
-       if (nbuf >= card->chan[ch].nfree_tx_bd) {
-               return 1;
-       }
-       
-       /* write buffer to DMA buffers */ 
-       CPC_TTY_DBG("%s: call dma_buf_write\n",
-                       (st_cpc_tty_area *)dev->cpc_tty->name); 
-       for (i = 0 ; i < nbuf ; i++) {
-               ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + 
-                       TX_BD_ADDR(ch, card->chan[ch].tx_next_bd));
-               nchar = (BD_DEF_LEN > tosend) ? tosend : BD_DEF_LEN;
-               if (cpc_readb(&ptdescr->status) & DST_OSB) {
-                       memcpy_toio((void __iomem *)(card->hw.rambase + 
-                               cpc_readl(&ptdescr->ptbuf)), 
-                               &pdata[len - tosend], 
-                               nchar);
-                       card->chan[ch].nfree_tx_bd--;
-                       if ((i + 1) == nbuf) {
-                               /* This must be the last BD to be used */
-                               cpc_writeb(&ptdescr->status, DST_EOM);
-                       } else {
-                               cpc_writeb(&ptdescr->status, 0);
-                       }
-                       cpc_writew(&ptdescr->len, nchar);
-               } else {
-                       CPC_TTY_DBG("%s: error in dma_buf_write\n",
-                                       (st_cpc_tty_area *)dev->cpc_tty->name); 
-                       stats->tx_dropped++;
-                       return 1; 
-               }
-               tosend -= nchar;
-               card->chan[ch].tx_next_bd = 
-                       (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1);
-       }
-
-       if (dev->trace_on) { 
-               cpc_tty_trace(dev, buf, len,'T'); 
-       }
-
-       /* start transmission */ 
-       CPC_TTY_DBG("%s: start transmission\n",
-               (st_cpc_tty_area *)dev->cpc_tty->name); 
-       
-       CPC_TTY_LOCK(card, flags); 
-       cpc_writeb(card->hw.scabase + DTX_REG(EDAL, ch), 
-                       TX_BD_ADDR(ch, chan->tx_next_bd)); 
-       cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA); 
-       cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE); 
-
-       if (card->hw.type == PC300_TE) { 
-               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, 
-                       cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) |
-                       (CPLD_REG2_FALC_LED1 << (2 * ch))); 
-       }
-       CPC_TTY_UNLOCK(card, flags); 
-       return 0; 
-} 
-
-/*
- *     PC300 TTY trace routine
- *
- *  This routine send trace of connection to application. 
- *  o clear descriptors
- *  o write data to DMA buffers
- *  o start the transmission
- */
-
-static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx)
-{
-       struct sk_buff *skb; 
-
-       if ((skb = dev_alloc_skb(10 + len)) == NULL) { 
-               /* out of memory */ 
-               CPC_TTY_DBG("%s: tty_trace - out of memory\n", dev->dev->name);
-               return; 
-       }
-
-       skb_put (skb, 10 + len); 
-       skb->dev = dev->dev; 
-       skb->protocol = htons(ETH_P_CUST); 
-       skb_reset_mac_header(skb);
-       skb->pkt_type = PACKET_HOST; 
-       skb->len = 10 + len; 
-
-       skb_copy_to_linear_data(skb, dev->dev->name, 5);
-       skb->data[5] = '['; 
-       skb->data[6] = rxtx; 
-       skb->data[7] = ']'; 
-       skb->data[8] = ':'; 
-       skb->data[9] = ' '; 
-       skb_copy_to_linear_data_offset(skb, 10, buf, len);
-       netif_rx(skb); 
-}      
-
-/*
- *     PC300 TTY unregister service routine
- *
- *     This routine unregister one interface. 
- */
-void cpc_tty_unregister_service(pc300dev_t *pc300dev)
-{
-       st_cpc_tty_area *cpc_tty; 
-       ulong flags;
-       int res;
-
-       if ((cpc_tty= (st_cpc_tty_area *) pc300dev->cpc_tty) == NULL) {
-               CPC_TTY_DBG("%s: interface is not TTY\n", pc300dev->dev->name);
-               return; 
-       }
-       CPC_TTY_DBG("%s: cpc_tty_unregister_service", cpc_tty->name);
-
-       if (cpc_tty->pc300dev != pc300dev) { 
-               CPC_TTY_DBG("%s: invalid tty ptr=%s\n", 
-               pc300dev->dev->name, cpc_tty->name);
-               return; 
-       }
-
-       if (--cpc_tty_cnt == 0) { 
-               if (serial_drv.refcount) {
-                       CPC_TTY_DBG("%s: unregister is not possible, refcount=%d",
-                                                       cpc_tty->name, serial_drv.refcount);
-                       cpc_tty_cnt++;
-                       cpc_tty_unreg_flag = 1;
-                       return;
-               } else { 
-                       CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name);
-                       if ((res=tty_unregister_driver(&serial_drv))) { 
-                               CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n",
-                                                               cpc_tty->name,res);
-                       }
-               }
-       }
-       CPC_TTY_LOCK(pc300dev->chan->card,flags);
-       cpc_tty->tty = NULL; 
-       CPC_TTY_UNLOCK(pc300dev->chan->card, flags);
-       cpc_tty->tty_minor = 0; 
-       cpc_tty->state = CPC_TTY_ST_IDLE; 
-} 
-
-/*
- * PC300 TTY trigger poll routine
- * This routine is called by pc300driver to treats Tx interrupt. 
- */
-void cpc_tty_trigger_poll(pc300dev_t *pc300dev)
-{
-       st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *)pc300dev->cpc_tty; 
-       if (!cpc_tty) {
-               return;
-       }
-       schedule_work(&(cpc_tty->tty_tx_work)); 
-} 
 
 
 source "drivers/staging/media/Kconfig"
 
+source "drivers/staging/net/Kconfig"
+
 source "drivers/staging/omapdrm/Kconfig"
 
 source "drivers/staging/android/Kconfig"
 
 obj-$(CONFIG_STAGING)          += staging.o
 
 obj-y                          += media/
+obj-y                          += net/
 obj-$(CONFIG_ET131X)           += et131x/
 obj-$(CONFIG_SLICOSS)          += slicoss/
 obj-$(CONFIG_USBIP_CORE)       += usbip/
 
--- /dev/null
+if NETDEVICES
+
+if WAN
+
+config PC300
+       tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)"
+       depends on HDLC && PCI && BROKEN
+       ---help---
+         This driver is broken because of struct tty_driver change.
+
+         Driver for the Cyclades-PC300 synchronous communication boards.
+
+         These boards provide synchronous serial interfaces to your
+         Linux box (interfaces currently available are RS-232/V.35, X.21 and
+         T1/E1). If you wish to support Multilink PPP, please select the
+         option later and read the file README.mlppp provided by PC300
+         package.
+
+         To compile this as a module, choose M here: the module
+         will be called pc300.
+
+         If unsure, say N.
+
+config PC300_MLPPP
+       bool "Cyclades-PC300 MLPPP support"
+       depends on PC300 && PPP_MULTILINK && PPP_SYNC_TTY && HDLC_PPP
+       help
+         Multilink PPP over the PC300 synchronous communication boards.
+
+comment "Cyclades-PC300 MLPPP support is disabled."
+       depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
+
+comment "Refer to the file README.mlppp, provided by PC300 package."
+       depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP)
+
+endif # WAN
+
+endif # NETDEVICES
 
--- /dev/null
+pc300-y                                := pc300_drv.o
+pc300-$(CONFIG_PC300_MLPPP)    += pc300_tty.o
+pc300-objs                     := $(pc300-y)
+
+obj-$(CONFIG_PC300)            += pc300.o
 
--- /dev/null
+PC300
+The driver is very broken and cannot work with the current TTY layer. It is
+inevitable to convert it to the new TTY API.
+
+If no one steps in to adopt the driver, it will be removed in the 3.7 release.
 
--- /dev/null
+/*
+ * falc.h      Description of the Siemens FALC T1/E1 framer.
+ *
+ * Author:     Ivan Passos <ivan@cyclades.com>
+ *
+ * Copyright:  (c) 2000-2001 Cyclades Corp.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ * $Log: falc-lh.h,v $
+ * Revision 3.1  2001/06/15 12:41:10  regina
+ * upping major version number
+ *
+ * Revision 1.1.1.1  2001/06/13 20:24:47  daniela
+ * PC300 initial CVS version (3.4.0-pre1)
+ *
+ * Revision 1.1 2000/05/15 ivan
+ * Included DJA bits for the LIM2 register.
+ *
+ * Revision 1.0 2000/02/22 ivan
+ * Initial version.
+ *
+ */
+
+#ifndef _FALC_LH_H
+#define _FALC_LH_H
+
+#define NUM_OF_T1_CHANNELS     24
+#define NUM_OF_E1_CHANNELS     32
+
+/*>>>>>>>>>>>>>>>>>  FALC Register Bits (Transmit Mode)  <<<<<<<<<<<<<<<<<<< */
+
+/* CMDR (Command Register)
+   ---------------- E1 & T1 ------------------------------ */
+#define CMDR_RMC       0x80
+#define CMDR_RRES      0x40
+#define CMDR_XREP      0x20
+#define CMDR_XRES      0x10
+#define CMDR_XHF       0x08
+#define CMDR_XTF       0x04
+#define CMDR_XME       0x02
+#define CMDR_SRES      0x01
+
+/* MODE (Mode Register)
+   ----------------- E1 & T1 ----------------------------- */
+#define MODE_MDS2      0x80
+#define MODE_MDS1      0x40
+#define MODE_MDS0      0x20
+#define MODE_BRAC      0x10
+#define MODE_HRAC      0x08
+
+/* IPC (Interrupt Port Configuration)
+   ----------------- E1 & T1 ----------------------------- */
+#define IPC_VIS                0x80
+#define IPC_SCI                0x04
+#define IPC_IC1                0x02
+#define IPC_IC0                0x01
+
+/* CCR1 (Common Configuration Register 1)
+   ----------------- E1 & T1 ----------------------------- */
+#define CCR1_SFLG       0x80
+#define CCR1_XTS16RA    0x40
+#define CCR1_BRM        0x40
+#define CCR1_CASSYM     0x20
+#define CCR1_EDLX       0x20
+#define CCR1_EITS       0x10
+#define CCR1_ITF        0x08
+#define CCR1_RFT1       0x02
+#define CCR1_RFT0       0x01
+
+/* CCR3 (Common Configuration Register 3)
+   ---------------- E1 & T1 ------------------------------ */
+
+#define CCR3_PRE1       0x80
+#define CCR3_PRE0       0x40
+#define CCR3_EPT        0x20
+#define CCR3_RADD       0x10
+#define CCR3_RCRC       0x04
+#define CCR3_XCRC       0x02
+
+
+/* RTR1-4 (Receive Timeslot Register 1-4)
+   ---------------- E1 & T1 ------------------------------ */
+
+#define RTR1_TS0        0x80
+#define RTR1_TS1        0x40
+#define RTR1_TS2        0x20
+#define RTR1_TS3        0x10
+#define RTR1_TS4        0x08
+#define RTR1_TS5        0x04
+#define RTR1_TS6        0x02
+#define RTR1_TS7        0x01
+
+#define RTR2_TS8        0x80
+#define RTR2_TS9        0x40
+#define RTR2_TS10       0x20
+#define RTR2_TS11       0x10
+#define RTR2_TS12       0x08
+#define RTR2_TS13       0x04
+#define RTR2_TS14       0x02
+#define RTR2_TS15       0x01
+
+#define RTR3_TS16       0x80
+#define RTR3_TS17       0x40
+#define RTR3_TS18       0x20
+#define RTR3_TS19       0x10
+#define RTR3_TS20       0x08
+#define RTR3_TS21       0x04
+#define RTR3_TS22       0x02
+#define RTR3_TS23       0x01
+
+#define RTR4_TS24       0x80
+#define RTR4_TS25       0x40
+#define RTR4_TS26       0x20
+#define RTR4_TS27       0x10
+#define RTR4_TS28       0x08
+#define RTR4_TS29       0x04
+#define RTR4_TS30       0x02
+#define RTR4_TS31       0x01
+
+
+/* TTR1-4 (Transmit Timeslot Register 1-4)
+   ---------------- E1 & T1 ------------------------------ */
+
+#define TTR1_TS0        0x80
+#define TTR1_TS1        0x40
+#define TTR1_TS2        0x20
+#define TTR1_TS3        0x10
+#define TTR1_TS4        0x08
+#define TTR1_TS5        0x04
+#define TTR1_TS6        0x02
+#define TTR1_TS7        0x01
+
+#define TTR2_TS8        0x80
+#define TTR2_TS9        0x40
+#define TTR2_TS10       0x20
+#define TTR2_TS11       0x10
+#define TTR2_TS12       0x08
+#define TTR2_TS13       0x04
+#define TTR2_TS14       0x02
+#define TTR2_TS15       0x01
+
+#define TTR3_TS16       0x80
+#define TTR3_TS17       0x40
+#define TTR3_TS18       0x20
+#define TTR3_TS19       0x10
+#define TTR3_TS20       0x08
+#define TTR3_TS21       0x04
+#define TTR3_TS22       0x02
+#define TTR3_TS23       0x01
+
+#define TTR4_TS24       0x80
+#define TTR4_TS25       0x40
+#define TTR4_TS26       0x20
+#define TTR4_TS27       0x10
+#define TTR4_TS28       0x08
+#define TTR4_TS29       0x04
+#define TTR4_TS30       0x02
+#define TTR4_TS31       0x01
+
+
+
+/* IMR0-4 (Interrupt Mask Register 0-4)
+
+   ----------------- E1 & T1 ----------------------------- */
+
+#define IMR0_RME        0x80
+#define IMR0_RFS        0x40
+#define IMR0_T8MS       0x20
+#define IMR0_ISF        0x20
+#define IMR0_RMB        0x10
+#define IMR0_CASC       0x08
+#define IMR0_RSC        0x08
+#define IMR0_CRC6       0x04
+#define IMR0_CRC4       0x04
+#define IMR0_PDEN      0x02
+#define IMR0_RPF        0x01
+
+#define IMR1_CASE       0x80
+#define IMR1_RDO        0x40
+#define IMR1_ALLS       0x20
+#define IMR1_XDU        0x10
+#define IMR1_XMB        0x08
+#define IMR1_XLSC       0x02
+#define IMR1_XPR        0x01
+#define IMR1_LLBSC     0x80
+
+#define IMR2_FAR        0x80
+#define IMR2_LFA        0x40
+#define IMR2_MFAR       0x20
+#define IMR2_T400MS     0x10
+#define IMR2_LMFA       0x10
+#define IMR2_AIS        0x08
+#define IMR2_LOS        0x04
+#define IMR2_RAR        0x02
+#define IMR2_RA         0x01
+
+#define IMR3_ES         0x80
+#define IMR3_SEC        0x40
+#define IMR3_LMFA16     0x20
+#define IMR3_AIS16      0x10
+#define IMR3_RA16       0x08
+#define IMR3_API        0x04
+#define IMR3_XSLP       0x20
+#define IMR3_XSLN       0x10
+#define IMR3_LLBSC      0x08
+#define IMR3_XRS        0x04
+#define IMR3_SLN        0x02
+#define IMR3_SLP        0x01
+
+#define IMR4_LFA        0x80
+#define IMR4_FER        0x40
+#define IMR4_CER        0x20
+#define IMR4_AIS        0x10
+#define IMR4_LOS        0x08
+#define IMR4_CVE        0x04
+#define IMR4_SLIP       0x02
+#define IMR4_EBE        0x01
+
+/* FMR0-5 for E1 and T1  (Framer Mode Register ) */
+
+#define FMR0_XC1        0x80
+#define FMR0_XC0        0x40
+#define FMR0_RC1        0x20
+#define FMR0_RC0        0x10
+#define FMR0_EXTD       0x08
+#define FMR0_ALM        0x04
+#define E1_FMR0_FRS     0x02
+#define T1_FMR0_FRS     0x08
+#define FMR0_SRAF       0x04
+#define FMR0_EXLS       0x02
+#define FMR0_SIM        0x01
+
+#define FMR1_MFCS       0x80
+#define FMR1_AFR        0x40
+#define FMR1_ENSA       0x20
+#define FMR1_CTM        0x80
+#define FMR1_SIGM       0x40
+#define FMR1_EDL        0x20
+#define FMR1_PMOD       0x10
+#define FMR1_XFS        0x08
+#define FMR1_CRC        0x08
+#define FMR1_ECM        0x04
+#define FMR1_IMOD       0x02
+#define FMR1_XAIS       0x01
+
+#define FMR2_RFS1       0x80
+#define FMR2_RFS0       0x40
+#define FMR2_MCSP      0x40
+#define FMR2_RTM        0x20
+#define FMR2_SSP        0x20
+#define FMR2_DAIS       0x10
+#define FMR2_SAIS       0x08
+#define FMR2_PLB        0x04
+#define FMR2_AXRA       0x02
+#define FMR2_ALMF       0x01
+#define FMR2_EXZE       0x01
+
+#define LOOP_RTM       0x40
+#define LOOP_SFM       0x40
+#define LOOP_ECLB      0x20
+#define LOOP_CLA       0x1f
+
+/*--------------------- E1 ----------------------------*/
+#define FMR3_XLD       0x20
+#define FMR3_XLU       0x10
+
+/*--------------------- T1 ----------------------------*/
+#define FMR4_AIS3       0x80
+#define FMR4_TM         0x40
+#define FMR4_XRA        0x20
+#define FMR4_SSC1       0x10
+#define FMR4_SSC0       0x08
+#define FMR4_AUTO       0x04
+#define FMR4_FM1        0x02
+#define FMR4_FM0        0x01
+
+#define FMR5_SRS        0x80
+#define FMR5_EIBR       0x40
+#define FMR5_XLD        0x20
+#define FMR5_XLU        0x10
+
+
+/* LOOP (Channel Loop Back)
+
+   ------------------ E1 & T1 ---------------------------- */
+
+#define LOOP_SFM        0x40
+#define LOOP_ECLB       0x20
+#define LOOP_CLA4       0x10
+#define LOOP_CLA3       0x08
+#define LOOP_CLA2       0x04
+#define LOOP_CLA1       0x02
+#define LOOP_CLA0       0x01
+
+
+
+/* XSW (Transmit Service Word Pulseframe)
+
+   ------------------- E1 --------------------------- */
+
+#define XSW_XSIS        0x80
+#define XSW_XTM         0x40
+#define XSW_XRA         0x20
+#define XSW_XY0         0x10
+#define XSW_XY1         0x08
+#define XSW_XY2         0x04
+#define XSW_XY3         0x02
+#define XSW_XY4         0x01
+
+
+/* XSP (Transmit Spare Bits)
+
+   ------------------- E1 --------------------------- */
+
+#define XSP_XAP         0x80
+#define XSP_CASEN       0x40
+#define XSP_TT0         0x20
+#define XSP_EBP         0x10
+#define XSP_AXS         0x08
+#define XSP_XSIF        0x04
+#define XSP_XS13        0x02
+#define XSP_XS15        0x01
+
+
+/* XC0/1 (Transmit Control 0/1)
+   ------------------ E1 & T1 ---------------------------- */
+
+#define XC0_SA8E        0x80
+#define XC0_SA7E        0x40
+#define XC0_SA6E        0x20
+#define XC0_SA5E        0x10
+#define XC0_SA4E        0x08
+#define XC0_BRM         0x80
+#define XC0_MFBS        0x40
+#define XC0_SFRZ        0x10
+#define XC0_XCO2        0x04
+#define XC0_XCO1        0x02
+#define XC0_XCO0        0x01
+
+#define XC1_XTO5        0x20
+#define XC1_XTO4        0x10
+#define XC1_XTO3        0x08
+#define XC1_XTO2        0x04
+#define XC1_XTO1        0x02
+#define XC1_XTO0        0x01
+
+
+/* RC0/1 (Receive Control 0/1)
+   ------------------ E1 & T1 ---------------------------- */
+
+#define RC0_SICS        0x40
+#define RC0_CRCI        0x20
+#define RC0_XCRCI       0x10
+#define RC0_RDIS        0x08
+#define RC0_RCO2        0x04
+#define RC0_RCO1        0x02
+#define RC0_RCO0        0x01
+
+#define RC1_SWD         0x80
+#define RC1_ASY4        0x40
+#define RC1_RRAM        0x40
+#define RC1_RTO5        0x20
+#define RC1_RTO4        0x10
+#define RC1_RTO3        0x08
+#define RC1_RTO2        0x04
+#define RC1_RTO1        0x02
+#define RC1_RTO0        0x01
+
+
+
+/* XPM0-2 (Transmit Pulse Mask 0-2)
+   --------------------- E1 & T1 ------------------------- */
+
+#define XPM0_XP12       0x80
+#define XPM0_XP11       0x40
+#define XPM0_XP10       0x20
+#define XPM0_XP04       0x10
+#define XPM0_XP03       0x08
+#define XPM0_XP02       0x04
+#define XPM0_XP01       0x02
+#define XPM0_XP00       0x01
+
+#define XPM1_XP30       0x80
+#define XPM1_XP24       0x40
+#define XPM1_XP23       0x20
+#define XPM1_XP22       0x10
+#define XPM1_XP21       0x08
+#define XPM1_XP20       0x04
+#define XPM1_XP14       0x02
+#define XPM1_XP13       0x01
+
+#define XPM2_XLHP       0x80
+#define XPM2_XLT        0x40
+#define XPM2_DAXLT      0x20
+#define XPM2_XP34       0x08
+#define XPM2_XP33       0x04
+#define XPM2_XP32       0x02
+#define XPM2_XP31       0x01
+
+
+/* TSWM (Transparent Service Word Mask)
+   ------------------ E1 ---------------------------- */
+
+#define TSWM_TSIS       0x80
+#define TSWM_TSIF       0x40
+#define TSWM_TRA        0x20
+#define TSWM_TSA4       0x10
+#define TSWM_TSA5       0x08
+#define TSWM_TSA6       0x04
+#define TSWM_TSA7       0x02
+#define TSWM_TSA8       0x01
+
+/* IDLE <Idle Channel Code Register>
+
+   ------------------ E1 & T1 ----------------------- */
+
+#define IDLE_IDL7       0x80
+#define IDLE_IDL6       0x40
+#define IDLE_IDL5       0x20
+#define IDLE_IDL4       0x10
+#define IDLE_IDL3       0x08
+#define IDLE_IDL2       0x04
+#define IDLE_IDL1       0x02
+#define IDLE_IDL0       0x01
+
+
+/* XSA4-8 <Transmit SA4-8 Register(Read/Write) >
+   -------------------E1 ----------------------------- */
+
+#define XSA4_XS47       0x80
+#define XSA4_XS46       0x40
+#define XSA4_XS45       0x20
+#define XSA4_XS44       0x10
+#define XSA4_XS43       0x08
+#define XSA4_XS42       0x04
+#define XSA4_XS41       0x02
+#define XSA4_XS40       0x01
+
+#define XSA5_XS57       0x80
+#define XSA5_XS56       0x40
+#define XSA5_XS55       0x20
+#define XSA5_XS54       0x10
+#define XSA5_XS53       0x08
+#define XSA5_XS52       0x04
+#define XSA5_XS51       0x02
+#define XSA5_XS50       0x01
+
+#define XSA6_XS67       0x80
+#define XSA6_XS66       0x40
+#define XSA6_XS65       0x20
+#define XSA6_XS64       0x10
+#define XSA6_XS63       0x08
+#define XSA6_XS62       0x04
+#define XSA6_XS61       0x02
+#define XSA6_XS60       0x01
+
+#define XSA7_XS77       0x80
+#define XSA7_XS76       0x40
+#define XSA7_XS75       0x20
+#define XSA7_XS74       0x10
+#define XSA7_XS73       0x08
+#define XSA7_XS72       0x04
+#define XSA7_XS71       0x02
+#define XSA7_XS70       0x01
+
+#define XSA8_XS87       0x80
+#define XSA8_XS86       0x40
+#define XSA8_XS85       0x20
+#define XSA8_XS84       0x10
+#define XSA8_XS83       0x08
+#define XSA8_XS82       0x04
+#define XSA8_XS81       0x02
+#define XSA8_XS80       0x01
+
+
+/* XDL1-3 (Transmit DL-Bit Register1-3 (read/write))
+   ----------------------- T1 --------------------- */
+
+#define XDL1_XDL17      0x80
+#define XDL1_XDL16      0x40
+#define XDL1_XDL15      0x20
+#define XDL1_XDL14      0x10
+#define XDL1_XDL13      0x08
+#define XDL1_XDL12      0x04
+#define XDL1_XDL11      0x02
+#define XDL1_XDL10      0x01
+
+#define XDL2_XDL27      0x80
+#define XDL2_XDL26      0x40
+#define XDL2_XDL25      0x20
+#define XDL2_XDL24      0x10
+#define XDL2_XDL23      0x08
+#define XDL2_XDL22      0x04
+#define XDL2_XDL21      0x02
+#define XDL2_XDL20      0x01
+
+#define XDL3_XDL37      0x80
+#define XDL3_XDL36      0x40
+#define XDL3_XDL35      0x20
+#define XDL3_XDL34      0x10
+#define XDL3_XDL33      0x08
+#define XDL3_XDL32      0x04
+#define XDL3_XDL31      0x02
+#define XDL3_XDL30      0x01
+
+
+/* ICB1-4 (Idle Channel Register 1-4)
+   ------------------ E1 ---------------------------- */
+
+#define E1_ICB1_IC0    0x80
+#define E1_ICB1_IC1    0x40
+#define E1_ICB1_IC2    0x20
+#define E1_ICB1_IC3    0x10
+#define E1_ICB1_IC4    0x08
+#define E1_ICB1_IC5    0x04
+#define E1_ICB1_IC6    0x02
+#define E1_ICB1_IC7    0x01
+
+#define E1_ICB2_IC8    0x80
+#define E1_ICB2_IC9    0x40
+#define E1_ICB2_IC10   0x20
+#define E1_ICB2_IC11   0x10
+#define E1_ICB2_IC12   0x08
+#define E1_ICB2_IC13   0x04
+#define E1_ICB2_IC14   0x02
+#define E1_ICB2_IC15   0x01
+
+#define E1_ICB3_IC16   0x80
+#define E1_ICB3_IC17   0x40
+#define E1_ICB3_IC18   0x20
+#define E1_ICB3_IC19   0x10
+#define E1_ICB3_IC20   0x08
+#define E1_ICB3_IC21   0x04
+#define E1_ICB3_IC22   0x02
+#define E1_ICB3_IC23   0x01
+
+#define E1_ICB4_IC24   0x80
+#define E1_ICB4_IC25   0x40
+#define E1_ICB4_IC26   0x20
+#define E1_ICB4_IC27   0x10
+#define E1_ICB4_IC28   0x08
+#define E1_ICB4_IC29   0x04
+#define E1_ICB4_IC30   0x02
+#define E1_ICB4_IC31   0x01
+
+/* ICB1-4 (Idle Channel Register 1-4)
+   ------------------ T1 ---------------------------- */
+
+#define T1_ICB1_IC1    0x80
+#define T1_ICB1_IC2    0x40
+#define T1_ICB1_IC3    0x20
+#define T1_ICB1_IC4    0x10
+#define T1_ICB1_IC5    0x08
+#define T1_ICB1_IC6    0x04
+#define T1_ICB1_IC7    0x02
+#define T1_ICB1_IC8    0x01
+
+#define T1_ICB2_IC9    0x80
+#define T1_ICB2_IC10   0x40
+#define T1_ICB2_IC11   0x20
+#define T1_ICB2_IC12   0x10
+#define T1_ICB2_IC13   0x08
+#define T1_ICB2_IC14   0x04
+#define T1_ICB2_IC15   0x02
+#define T1_ICB2_IC16   0x01
+
+#define T1_ICB3_IC17   0x80
+#define T1_ICB3_IC18   0x40
+#define T1_ICB3_IC19   0x20
+#define T1_ICB3_IC20   0x10
+#define T1_ICB3_IC21   0x08
+#define T1_ICB3_IC22   0x04
+#define T1_ICB3_IC23   0x02
+#define T1_ICB3_IC24   0x01
+
+/* FMR3 (Framer Mode Register 3)
+   --------------------E1------------------------ */
+
+#define FMR3_CMI        0x08
+#define FMR3_SYNSA      0x04
+#define FMR3_CFRZ       0x02
+#define FMR3_EXTIW      0x01
+
+
+
+/* CCB1-3 (Clear Channel Register)
+   ------------------- T1 ----------------------- */
+
+#define CCB1_CH1        0x80
+#define CCB1_CH2        0x40
+#define CCB1_CH3        0x20
+#define CCB1_CH4        0x10
+#define CCB1_CH5        0x08
+#define CCB1_CH6        0x04
+#define CCB1_CH7        0x02
+#define CCB1_CH8        0x01
+
+#define CCB2_CH9        0x80
+#define CCB2_CH10       0x40
+#define CCB2_CH11       0x20
+#define CCB2_CH12       0x10
+#define CCB2_CH13       0x08
+#define CCB2_CH14       0x04
+#define CCB2_CH15       0x02
+#define CCB2_CH16       0x01
+
+#define CCB3_CH17       0x80
+#define CCB3_CH18       0x40
+#define CCB3_CH19       0x20
+#define CCB3_CH20       0x10
+#define CCB3_CH21       0x08
+#define CCB3_CH22       0x04
+#define CCB3_CH23       0x02
+#define CCB3_CH24       0x01
+
+
+/* LIM0/1 (Line Interface Mode 0/1)
+   ------------------- E1 & T1 --------------------------- */
+
+#define LIM0_XFB        0x80
+#define LIM0_XDOS       0x40
+#define LIM0_SCL1       0x20
+#define LIM0_SCL0       0x10
+#define LIM0_EQON       0x08
+#define LIM0_ELOS       0x04
+#define LIM0_LL         0x02
+#define LIM0_MAS        0x01
+
+#define LIM1_EFSC       0x80
+#define LIM1_RIL2       0x40
+#define LIM1_RIL1       0x20
+#define LIM1_RIL0       0x10
+#define LIM1_DCOC       0x08
+#define LIM1_JATT       0x04
+#define LIM1_RL         0x02
+#define LIM1_DRS        0x01
+
+
+/* PCDR (Pulse Count Detection Register(Read/Write))
+   ------------------ E1 & T1 ------------------------- */
+
+#define PCDR_PCD7      0x80
+#define PCDR_PCD6      0x40
+#define PCDR_PCD5      0x20
+#define PCDR_PCD4      0x10
+#define PCDR_PCD3      0x08
+#define PCDR_PCD2      0x04
+#define PCDR_PCD1      0x02
+#define PCDR_PCD0      0x01
+
+#define PCRR_PCR7      0x80
+#define PCRR_PCR6      0x40
+#define PCRR_PCR5      0x20
+#define PCRR_PCR4      0x10
+#define PCRR_PCR3      0x08
+#define PCRR_PCR2      0x04
+#define PCRR_PCR1      0x02
+#define PCRR_PCR0      0x01
+
+
+/* LIM2 (Line Interface Mode 2)
+
+   ------------------ E1 & T1 ---------------------------- */
+
+#define LIM2_DJA2      0x20
+#define LIM2_DJA1      0x10
+#define LIM2_LOS2      0x02
+#define LIM2_LOS1      0x01
+
+/* LCR1 (Loop Code Register 1) */
+
+#define LCR1_EPRM      0x80
+#define        LCR1_XPRBS      0x40
+
+/* SIC1 (System Interface Control 1) */
+#define SIC1_SRSC      0x80
+#define SIC1_RBS1      0x20
+#define SIC1_RBS0      0x10
+#define SIC1_SXSC      0x08
+#define SIC1_XBS1      0x02
+#define SIC1_XBS0      0x01
+
+/* DEC (Disable Error Counter)
+   ------------------ E1 & T1 ---------------------------- */
+
+#define DEC_DCEC3       0x20
+#define DEC_DBEC        0x10
+#define DEC_DCEC1       0x08
+#define DEC_DCEC        0x08
+#define DEC_DEBC        0x04
+#define DEC_DCVC        0x02
+#define DEC_DFEC        0x01
+
+
+/* FALC Register Bits (Receive Mode)
+   ---------------------------------------------------------------------------- */
+
+
+/* FRS0/1 (Framer Receive Status Register 0/1)
+   ----------------- E1 & T1 ---------------------------------- */
+
+#define FRS0_LOS        0x80
+#define FRS0_AIS        0x40
+#define FRS0_LFA        0x20
+#define FRS0_RRA        0x10
+#define FRS0_API        0x08
+#define FRS0_NMF        0x04
+#define FRS0_LMFA       0x02
+#define FRS0_FSRF       0x01
+
+#define FRS1_TS16RA     0x40
+#define FRS1_TS16LOS    0x20
+#define FRS1_TS16AIS    0x10
+#define FRS1_TS16LFA    0x08
+#define FRS1_EXZD       0x80
+#define FRS1_LLBDD      0x10
+#define FRS1_LLBAD      0x08
+#define FRS1_XLS        0x02
+#define FRS1_XLO        0x01
+#define FRS1_PDEN      0x40
+
+/* FRS2/3 (Framer Receive Status Register 2/3)
+   ----------------- T1 ---------------------------------- */
+
+#define FRS2_ESC2       0x80
+#define FRS2_ESC1       0x40
+#define FRS2_ESC0       0x20
+
+#define FRS3_FEH5       0x20
+#define FRS3_FEH4       0x10
+#define FRS3_FEH3       0x08
+#define FRS3_FEH2       0x04
+#define FRS3_FEH1       0x02
+#define FRS3_FEH0       0x01
+
+
+/* RSW (Receive Service Word Pulseframe)
+   ----------------- E1 ------------------------------ */
+
+#define RSW_RSI         0x80
+#define RSW_RRA         0x20
+#define RSW_RYO         0x10
+#define RSW_RY1         0x08
+#define RSW_RY2         0x04
+#define RSW_RY3         0x02
+#define RSW_RY4         0x01
+
+
+/* RSP (Receive Spare Bits / Additional Status)
+   ---------------- E1 ------------------------------- */
+
+#define RSP_SI1         0x80
+#define RSP_SI2         0x40
+#define RSP_LLBDD      0x10
+#define RSP_LLBAD      0x08
+#define RSP_RSIF        0x04
+#define RSP_RS13        0x02
+#define RSP_RS15        0x01
+
+
+/* FECL (Framing Error Counter)
+   ---------------- E1 & T1 -------------------------- */
+
+#define FECL_FE7        0x80
+#define FECL_FE6        0x40
+#define FECL_FE5        0x20
+#define FECL_FE4        0x10
+#define FECL_FE3        0x08
+#define FECL_FE2        0x04
+#define FECL_FE1        0x02
+#define FECL_FE0        0x01
+
+#define FECH_FE15       0x80
+#define FECH_FE14       0x40
+#define FECH_FE13       0x20
+#define FECH_FE12       0x10
+#define FECH_FE11       0x08
+#define FECH_FE10       0x04
+#define FECH_FE9        0x02
+#define FECH_FE8        0x01
+
+
+/* CVCl (Code Violation Counter)
+   ----------------- E1 ------------------------- */
+
+#define CVCL_CV7        0x80
+#define CVCL_CV6        0x40
+#define CVCL_CV5        0x20
+#define CVCL_CV4        0x10
+#define CVCL_CV3        0x08
+#define CVCL_CV2        0x04
+#define CVCL_CV1        0x02
+#define CVCL_CV0        0x01
+
+#define CVCH_CV15       0x80
+#define CVCH_CV14       0x40
+#define CVCH_CV13       0x20
+#define CVCH_CV12       0x10
+#define CVCH_CV11       0x08
+#define CVCH_CV10       0x04
+#define CVCH_CV9        0x02
+#define CVCH_CV8        0x01
+
+
+/* CEC1-3L (CRC Error Counter)
+   ------------------ E1 ----------------------------- */
+
+#define CEC1L_CR7       0x80
+#define CEC1L_CR6       0x40
+#define CEC1L_CR5       0x20
+#define CEC1L_CR4       0x10
+#define CEC1L_CR3       0x08
+#define CEC1L_CR2       0x04
+#define CEC1L_CR1       0x02
+#define CEC1L_CR0       0x01
+
+#define CEC1H_CR15      0x80
+#define CEC1H_CR14      0x40
+#define CEC1H_CR13      0x20
+#define CEC1H_CR12      0x10
+#define CEC1H_CR11      0x08
+#define CEC1H_CR10      0x04
+#define CEC1H_CR9       0x02
+#define CEC1H_CR8       0x01
+
+#define CEC2L_CR7       0x80
+#define CEC2L_CR6       0x40
+#define CEC2L_CR5       0x20
+#define CEC2L_CR4       0x10
+#define CEC2L_CR3       0x08
+#define CEC2L_CR2       0x04
+#define CEC2L_CR1       0x02
+#define CEC2L_CR0       0x01
+
+#define CEC2H_CR15      0x80
+#define CEC2H_CR14      0x40
+#define CEC2H_CR13      0x20
+#define CEC2H_CR12      0x10
+#define CEC2H_CR11      0x08
+#define CEC2H_CR10      0x04
+#define CEC2H_CR9       0x02
+#define CEC2H_CR8       0x01
+
+#define CEC3L_CR7       0x80
+#define CEC3L_CR6       0x40
+#define CEC3L_CR5       0x20
+#define CEC3L_CR4       0x10
+#define CEC3L_CR3       0x08
+#define CEC3L_CR2       0x04
+#define CEC3L_CR1       0x02
+#define CEC3L_CR0       0x01
+
+#define CEC3H_CR15      0x80
+#define CEC3H_CR14      0x40
+#define CEC3H_CR13      0x20
+#define CEC3H_CR12      0x10
+#define CEC3H_CR11      0x08
+#define CEC3H_CR10      0x04
+#define CEC3H_CR9       0x02
+#define CEC3H_CR8       0x01
+
+
+/* CECL (CRC Error Counter)
+
+   ------------------ T1 ----------------------------- */
+
+#define CECL_CR7        0x80
+#define CECL_CR6        0x40
+#define CECL_CR5        0x20
+#define CECL_CR4        0x10
+#define CECL_CR3        0x08
+#define CECL_CR2        0x04
+#define CECL_CR1        0x02
+#define CECL_CR0        0x01
+
+#define CECH_CR15       0x80
+#define CECH_CR14       0x40
+#define CECH_CR13       0x20
+#define CECH_CR12       0x10
+#define CECH_CR11       0x08
+#define CECH_CR10       0x04
+#define CECH_CR9        0x02
+#define CECH_CR8        0x01
+
+/* EBCL (E Bit Error Counter)
+   ------------------- E1 & T1 ------------------------- */
+
+#define EBCL_EB7        0x80
+#define EBCL_EB6        0x40
+#define EBCL_EB5        0x20
+#define EBCL_EB4        0x10
+#define EBCL_EB3        0x08
+#define EBCL_EB2        0x04
+#define EBCL_EB1        0x02
+#define EBCL_EB0        0x01
+
+#define EBCH_EB15       0x80
+#define EBCH_EB14       0x40
+#define EBCH_EB13       0x20
+#define EBCH_EB12       0x10
+#define EBCH_EB11       0x08
+#define EBCH_EB10       0x04
+#define EBCH_EB9        0x02
+#define EBCH_EB8        0x01
+
+
+/* RSA4-8 (Receive Sa4-8-Bit Register)
+   -------------------- E1 --------------------------- */
+
+#define RSA4_RS47       0x80
+#define RSA4_RS46       0x40
+#define RSA4_RS45       0x20
+#define RSA4_RS44       0x10
+#define RSA4_RS43       0x08
+#define RSA4_RS42       0x04
+#define RSA4_RS41       0x02
+#define RSA4_RS40       0x01
+
+#define RSA5_RS57       0x80
+#define RSA5_RS56       0x40
+#define RSA5_RS55       0x20
+#define RSA5_RS54       0x10
+#define RSA5_RS53       0x08
+#define RSA5_RS52       0x04
+#define RSA5_RS51       0x02
+#define RSA5_RS50       0x01
+
+#define RSA6_RS67       0x80
+#define RSA6_RS66       0x40
+#define RSA6_RS65       0x20
+#define RSA6_RS64       0x10
+#define RSA6_RS63       0x08
+#define RSA6_RS62       0x04
+#define RSA6_RS61       0x02
+#define RSA6_RS60       0x01
+
+#define RSA7_RS77       0x80
+#define RSA7_RS76       0x40
+#define RSA7_RS75       0x20
+#define RSA7_RS74       0x10
+#define RSA7_RS73       0x08
+#define RSA7_RS72       0x04
+#define RSA7_RS71       0x02
+#define RSA7_RS70       0x01
+
+#define RSA8_RS87       0x80
+#define RSA8_RS86       0x40
+#define RSA8_RS85       0x20
+#define RSA8_RS84       0x10
+#define RSA8_RS83       0x08
+#define RSA8_RS82       0x04
+#define RSA8_RS81       0x02
+#define RSA8_RS80       0x01
+
+/* RSA6S (Receive Sa6 Bit Status Register)
+   ------------------------ T1 ------------------------- */
+
+#define RSA6S_SX        0x20
+#define RSA6S_SF        0x10
+#define RSA6S_SE        0x08
+#define RSA6S_SC        0x04
+#define RSA6S_SA        0x02
+#define RSA6S_S8        0x01
+
+
+/* RDL1-3 Receive DL-Bit Register1-3)
+   ------------------------ T1 ------------------------- */
+
+#define RDL1_RDL17      0x80
+#define RDL1_RDL16      0x40
+#define RDL1_RDL15      0x20
+#define RDL1_RDL14      0x10
+#define RDL1_RDL13      0x08
+#define RDL1_RDL12      0x04
+#define RDL1_RDL11      0x02
+#define RDL1_RDL10      0x01
+
+#define RDL2_RDL27      0x80
+#define RDL2_RDL26      0x40
+#define RDL2_RDL25      0x20
+#define RDL2_RDL24      0x10
+#define RDL2_RDL23      0x08
+#define RDL2_RDL22      0x04
+#define RDL2_RDL21      0x02
+#define RDL2_RDL20      0x01
+
+#define RDL3_RDL37      0x80
+#define RDL3_RDL36      0x40
+#define RDL3_RDL35      0x20
+#define RDL3_RDL34      0x10
+#define RDL3_RDL33      0x08
+#define RDL3_RDL32      0x04
+#define RDL3_RDL31      0x02
+#define RDL3_RDL30      0x01
+
+
+/* SIS (Signaling Status Register)
+
+   -------------------- E1 & T1 -------------------------- */
+
+#define SIS_XDOV        0x80
+#define SIS_XFW         0x40
+#define SIS_XREP        0x20
+#define SIS_RLI         0x08
+#define SIS_CEC         0x04
+#define SIS_BOM         0x01
+
+
+/* RSIS (Receive Signaling Status Register)
+
+   -------------------- E1 & T1 --------------------------- */
+
+#define RSIS_VFR        0x80
+#define RSIS_RDO        0x40
+#define RSIS_CRC16      0x20
+#define RSIS_RAB        0x10
+#define RSIS_HA1        0x08
+#define RSIS_HA0        0x04
+#define RSIS_HFR        0x02
+#define RSIS_LA         0x01
+
+
+/* RBCL/H (Receive Byte Count Low/High)
+
+   ------------------- E1 & T1 ----------------------- */
+
+#define RBCL_RBC7       0x80
+#define RBCL_RBC6       0x40
+#define RBCL_RBC5       0x20
+#define RBCL_RBC4       0x10
+#define RBCL_RBC3       0x08
+#define RBCL_RBC2       0x04
+#define RBCL_RBC1       0x02
+#define RBCL_RBC0       0x01
+
+#define RBCH_OV         0x10
+#define RBCH_RBC11      0x08
+#define RBCH_RBC10      0x04
+#define RBCH_RBC9       0x02
+#define RBCH_RBC8       0x01
+
+
+/* ISR1-3  (Interrupt Status Register 1-3)
+
+   ------------------ E1 & T1 ------------------------------ */
+
+#define  FISR0_RME     0x80
+#define  FISR0_RFS     0x40
+#define  FISR0_T8MS    0x20
+#define  FISR0_ISF     0x20
+#define  FISR0_RMB     0x10
+#define  FISR0_CASC    0x08
+#define  FISR0_RSC     0x08
+#define  FISR0_CRC6    0x04
+#define  FISR0_CRC4    0x04
+#define  FISR0_PDEN    0x02
+#define  FISR0_RPF     0x01
+
+#define  FISR1_CASE    0x80
+#define  FISR1_LLBSC   0x80
+#define  FISR1_RDO     0x40
+#define  FISR1_ALLS    0x20
+#define  FISR1_XDU     0x10
+#define  FISR1_XMB     0x08
+#define  FISR1_XLSC    0x02
+#define  FISR1_XPR     0x01
+
+#define  FISR2_FAR     0x80
+#define  FISR2_LFA     0x40
+#define  FISR2_MFAR    0x20
+#define  FISR2_T400MS  0x10
+#define  FISR2_LMFA    0x10
+#define  FISR2_AIS     0x08
+#define  FISR2_LOS     0x04
+#define  FISR2_RAR     0x02
+#define  FISR2_RA      0x01
+
+#define  FISR3_ES      0x80
+#define  FISR3_SEC     0x40
+#define  FISR3_LMFA16  0x20
+#define  FISR3_AIS16   0x10
+#define  FISR3_RA16    0x08
+#define  FISR3_API     0x04
+#define  FISR3_XSLP    0x20
+#define  FISR3_XSLN    0x10
+#define  FISR3_LLBSC   0x08
+#define  FISR3_XRS     0x04
+#define  FISR3_SLN     0x02
+#define  FISR3_SLP     0x01
+
+
+/* GIS  (Global Interrupt Status Register)
+
+   --------------------- E1 & T1 --------------------- */
+
+#define  GIS_ISR3      0x08
+#define  GIS_ISR2      0x04
+#define  GIS_ISR1      0x02
+#define  GIS_ISR0      0x01
+
+
+/* VSTR  (Version Status Register)
+
+   --------------------- E1 & T1 --------------------- */
+
+#define  VSTR_VN3      0x08
+#define  VSTR_VN2      0x04
+#define  VSTR_VN1      0x02
+#define  VSTR_VN0      0x01
+
+
+/*>>>>>>>>>>>>>>>>>>>>>  Local Control Structures  <<<<<<<<<<<<<<<<<<<<<<<<< */
+
+/* Write-only Registers (E1/T1 control mode write registers) */
+#define XFIFOH 0x00            /* Tx FIFO High Byte */
+#define XFIFOL 0x01            /* Tx FIFO Low Byte */
+#define CMDR   0x02            /* Command Reg */
+#define DEC    0x60            /* Disable Error Counter */
+#define TEST2  0x62            /* Manuf. Test Reg 2 */
+#define XS(nbr)        (0x70 + (nbr))  /* Tx CAS Reg (0 to 15) */
+
+/* Read-write Registers (E1/T1 status mode read registers) */
+#define MODE   0x03    /* Mode Reg */
+#define RAH1   0x04    /* Receive Address High 1 */
+#define RAH2   0x05    /* Receive Address High 2 */
+#define RAL1   0x06    /* Receive Address Low 1 */
+#define RAL2   0x07    /* Receive Address Low 2 */
+#define IPC    0x08    /* Interrupt Port Configuration */
+#define CCR1   0x09    /* Common Configuration Reg 1 */
+#define CCR3   0x0A    /* Common Configuration Reg 3 */
+#define PRE    0x0B    /* Preamble Reg */
+#define RTR1   0x0C    /* Receive Timeslot Reg 1 */
+#define RTR2   0x0D    /* Receive Timeslot Reg 2 */
+#define RTR3   0x0E    /* Receive Timeslot Reg 3 */
+#define RTR4   0x0F    /* Receive Timeslot Reg 4 */
+#define TTR1   0x10    /* Transmit Timeslot Reg 1 */
+#define TTR2   0x11    /* Transmit Timeslot Reg 2 */
+#define TTR3   0x12    /* Transmit Timeslot Reg 3 */
+#define TTR4   0x13    /* Transmit Timeslot Reg 4 */
+#define IMR0   0x14    /* Interrupt Mask Reg 0 */
+#define IMR1   0x15    /* Interrupt Mask Reg 1 */
+#define IMR2   0x16    /* Interrupt Mask Reg 2 */
+#define IMR3   0x17    /* Interrupt Mask Reg 3 */
+#define IMR4   0x18    /* Interrupt Mask Reg 4 */
+#define IMR5   0x19    /* Interrupt Mask Reg 5 */
+#define FMR0   0x1A    /* Framer Mode Reigster 0 */
+#define FMR1   0x1B    /* Framer Mode Reigster 1 */
+#define FMR2   0x1C    /* Framer Mode Reigster 2 */
+#define LOOP   0x1D    /* Channel Loop Back */
+#define XSW    0x1E    /* Transmit Service Word */
+#define FMR4   0x1E    /* Framer Mode Reg 4 */
+#define XSP    0x1F    /* Transmit Spare Bits */
+#define FMR5   0x1F    /* Framer Mode Reg 5 */
+#define XC0    0x20    /* Transmit Control 0 */
+#define XC1    0x21    /* Transmit Control 1 */
+#define RC0    0x22    /* Receive Control 0 */
+#define RC1    0x23    /* Receive Control 1 */
+#define XPM0   0x24    /* Transmit Pulse Mask 0 */
+#define XPM1   0x25    /* Transmit Pulse Mask 1 */
+#define XPM2   0x26    /* Transmit Pulse Mask 2 */
+#define TSWM   0x27    /* Transparent Service Word Mask */
+#define TEST1  0x28    /* Manuf. Test Reg 1 */
+#define IDLE   0x29    /* Idle Channel Code */
+#define XSA4    0x2A   /* Transmit SA4 Bit Reg */
+#define XDL1   0x2A    /* Transmit DL-Bit Reg 2 */
+#define XSA5    0x2B   /* Transmit SA4 Bit Reg */
+#define XDL2   0x2B    /* Transmit DL-Bit Reg 2 */
+#define XSA6    0x2C   /* Transmit SA4 Bit Reg */
+#define XDL3   0x2C    /* Transmit DL-Bit Reg 2 */
+#define XSA7    0x2D   /* Transmit SA4 Bit Reg */
+#define CCB1   0x2D    /* Clear Channel Reg 1 */
+#define XSA8    0x2E   /* Transmit SA4 Bit Reg */
+#define CCB2   0x2E    /* Clear Channel Reg 2 */
+#define FMR3   0x2F    /* Framer Mode Reg. 3 */
+#define CCB3   0x2F    /* Clear Channel Reg 3 */
+#define ICB1   0x30    /* Idle Channel Reg 1 */
+#define ICB2   0x31    /* Idle Channel Reg 2 */
+#define ICB3   0x32    /* Idle Channel Reg 3 */
+#define ICB4   0x33    /* Idle Channel Reg 4 */
+#define LIM0   0x34    /* Line Interface Mode 0 */
+#define LIM1   0x35    /* Line Interface Mode 1 */
+#define PCDR   0x36    /* Pulse Count Detection */
+#define PCRR   0x37    /* Pulse Count Recovery */
+#define LIM2   0x38    /* Line Interface Mode Reg 2 */
+#define LCR1   0x39    /* Loop Code Reg 1 */
+#define LCR2   0x3A    /* Loop Code Reg 2 */
+#define LCR3   0x3B    /* Loop Code Reg 3 */
+#define SIC1   0x3C    /* System Interface Control 1 */
+
+/* Read-only Registers (E1/T1 control mode read registers) */
+#define RFIFOH 0x00            /* Receive FIFO */
+#define RFIFOL 0x01            /* Receive FIFO */
+#define FRS0   0x4C            /* Framer Receive Status 0 */
+#define FRS1   0x4D            /* Framer Receive Status 1 */
+#define RSW    0x4E            /* Receive Service Word */
+#define FRS2   0x4E            /* Framer Receive Status 2 */
+#define RSP    0x4F            /* Receive Spare Bits */
+#define FRS3   0x4F            /* Framer Receive Status 3 */
+#define FECL   0x50            /* Framing Error Counter */
+#define FECH   0x51            /* Framing Error Counter */
+#define CVCL   0x52            /* Code Violation Counter */
+#define CVCH   0x53            /* Code Violation Counter */
+#define CECL   0x54            /* CRC Error Counter 1 */
+#define CECH   0x55            /* CRC Error Counter 1 */
+#define EBCL   0x56            /* E-Bit Error Counter */
+#define EBCH   0x57            /* E-Bit Error Counter */
+#define BECL   0x58            /* Bit Error Counter Low */
+#define BECH   0x59            /* Bit Error Counter Low */
+#define CEC3   0x5A            /* CRC Error Counter 3 (16-bit) */
+#define RSA4   0x5C            /* Receive SA4 Bit Reg */
+#define RDL1   0x5C            /* Receive DL-Bit Reg 1 */
+#define RSA5   0x5D            /* Receive SA5 Bit Reg */
+#define RDL2   0x5D            /* Receive DL-Bit Reg 2 */
+#define RSA6   0x5E            /* Receive SA6 Bit Reg */
+#define RDL3   0x5E            /* Receive DL-Bit Reg 3 */
+#define RSA7   0x5F            /* Receive SA7 Bit Reg */
+#define RSA8   0x60            /* Receive SA8 Bit Reg */
+#define RSA6S  0x61            /* Receive SA6 Bit Status Reg */
+#define TSR0   0x62            /* Manuf. Test Reg 0 */
+#define TSR1   0x63            /* Manuf. Test Reg 1 */
+#define SIS    0x64            /* Signaling Status Reg */
+#define RSIS   0x65            /* Receive Signaling Status Reg */
+#define RBCL   0x66            /* Receive Byte Control */
+#define RBCH   0x67            /* Receive Byte Control */
+#define FISR0  0x68            /* Interrupt Status Reg 0 */
+#define FISR1  0x69            /* Interrupt Status Reg 1 */
+#define FISR2  0x6A            /* Interrupt Status Reg 2 */
+#define FISR3  0x6B            /* Interrupt Status Reg 3 */
+#define GIS    0x6E            /* Global Interrupt Status */
+#define VSTR   0x6F            /* Version Status */
+#define RS(nbr)        (0x70 + (nbr))  /* Rx CAS Reg (0 to 15) */
+
+#endif /* _FALC_LH_H */
+
 
--- /dev/null
+/*
+ * pc300.h     Cyclades-PC300(tm) Kernel API Definitions.
+ *
+ * Author:     Ivan Passos <ivan@cyclades.com>
+ *
+ * Copyright:  (c) 1999-2002 Cyclades Corp.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *
+ * $Log: pc300.h,v $
+ * Revision 3.12  2002/03/07 14:17:09  henrique
+ * License data fixed
+ *
+ * Revision 3.11  2002/01/28 21:09:39  daniela
+ * Included ';' after pc300hw.bus.
+ *
+ * Revision 3.10  2002/01/17 17:58:52  ivan
+ * Support for PC300-TE/M (PMC).
+ *
+ * Revision 3.9  2001/09/28 13:30:53  daniela
+ * Renamed dma_start routine to rx_dma_start.
+ *
+ * Revision 3.8  2001/09/24 13:03:45  daniela
+ * Fixed BOF interrupt treatment. Created dma_start routine.
+ *
+ * Revision 3.7  2001/08/10 17:19:58  daniela
+ * Fixed IOCTLs defines.
+ *
+ * Revision 3.6  2001/07/18 19:24:42  daniela
+ * Included kernel version.
+ *
+ * Revision 3.5  2001/07/05 18:38:08  daniela
+ * DMA transmission bug fix.
+ *
+ * Revision 3.4  2001/06/26 17:10:40  daniela
+ * New configuration parameters (line code, CRC calculation and clock).
+ *
+ * Revision 3.3  2001/06/22 13:13:02  regina
+ * MLPPP implementation
+ *
+ * Revision 3.2  2001/06/18 17:56:09  daniela
+ * Increased DEF_MTU and TX_QUEUE_LEN.
+ *
+ * Revision 3.1  2001/06/15 12:41:10  regina
+ * upping major version number
+ *
+ * Revision 1.1.1.1  2001/06/13 20:25:06  daniela
+ * PC300 initial CVS version (3.4.0-pre1)
+ *
+ * Revision 2.3 2001/03/05 daniela
+ * Created struct pc300conf, to provide the hardware information to pc300util.
+ * Inclusion of 'alloc_ramsize' field on structure 'pc300hw'.
+ * 
+ * Revision 2.2 2000/12/22 daniela
+ * Structures and defines to support pc300util: statistics, status, 
+ * loopback tests, trace.
+ * 
+ * Revision 2.1 2000/09/28 ivan
+ * Inclusion of 'iophys' and 'iosize' fields on structure 'pc300hw', to 
+ * allow release of I/O region at module unload.
+ * Changed location of include files.
+ *
+ * Revision 2.0 2000/03/27 ivan
+ * Added support for the PC300/TE cards.
+ *
+ * Revision 1.1 2000/01/31 ivan
+ * Replaced 'pc300[drv|sca].h' former PC300 driver include files.
+ *
+ * Revision 1.0 1999/12/16 ivan
+ * First official release.
+ * Inclusion of 'nchan' field on structure 'pc300hw', to allow variable 
+ * number of ports per card.
+ * Inclusion of 'if_ptr' field on structure 'pc300dev'.
+ *
+ * Revision 0.6 1999/11/17 ivan
+ * Changed X.25-specific function names to comply with adopted convention.
+ *
+ * Revision 0.5 1999/11/16 Daniela Squassoni
+ * X.25 support.
+ *
+ * Revision 0.4 1999/11/15 ivan
+ * Inclusion of 'clock' field on structure 'pc300hw'.
+ *
+ * Revision 0.3 1999/11/10 ivan
+ * IOCTL name changing.
+ * Inclusion of driver function prototypes.
+ *
+ * Revision 0.2 1999/11/03 ivan
+ * Inclusion of 'tx_skb' and union 'ifu' on structure 'pc300dev'.
+ *
+ * Revision 0.1 1999/01/15 ivan
+ * Initial version.
+ *
+ */
+
+#ifndef        _PC300_H
+#define        _PC300_H
+
+#include <linux/hdlc.h>
+#include "hd64572.h"
+#include "pc300-falc-lh.h"
+
+#define PC300_PROTO_MLPPP 1
+
+#define        PC300_MAXCHAN   2       /* Number of channels per card */
+
+#define        PC300_RAMSIZE   0x40000 /* RAM window size (256Kb) */
+#define        PC300_FALCSIZE  0x400   /* FALC window size (1Kb) */
+
+#define PC300_OSC_CLOCK        24576000
+#define PC300_PCI_CLOCK        33000000
+
+#define BD_DEF_LEN     0x0800  /* DMA buffer length (2KB) */
+#define DMA_TX_MEMSZ   0x8000  /* Total DMA Tx memory size (32KB/ch) */
+#define DMA_RX_MEMSZ   0x10000 /* Total DMA Rx memory size (64KB/ch) */
+
+#define N_DMA_TX_BUF   (DMA_TX_MEMSZ / BD_DEF_LEN)     /* DMA Tx buffers */
+#define N_DMA_RX_BUF   (DMA_RX_MEMSZ / BD_DEF_LEN)     /* DMA Rx buffers */
+
+/* DMA Buffer Offsets */
+#define DMA_TX_BASE    ((N_DMA_TX_BUF + N_DMA_RX_BUF) *        \
+                        PC300_MAXCHAN * sizeof(pcsca_bd_t))
+#define DMA_RX_BASE    (DMA_TX_BASE + PC300_MAXCHAN*DMA_TX_MEMSZ)
+
+/* DMA Descriptor Offsets */
+#define DMA_TX_BD_BASE 0x0000
+#define DMA_RX_BD_BASE (DMA_TX_BD_BASE + ((PC300_MAXCHAN*DMA_TX_MEMSZ / \
+                               BD_DEF_LEN) * sizeof(pcsca_bd_t)))
+
+/* DMA Descriptor Macros */
+#define TX_BD_ADDR(chan, n)    (DMA_TX_BD_BASE + \
+                                ((N_DMA_TX_BUF*chan) + n) * sizeof(pcsca_bd_t))
+#define RX_BD_ADDR(chan, n)    (DMA_RX_BD_BASE + \
+                                ((N_DMA_RX_BUF*chan) + n) * sizeof(pcsca_bd_t))
+
+/* Macro to access the FALC registers (TE only) */
+#define F_REG(reg, chan)       (0x200*(chan) + ((reg)<<2))
+
+/***************************************
+ * Memory access functions/macros      *
+ * (required to support Alpha systems) *
+ ***************************************/
+#define cpc_writeb(port,val)   {writeb((u8)(val),(port)); mb();}
+#define cpc_writew(port,val)   {writew((ushort)(val),(port)); mb();}
+#define cpc_writel(port,val)   {writel((u32)(val),(port)); mb();}
+
+#define cpc_readb(port)                readb(port)
+#define cpc_readw(port)                readw(port)
+#define cpc_readl(port)                readl(port)
+
+/****** Data Structures *****************************************************/
+
+/*
+ *      RUNTIME_9050 - PLX PCI9050-1 local configuration and shared runtime
+ *      registers. This structure can be used to access the 9050 registers
+ *      (memory mapped).
+ */
+struct RUNTIME_9050 {
+       u32 loc_addr_range[4];  /* 00-0Ch : Local Address Ranges */
+       u32 loc_rom_range;      /* 10h : Local ROM Range */
+       u32 loc_addr_base[4];   /* 14-20h : Local Address Base Addrs */
+       u32 loc_rom_base;       /* 24h : Local ROM Base */
+       u32 loc_bus_descr[4];   /* 28-34h : Local Bus Descriptors */
+       u32 rom_bus_descr;      /* 38h : ROM Bus Descriptor */
+       u32 cs_base[4];         /* 3C-48h : Chip Select Base Addrs */
+       u32 intr_ctrl_stat;     /* 4Ch : Interrupt Control/Status */
+       u32 init_ctrl;          /* 50h : EEPROM ctrl, Init Ctrl, etc */
+};
+
+#define PLX_9050_LINT1_ENABLE  0x01
+#define PLX_9050_LINT1_POL     0x02
+#define PLX_9050_LINT1_STATUS  0x04
+#define PLX_9050_LINT2_ENABLE  0x08
+#define PLX_9050_LINT2_POL     0x10
+#define PLX_9050_LINT2_STATUS  0x20
+#define PLX_9050_INTR_ENABLE   0x40
+#define PLX_9050_SW_INTR       0x80
+
+/* Masks to access the init_ctrl PLX register */
+#define        PC300_CLKSEL_MASK               (0x00000004UL)
+#define        PC300_CHMEDIA_MASK(chan)        (0x00000020UL<<(chan*3))
+#define        PC300_CTYPE_MASK                (0x00000800UL)
+
+/* CPLD Registers (base addr = falcbase, TE only) */
+/* CPLD v. 0 */
+#define CPLD_REG1      0x140   /* Chip resets, DCD/CTS status */
+#define CPLD_REG2      0x144   /* Clock enable , LED control */
+/* CPLD v. 2 or higher */
+#define CPLD_V2_REG1   0x100   /* Chip resets, DCD/CTS status */
+#define CPLD_V2_REG2   0x104   /* Clock enable , LED control */
+#define CPLD_ID_REG    0x108   /* CPLD version */
+
+/* CPLD Register bit description: for the FALC bits, they should always be 
+   set based on the channel (use (bit<<(2*ch)) to access the correct bit for 
+   that channel) */
+#define CPLD_REG1_FALC_RESET   0x01
+#define CPLD_REG1_SCA_RESET    0x02
+#define CPLD_REG1_GLOBAL_CLK   0x08
+#define CPLD_REG1_FALC_DCD     0x10
+#define CPLD_REG1_FALC_CTS     0x20
+
+#define CPLD_REG2_FALC_TX_CLK  0x01
+#define CPLD_REG2_FALC_RX_CLK  0x02
+#define CPLD_REG2_FALC_LED1    0x10
+#define CPLD_REG2_FALC_LED2    0x20
+
+/* Structure with FALC-related fields (TE only) */
+#define PC300_FALC_MAXLOOP     0x0000ffff      /* for falc_issue_cmd() */
+
+typedef struct falc {
+       u8 sync;        /* If true FALC is synchronized */
+       u8 active;      /* if TRUE then already active */
+       u8 loop_active; /* if TRUE a line loopback UP was received */
+       u8 loop_gen;    /* if TRUE a line loopback UP was issued */
+
+       u8 num_channels;
+       u8 offset;      /* 1 for T1, 0 for E1 */
+       u8 full_bandwidth;
+
+       u8 xmb_cause;
+       u8 multiframe_mode;
+
+       /* Statistics */
+       u16 pden;       /* Pulse Density violation count */
+       u16 los;        /* Loss of Signal count */
+       u16 losr;       /* Loss of Signal recovery count */
+       u16 lfa;        /* Loss of frame alignment count */
+       u16 farec;      /* Frame Alignment Recovery count */
+       u16 lmfa;       /* Loss of multiframe alignment count */
+       u16 ais;        /* Remote Alarm indication Signal count */
+       u16 sec;        /* One-second timer */
+       u16 es;         /* Errored second */
+       u16 rai;        /* remote alarm received */
+       u16 bec;
+       u16 fec;
+       u16 cvc;
+       u16 cec;
+       u16 ebc;
+
+       /* Status */
+       u8 red_alarm;
+       u8 blue_alarm;
+       u8 loss_fa;
+       u8 yellow_alarm;
+       u8 loss_mfa;
+       u8 prbs;
+} falc_t;
+
+typedef struct falc_status {
+       u8 sync;        /* If true FALC is synchronized */
+       u8 red_alarm;
+       u8 blue_alarm;
+       u8 loss_fa;
+       u8 yellow_alarm;
+       u8 loss_mfa;
+       u8 prbs;
+} falc_status_t;
+
+typedef struct rsv_x21_status {
+       u8 dcd;
+       u8 dsr;
+       u8 cts;
+       u8 rts;
+       u8 dtr;
+} rsv_x21_status_t;
+
+typedef struct pc300stats {
+       int hw_type;
+       u32 line_on;
+       u32 line_off;
+       struct net_device_stats gen_stats;
+       falc_t te_stats;
+} pc300stats_t;
+
+typedef struct pc300status {
+       int hw_type;
+       rsv_x21_status_t gen_status;
+       falc_status_t te_status;
+} pc300status_t;
+
+typedef struct pc300loopback {
+       char loop_type;
+       char loop_on;
+} pc300loopback_t;
+
+typedef struct pc300patterntst {
+       char patrntst_on;       /* 0 - off; 1 - on; 2 - read num_errors */
+       u16 num_errors;
+} pc300patterntst_t;
+
+typedef struct pc300dev {
+       struct pc300ch *chan;
+       u8 trace_on;
+       u32 line_on;            /* DCD(X.21, RSV) / sync(TE) change counters */
+       u32 line_off;
+       char name[16];
+       struct net_device *dev;
+#ifdef CONFIG_PC300_MLPPP
+       void *cpc_tty;  /* information to PC300 TTY driver */
+#endif
+}pc300dev_t;
+
+typedef struct pc300hw {
+       int type;               /* RSV, X21, etc. */
+       int bus;                /* Bus (PCI, PMC, etc.) */
+       int nchan;              /* number of channels */
+       int irq;                /* interrupt request level */
+       u32 clock;              /* Board clock */
+       u8 cpld_id;             /* CPLD ID (TE only) */
+       u16 cpld_reg1;          /* CPLD reg 1 (TE only) */
+       u16 cpld_reg2;          /* CPLD reg 2 (TE only) */
+       u16 gpioc_reg;          /* PLX GPIOC reg */
+       u16 intctl_reg;         /* PLX Int Ctrl/Status reg */
+       u32 iophys;             /* PLX registers I/O base */
+       u32 iosize;             /* PLX registers I/O size */
+       u32 plxphys;            /* PLX registers MMIO base (physical) */
+       void __iomem * plxbase; /* PLX registers MMIO base (virtual) */
+       u32 plxsize;            /* PLX registers MMIO size */
+       u32 scaphys;            /* SCA registers MMIO base (physical) */
+       void __iomem * scabase; /* SCA registers MMIO base (virtual) */
+       u32 scasize;            /* SCA registers MMIO size */
+       u32 ramphys;            /* On-board RAM MMIO base (physical) */
+       void __iomem * rambase; /* On-board RAM MMIO base (virtual) */
+       u32 alloc_ramsize;      /* RAM MMIO size allocated by the PCI bridge */
+       u32 ramsize;            /* On-board RAM MMIO size */
+       u32 falcphys;           /* FALC registers MMIO base (physical) */
+       void __iomem * falcbase;/* FALC registers MMIO base (virtual) */
+       u32 falcsize;           /* FALC registers MMIO size */
+} pc300hw_t;
+
+typedef struct pc300chconf {
+       sync_serial_settings    phys_settings;  /* Clock type/rate (in bps),
+                                                  loopback mode */
+       raw_hdlc_proto          proto_settings; /* Encoding, parity (CRC) */
+       u32 media;              /* HW media (RS232, V.35, etc.) */
+       u32 proto;              /* Protocol (PPP, X.25, etc.) */
+
+       /* TE-specific parameters */
+       u8 lcode;               /* Line Code (AMI, B8ZS, etc.) */
+       u8 fr_mode;             /* Frame Mode (ESF, D4, etc.) */
+       u8 lbo;                 /* Line Build Out */
+       u8 rx_sens;             /* Rx Sensitivity (long- or short-haul) */
+       u32 tslot_bitmap;       /* bit[i]=1  =>  timeslot _i_ is active */
+} pc300chconf_t;
+
+typedef struct pc300ch {
+       struct pc300 *card;
+       int channel;
+       pc300dev_t d;
+       pc300chconf_t conf;
+       u8 tx_first_bd; /* First TX DMA block descr. w/ data */
+       u8 tx_next_bd;  /* Next free TX DMA block descriptor */
+       u8 rx_first_bd; /* First free RX DMA block descriptor */
+       u8 rx_last_bd;  /* Last free RX DMA block descriptor */
+       u8 nfree_tx_bd; /* Number of free TX DMA block descriptors */
+       falc_t falc;    /* FALC structure (TE only) */
+} pc300ch_t;
+
+typedef struct pc300 {
+       pc300hw_t hw;                   /* hardware config. */
+       pc300ch_t chan[PC300_MAXCHAN];
+       spinlock_t card_lock;
+} pc300_t;
+
+typedef struct pc300conf {
+       pc300hw_t hw;
+       pc300chconf_t conf;
+} pc300conf_t;
+
+/* DEV ioctl() commands */
+#define        N_SPPP_IOCTLS   2
+
+enum pc300_ioctl_cmds {
+       SIOCCPCRESERVED = (SIOCDEVPRIVATE + N_SPPP_IOCTLS),
+       SIOCGPC300CONF,
+       SIOCSPC300CONF,
+       SIOCGPC300STATUS,
+       SIOCGPC300FALCSTATUS,
+       SIOCGPC300UTILSTATS,
+       SIOCGPC300UTILSTATUS,
+       SIOCSPC300TRACE,
+       SIOCSPC300LOOPBACK,
+       SIOCSPC300PATTERNTEST,
+};
+
+/* Loopback types - PC300/TE boards */
+enum pc300_loopback_cmds {
+       PC300LOCLOOP = 1,
+       PC300REMLOOP,
+       PC300PAYLOADLOOP,
+       PC300GENLOOPUP,
+       PC300GENLOOPDOWN,
+};
+
+/* Control Constant Definitions */
+#define        PC300_RSV       0x01
+#define        PC300_X21       0x02
+#define        PC300_TE        0x03
+
+#define        PC300_PCI       0x00
+#define        PC300_PMC       0x01
+
+#define PC300_LC_AMI   0x01
+#define PC300_LC_B8ZS  0x02
+#define PC300_LC_NRZ   0x03
+#define PC300_LC_HDB3  0x04
+
+/* Framing (T1) */
+#define PC300_FR_ESF           0x01
+#define PC300_FR_D4            0x02
+#define PC300_FR_ESF_JAPAN     0x03
+
+/* Framing (E1) */
+#define PC300_FR_MF_CRC4       0x04
+#define PC300_FR_MF_NON_CRC4   0x05
+#define PC300_FR_UNFRAMED      0x06
+
+#define PC300_LBO_0_DB         0x00
+#define PC300_LBO_7_5_DB       0x01
+#define PC300_LBO_15_DB                0x02
+#define PC300_LBO_22_5_DB      0x03
+
+#define PC300_RX_SENS_SH       0x01
+#define PC300_RX_SENS_LH       0x02
+
+#define PC300_TX_TIMEOUT       (2*HZ)
+#define PC300_TX_QUEUE_LEN     100
+#define        PC300_DEF_MTU           1600
+
+/* Function Prototypes */
+int cpc_open(struct net_device *dev);
+
+#endif /* _PC300_H */
 
--- /dev/null
+#define        USE_PCI_CLOCK
+static const char rcsid[] =
+"Revision: 3.4.5 Date: 2002/03/07 ";
+
+/*
+ * pc300.c     Cyclades-PC300(tm) Driver.
+ *
+ * Author:     Ivan Passos <ivan@cyclades.com>
+ * Maintainer: PC300 Maintainer <pc300@cyclades.com>
+ *
+ * Copyright:  (c) 1999-2003 Cyclades Corp.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *     modify it under the terms of the GNU General Public License
+ *     as published by the Free Software Foundation; either version
+ *     2 of the License, or (at your option) any later version.
+ *     
+ *     Using tabstop = 4.
+ * 
+ * $Log: pc300_drv.c,v $
+ * Revision 3.23  2002/03/20 13:58:40  henrique
+ * Fixed ortographic mistakes
+ *
+ * Revision 3.22  2002/03/13 16:56:56  henrique
+ * Take out the debug messages
+ *
+ * Revision 3.21  2002/03/07 14:17:09  henrique
+ * License data fixed
+ *
+ * Revision 3.20  2002/01/17 17:58:52  ivan
+ * Support for PC300-TE/M (PMC).
+ *
+ * Revision 3.19  2002/01/03 17:08:47  daniela
+ * Enables DMA reception when the SCA-II disables it improperly.
+ *
+ * Revision 3.18  2001/12/03 18:47:50  daniela
+ * Esthetic changes.
+ *
+ * Revision 3.17  2001/10/19 16:50:13  henrique
+ * Patch to kernel 2.4.12 and new generic hdlc.
+ *
+ * Revision 3.16  2001/10/16 15:12:31  regina
+ * clear statistics
+ *
+ * Revision 3.11 to 3.15  2001/10/11 20:26:04  daniela
+ * More DMA fixes for noisy lines.
+ * Return the size of bad frames in dma_get_rx_frame_size, so that the Rx buffer
+ * descriptors can be cleaned by dma_buf_read (called in cpc_net_rx).
+ * Renamed dma_start routine to rx_dma_start. Improved Rx statistics.
+ * Fixed BOF interrupt treatment. Created dma_start routine.
+ * Changed min and max to cpc_min and cpc_max.
+ *
+ * Revision 3.10  2001/08/06 12:01:51  regina
+ * Fixed problem in DSR_DE bit.
+ *
+ * Revision 3.9  2001/07/18 19:27:26  daniela
+ * Added some history comments.
+ *
+ * Revision 3.8  2001/07/12 13:11:19  regina
+ * bug fix - DCD-OFF in pc300 tty driver
+ *
+ * Revision 3.3 to 3.7  2001/07/06 15:00:20  daniela
+ * Removing kernel 2.4.3 and previous support.
+ * DMA transmission bug fix.
+ * MTU check in cpc_net_rx fixed.
+ * Boot messages reviewed.
+ * New configuration parameters (line code, CRC calculation and clock).
+ *
+ * Revision 3.2 2001/06/22 13:13:02  regina
+ * MLPPP implementation. Changed the header of message trace to include
+ * the device name. New format : "hdlcX[R/T]: ".
+ * Default configuration changed.
+ *
+ * Revision 3.1 2001/06/15 regina
+ * in cpc_queue_xmit, netif_stop_queue is called if don't have free descriptor
+ * upping major version number
+ *
+ * Revision 1.1.1.1  2001/06/13 20:25:04  daniela
+ * PC300 initial CVS version (3.4.0-pre1)
+ *
+ * Revision 3.0.1.2 2001/06/08 daniela
+ * Did some changes in the DMA programming implementation to avoid the 
+ * occurrence of a SCA-II bug when CDA is accessed during a DMA transfer.
+ *
+ * Revision 3.0.1.1 2001/05/02 daniela
+ * Added kernel 2.4.3 support.
+ * 
+ * Revision 3.0.1.0 2001/03/13 daniela, henrique
+ * Added Frame Relay Support.
+ * Driver now uses HDLC generic driver to provide protocol support.
+ * 
+ * Revision 3.0.0.8 2001/03/02 daniela
+ * Fixed ram size detection. 
+ * Changed SIOCGPC300CONF ioctl, to give hw information to pc300util.
+ * 
+ * Revision 3.0.0.7 2001/02/23 daniela
+ * netif_stop_queue called before the SCA-II transmition commands in 
+ * cpc_queue_xmit, and with interrupts disabled to avoid race conditions with 
+ * transmition interrupts.
+ * Fixed falc_check_status for Unframed E1.
+ * 
+ * Revision 3.0.0.6 2000/12/13 daniela
+ * Implemented pc300util support: trace, statistics, status and loopback
+ * tests for the PC300 TE boards.
+ * 
+ * Revision 3.0.0.5 2000/12/12 ivan
+ * Added support for Unframed E1.
+ * Implemented monitor mode.
+ * Fixed DCD sensitivity on the second channel.
+ * Driver now complies with new PCI kernel architecture.
+ *
+ * Revision 3.0.0.4 2000/09/28 ivan
+ * Implemented DCD sensitivity.
+ * Moved hardware-specific open to the end of cpc_open, to avoid race
+ * conditions with early reception interrupts.
+ * Included code for [request|release]_mem_region().
+ * Changed location of pc300.h .
+ * Minor code revision (contrib. of Jeff Garzik).
+ *
+ * Revision 3.0.0.3 2000/07/03 ivan
+ * Previous bugfix for the framing errors with external clock made X21
+ * boards stop working. This version fixes it.
+ *
+ * Revision 3.0.0.2 2000/06/23 ivan
+ * Revisited cpc_queue_xmit to prevent race conditions on Tx DMA buffer
+ * handling when Tx timeouts occur.
+ * Revisited Rx statistics.
+ * Fixed a bug in the SCA-II programming that would cause framing errors
+ * when external clock was configured.
+ *
+ * Revision 3.0.0.1 2000/05/26 ivan
+ * Added logic in the SCA interrupt handler so that no board can monopolize
+ * the driver.
+ * Request PLX I/O region, although driver doesn't use it, to avoid
+ * problems with other drivers accessing it.
+ *
+ * Revision 3.0.0.0 2000/05/15 ivan
+ * Did some changes in the DMA programming implementation to avoid the
+ * occurrence of a SCA-II bug in the second channel.
+ * Implemented workaround for PLX9050 bug that would cause a system lockup
+ * in certain systems, depending on the MMIO addresses allocated to the
+ * board.
+ * Fixed the FALC chip programming to avoid synchronization problems in the
+ * second channel (TE only).
+ * Implemented a cleaner and faster Tx DMA descriptor cleanup procedure in
+ * cpc_queue_xmit().
+ * Changed the built-in driver implementation so that the driver can use the
+ * general 'hdlcN' naming convention instead of proprietary device names.
+ * Driver load messages are now device-centric, instead of board-centric.
+ * Dynamic allocation of net_device structures.
+ * Code is now compliant with the new module interface (module_[init|exit]).
+ * Make use of the PCI helper functions to access PCI resources.
+ *
+ * Revision 2.0.0.0 2000/04/15 ivan
+ * Added support for the PC300/TE boards (T1/FT1/E1/FE1).
+ *
+ * Revision 1.1.0.0 2000/02/28 ivan
+ * Major changes in the driver architecture.
+ * Softnet compliancy implemented.
+ * Driver now reports physical instead of virtual memory addresses.
+ * Added cpc_change_mtu function.
+ *
+ * Revision 1.0.0.0 1999/12/16 ivan
+ * First official release.
+ * Support for 1- and 2-channel boards (which use distinct PCI Device ID's).
+ * Support for monolythic installation (i.e., drv built into the kernel).
+ * X.25 additional checking when lapb_[dis]connect_request returns an error.
+ * SCA programming now covers X.21 as well.
+ *
+ * Revision 0.3.1.0 1999/11/18 ivan
+ * Made X.25 support configuration-dependent (as it depends on external 
+ * modules to work).
+ * Changed X.25-specific function names to comply with adopted convention.
+ * Fixed typos in X.25 functions that would cause compile errors (Daniela).
+ * Fixed bug in ch_config that would disable interrupts on a previously 
+ * enabled channel if the other channel on the same board was enabled later.
+ *
+ * Revision 0.3.0.0 1999/11/16 daniela
+ * X.25 support.
+ *
+ * Revision 0.2.3.0 1999/11/15 ivan
+ * Function cpc_ch_status now provides more detailed information.
+ * Added support for X.21 clock configuration.
+ * Changed TNR1 setting in order to prevent Tx FIFO overaccesses by the SCA.
+ * Now using PCI clock instead of internal oscillator clock for the SCA.
+ *
+ * Revision 0.2.2.0 1999/11/10 ivan
+ * Changed the *_dma_buf_check functions so that they would print only 
+ * the useful info instead of the whole buffer descriptor bank.
+ * Fixed bug in cpc_queue_xmit that would eventually crash the system 
+ * in case of a packet drop.
+ * Implemented TX underrun handling.
+ * Improved SCA fine tuning to boost up its performance.
+ *
+ * Revision 0.2.1.0 1999/11/03 ivan
+ * Added functions *dma_buf_pt_init to allow independent initialization 
+ * of the next-descr. and DMA buffer pointers on the DMA descriptors.
+ * Kernel buffer release and tbusy clearing is now done in the interrupt 
+ * handler.
+ * Fixed bug in cpc_open that would cause an interface reopen to fail.
+ * Added a protocol-specific code section in cpc_net_rx.
+ * Removed printk level defs (they might be added back after the beta phase).
+ *
+ * Revision 0.2.0.0 1999/10/28 ivan
+ * Revisited the code so that new protocols can be easily added / supported. 
+ *
+ * Revision 0.1.0.1 1999/10/20 ivan
+ * Mostly "esthetic" changes.
+ *
+ * Revision 0.1.0.0 1999/10/11 ivan
+ * Initial version.
+ *
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/net.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/spinlock.h>
+#include <linux/if.h>
+#include <linux/slab.h>
+#include <net/arp.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "pc300.h"
+
+#define        CPC_LOCK(card,flags)            \
+               do {                                            \
+               spin_lock_irqsave(&card->card_lock, flags);     \
+               } while (0)
+
+#define CPC_UNLOCK(card,flags)                 \
+               do {                                                    \
+               spin_unlock_irqrestore(&card->card_lock, flags);        \
+               } while (0)
+
+#undef PC300_DEBUG_PCI
+#undef PC300_DEBUG_INTR
+#undef PC300_DEBUG_TX
+#undef PC300_DEBUG_RX
+#undef PC300_DEBUG_OTHER
+
+static DEFINE_PCI_DEVICE_TABLE(cpc_pci_dev_id) = {
+       /* PC300/RSV or PC300/X21, 2 chan */
+       {0x120e, 0x300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x300},
+       /* PC300/RSV or PC300/X21, 1 chan */
+       {0x120e, 0x301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x301},
+       /* PC300/TE, 2 chan */
+       {0x120e, 0x310, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x310},
+       /* PC300/TE, 1 chan */
+       {0x120e, 0x311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x311},
+       /* PC300/TE-M, 2 chan */
+       {0x120e, 0x320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x320},
+       /* PC300/TE-M, 1 chan */
+       {0x120e, 0x321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0x321},
+       /* End of table */
+       {0,},
+};
+MODULE_DEVICE_TABLE(pci, cpc_pci_dev_id);
+
+#ifndef cpc_min
+#define        cpc_min(a,b)    (((a)<(b))?(a):(b))
+#endif
+#ifndef cpc_max
+#define        cpc_max(a,b)    (((a)>(b))?(a):(b))
+#endif
+
+/* prototypes */
+static void tx_dma_buf_pt_init(pc300_t *, int);
+static void tx_dma_buf_init(pc300_t *, int);
+static void rx_dma_buf_pt_init(pc300_t *, int);
+static void rx_dma_buf_init(pc300_t *, int);
+static void tx_dma_buf_check(pc300_t *, int);
+static void rx_dma_buf_check(pc300_t *, int);
+static irqreturn_t cpc_intr(int, void *);
+static int clock_rate_calc(u32, u32, int *);
+static u32 detect_ram(pc300_t *);
+static void plx_init(pc300_t *);
+static void cpc_trace(struct net_device *, struct sk_buff *, char);
+static int cpc_attach(struct net_device *, unsigned short, unsigned short);
+static int cpc_close(struct net_device *dev);
+
+#ifdef CONFIG_PC300_MLPPP
+void cpc_tty_init(pc300dev_t * dev);
+void cpc_tty_unregister_service(pc300dev_t * pc300dev);
+void cpc_tty_receive(pc300dev_t * pc300dev);
+void cpc_tty_trigger_poll(pc300dev_t * pc300dev);
+#endif
+
+/************************/
+/***   DMA Routines   ***/
+/************************/
+static void tx_dma_buf_pt_init(pc300_t * card, int ch)
+{
+       int i;
+       int ch_factor = ch * N_DMA_TX_BUF;
+       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
+                                      + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+
+       for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
+               cpc_writel(&ptdescr->next, (u32)(DMA_TX_BD_BASE +
+                       (ch_factor + ((i + 1) & (N_DMA_TX_BUF - 1))) * sizeof(pcsca_bd_t)));
+               cpc_writel(&ptdescr->ptbuf,
+                          (u32)(DMA_TX_BASE + (ch_factor + i) * BD_DEF_LEN));
+       }
+}
+
+static void tx_dma_buf_init(pc300_t * card, int ch)
+{
+       int i;
+       int ch_factor = ch * N_DMA_TX_BUF;
+       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
+                              + DMA_TX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+
+       for (i = 0; i < N_DMA_TX_BUF; i++, ptdescr++) {
+               memset_io(ptdescr, 0, sizeof(pcsca_bd_t));
+               cpc_writew(&ptdescr->len, 0);
+               cpc_writeb(&ptdescr->status, DST_OSB);
+       }
+       tx_dma_buf_pt_init(card, ch);
+}
+
+static void rx_dma_buf_pt_init(pc300_t * card, int ch)
+{
+       int i;
+       int ch_factor = ch * N_DMA_RX_BUF;
+       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
+                                      + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+
+       for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
+               cpc_writel(&ptdescr->next, (u32)(DMA_RX_BD_BASE +
+                       (ch_factor + ((i + 1) & (N_DMA_RX_BUF - 1))) * sizeof(pcsca_bd_t)));
+               cpc_writel(&ptdescr->ptbuf,
+                          (u32)(DMA_RX_BASE + (ch_factor + i) * BD_DEF_LEN));
+       }
+}
+
+static void rx_dma_buf_init(pc300_t * card, int ch)
+{
+       int i;
+       int ch_factor = ch * N_DMA_RX_BUF;
+       volatile pcsca_bd_t __iomem *ptdescr = (card->hw.rambase
+                                      + DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+
+       for (i = 0; i < N_DMA_RX_BUF; i++, ptdescr++) {
+               memset_io(ptdescr, 0, sizeof(pcsca_bd_t));
+               cpc_writew(&ptdescr->len, 0);
+               cpc_writeb(&ptdescr->status, 0);
+       }
+       rx_dma_buf_pt_init(card, ch);
+}
+
+static void tx_dma_buf_check(pc300_t * card, int ch)
+{
+       volatile pcsca_bd_t __iomem *ptdescr;
+       int i;
+       u16 first_bd = card->chan[ch].tx_first_bd;
+       u16 next_bd = card->chan[ch].tx_next_bd;
+
+       printk("#CH%d: f_bd = %d(0x%08zx), n_bd = %d(0x%08zx)\n", ch,
+              first_bd, TX_BD_ADDR(ch, first_bd),
+              next_bd, TX_BD_ADDR(ch, next_bd));
+       for (i = first_bd,
+            ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, first_bd));
+            i != ((next_bd + 1) & (N_DMA_TX_BUF - 1));
+            i = (i + 1) & (N_DMA_TX_BUF - 1), 
+                ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i))) {
+               printk("\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d",
+                      ch, i, cpc_readl(&ptdescr->next),
+                      cpc_readl(&ptdescr->ptbuf),
+                      cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len));
+       }
+       printk("\n");
+}
+
+#ifdef PC300_DEBUG_OTHER
+/* Show all TX buffer descriptors */
+static void tx1_dma_buf_check(pc300_t * card, int ch)
+{
+       volatile pcsca_bd_t __iomem *ptdescr;
+       int i;
+       u16 first_bd = card->chan[ch].tx_first_bd;
+       u16 next_bd = card->chan[ch].tx_next_bd;
+       u32 scabase = card->hw.scabase;
+
+       printk ("\nnfree_tx_bd = %d\n", card->chan[ch].nfree_tx_bd);
+       printk("#CH%d: f_bd = %d(0x%08x), n_bd = %d(0x%08x)\n", ch,
+              first_bd, TX_BD_ADDR(ch, first_bd),
+              next_bd, TX_BD_ADDR(ch, next_bd));
+       printk("TX_CDA=0x%08x, TX_EDA=0x%08x\n",
+              cpc_readl(scabase + DTX_REG(CDAL, ch)),
+              cpc_readl(scabase + DTX_REG(EDAL, ch)));
+       for (i = 0; i < N_DMA_TX_BUF; i++) {
+               ptdescr = (card->hw.rambase + TX_BD_ADDR(ch, i));
+               printk("\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d",
+                      ch, i, cpc_readl(&ptdescr->next),
+                      cpc_readl(&ptdescr->ptbuf),
+                      cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len));
+       }
+       printk("\n");
+}
+#endif
+
+static void rx_dma_buf_check(pc300_t * card, int ch)
+{
+       volatile pcsca_bd_t __iomem *ptdescr;
+       int i;
+       u16 first_bd = card->chan[ch].rx_first_bd;
+       u16 last_bd = card->chan[ch].rx_last_bd;
+       int ch_factor;
+
+       ch_factor = ch * N_DMA_RX_BUF;
+       printk("#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd);
+       for (i = 0, ptdescr = (card->hw.rambase +
+                                             DMA_RX_BD_BASE + ch_factor * sizeof(pcsca_bd_t));
+            i < N_DMA_RX_BUF; i++, ptdescr++) {
+               if (cpc_readb(&ptdescr->status) & DST_OSB)
+                       printk ("\n CH%d RX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d",
+                                ch, i, cpc_readl(&ptdescr->next),
+                                cpc_readl(&ptdescr->ptbuf),
+                                cpc_readb(&ptdescr->status),
+                                cpc_readw(&ptdescr->len));
+       }
+       printk("\n");
+}
+
+static int dma_get_rx_frame_size(pc300_t * card, int ch)
+{
+       volatile pcsca_bd_t __iomem *ptdescr;
+       u16 first_bd = card->chan[ch].rx_first_bd;
+       int rcvd = 0;
+       volatile u8 status;
+
+       ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, first_bd));
+       while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
+               rcvd += cpc_readw(&ptdescr->len);
+               first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1);
+               if ((status & DST_EOM) || (first_bd == card->chan[ch].rx_last_bd)) {
+                       /* Return the size of a good frame or incomplete bad frame 
+                       * (dma_buf_read will clean the buffer descriptors in this case). */
+                       return rcvd;
+               }
+               ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
+       }
+       return -1;
+}
+
+/*
+ * dma_buf_write: writes a frame to the Tx DMA buffers
+ * NOTE: this function writes one frame at a time.
+ */
+static int dma_buf_write(pc300_t *card, int ch, u8 *ptdata, int len)
+{
+       int i, nchar;
+       volatile pcsca_bd_t __iomem *ptdescr;
+       int tosend = len;
+       u8 nbuf = ((len - 1) / BD_DEF_LEN) + 1;
+
+       if (nbuf >= card->chan[ch].nfree_tx_bd) {
+               return -ENOMEM;
+       }
+
+       for (i = 0; i < nbuf; i++) {
+               ptdescr = (card->hw.rambase +
+                                         TX_BD_ADDR(ch, card->chan[ch].tx_next_bd));
+               nchar = cpc_min(BD_DEF_LEN, tosend);
+               if (cpc_readb(&ptdescr->status) & DST_OSB) {
+                       memcpy_toio((card->hw.rambase + cpc_readl(&ptdescr->ptbuf)),
+                                   &ptdata[len - tosend], nchar);
+                       cpc_writew(&ptdescr->len, nchar);
+                       card->chan[ch].nfree_tx_bd--;
+                       if ((i + 1) == nbuf) {
+                               /* This must be the last BD to be used */
+                               cpc_writeb(&ptdescr->status, DST_EOM);
+                       } else {
+                               cpc_writeb(&ptdescr->status, 0);
+                       }
+               } else {
+                       return -ENOMEM;
+               }
+               tosend -= nchar;
+               card->chan[ch].tx_next_bd =
+                       (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1);
+       }
+       /* If it gets to here, it means we have sent the whole frame */
+       return 0;
+}
+
+/*
+ * dma_buf_read: reads a frame from the Rx DMA buffers
+ * NOTE: this function reads one frame at a time.
+ */
+static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb)
+{
+       int nchar;
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       volatile pcsca_bd_t __iomem *ptdescr;
+       int rcvd = 0;
+       volatile u8 status;
+
+       ptdescr = (card->hw.rambase +
+                                 RX_BD_ADDR(ch, chan->rx_first_bd));
+       while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
+               nchar = cpc_readw(&ptdescr->len);
+               if ((status & (DST_OVR | DST_CRC | DST_RBIT | DST_SHRT | DST_ABT)) ||
+                   (nchar > BD_DEF_LEN)) {
+
+                       if (nchar > BD_DEF_LEN)
+                               status |= DST_RBIT;
+                       rcvd = -status;
+                       /* Discard remaining descriptors used by the bad frame */
+                       while (chan->rx_first_bd != chan->rx_last_bd) {
+                               cpc_writeb(&ptdescr->status, 0);
+                               chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1);
+                               if (status & DST_EOM)
+                                       break;
+                               ptdescr = (card->hw.rambase +
+                                                         cpc_readl(&ptdescr->next));
+                               status = cpc_readb(&ptdescr->status);
+                       }
+                       break;
+               }
+               if (nchar != 0) {
+                       if (skb) {
+                               memcpy_fromio(skb_put(skb, nchar),
+                                (card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar);
+                       }
+                       rcvd += nchar;
+               }
+               cpc_writeb(&ptdescr->status, 0);
+               cpc_writeb(&ptdescr->len, 0);
+               chan->rx_first_bd = (chan->rx_first_bd + 1) & (N_DMA_RX_BUF - 1);
+
+               if (status & DST_EOM)
+                       break;
+
+               ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next));
+       }
+
+       if (rcvd != 0) {
+               /* Update pointer */
+               chan->rx_last_bd = (chan->rx_first_bd - 1) & (N_DMA_RX_BUF - 1);
+               /* Update EDA */
+               cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch),
+                          RX_BD_ADDR(ch, chan->rx_last_bd));
+       }
+       return rcvd;
+}
+
+static void tx_dma_stop(pc300_t * card, int ch)
+{
+       void __iomem *scabase = card->hw.scabase;
+       u8 drr_ena_bit = 1 << (5 + 2 * ch);
+       u8 drr_rst_bit = 1 << (1 + 2 * ch);
+
+       /* Disable DMA */
+       cpc_writeb(scabase + DRR, drr_ena_bit);
+       cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
+}
+
+static void rx_dma_stop(pc300_t * card, int ch)
+{
+       void __iomem *scabase = card->hw.scabase;
+       u8 drr_ena_bit = 1 << (4 + 2 * ch);
+       u8 drr_rst_bit = 1 << (2 * ch);
+
+       /* Disable DMA */
+       cpc_writeb(scabase + DRR, drr_ena_bit);
+       cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit);
+}
+
+static void rx_dma_start(pc300_t * card, int ch)
+{
+       void __iomem *scabase = card->hw.scabase;
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       
+       /* Start DMA */
+       cpc_writel(scabase + DRX_REG(CDAL, ch),
+                  RX_BD_ADDR(ch, chan->rx_first_bd));
+       if (cpc_readl(scabase + DRX_REG(CDAL,ch)) !=
+                                 RX_BD_ADDR(ch, chan->rx_first_bd)) {
+               cpc_writel(scabase + DRX_REG(CDAL, ch),
+                                  RX_BD_ADDR(ch, chan->rx_first_bd));
+       }
+       cpc_writel(scabase + DRX_REG(EDAL, ch),
+                  RX_BD_ADDR(ch, chan->rx_last_bd));
+       cpc_writew(scabase + DRX_REG(BFLL, ch), BD_DEF_LEN);
+       cpc_writeb(scabase + DSR_RX(ch), DSR_DE);
+       if (!(cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
+       cpc_writeb(scabase + DSR_RX(ch), DSR_DE);
+       }
+}
+
+/*************************/
+/***   FALC Routines   ***/
+/*************************/
+static void falc_issue_cmd(pc300_t *card, int ch, u8 cmd)
+{
+       void __iomem *falcbase = card->hw.falcbase;
+       unsigned long i = 0;
+
+       while (cpc_readb(falcbase + F_REG(SIS, ch)) & SIS_CEC) {
+               if (i++ >= PC300_FALC_MAXLOOP) {
+                       printk("%s: FALC command locked(cmd=0x%x).\n",
+                              card->chan[ch].d.name, cmd);
+                       break;
+               }
+       }
+       cpc_writeb(falcbase + F_REG(CMDR, ch), cmd);
+}
+
+static void falc_intr_enable(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       /* Interrupt pins are open-drain */
+       cpc_writeb(falcbase + F_REG(IPC, ch),
+                  cpc_readb(falcbase + F_REG(IPC, ch)) & ~IPC_IC0);
+       /* Conters updated each second */
+       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_ECM);
+       /* Enable SEC and ES interrupts  */
+       cpc_writeb(falcbase + F_REG(IMR3, ch),
+                  cpc_readb(falcbase + F_REG(IMR3, ch)) & ~(IMR3_SEC | IMR3_ES));
+       if (conf->fr_mode == PC300_FR_UNFRAMED) {
+               cpc_writeb(falcbase + F_REG(IMR4, ch),
+                          cpc_readb(falcbase + F_REG(IMR4, ch)) & ~(IMR4_LOS));
+       } else {
+               cpc_writeb(falcbase + F_REG(IMR4, ch),
+                          cpc_readb(falcbase + F_REG(IMR4, ch)) &
+                          ~(IMR4_LFA | IMR4_AIS | IMR4_LOS | IMR4_SLIP));
+       }
+       if (conf->media == IF_IFACE_T1) {
+               cpc_writeb(falcbase + F_REG(IMR3, ch),
+                          cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC);
+       } else {
+               cpc_writeb(falcbase + F_REG(IPC, ch),
+                          cpc_readb(falcbase + F_REG(IPC, ch)) | IPC_SCI);
+               if (conf->fr_mode == PC300_FR_UNFRAMED) {
+                       cpc_writeb(falcbase + F_REG(IMR2, ch),
+                                  cpc_readb(falcbase + F_REG(IMR2, ch)) & ~(IMR2_LOS));
+               } else {
+                       cpc_writeb(falcbase + F_REG(IMR2, ch),
+                                  cpc_readb(falcbase + F_REG(IMR2, ch)) &
+                                  ~(IMR2_FAR | IMR2_LFA | IMR2_AIS | IMR2_LOS));
+                       if (pfalc->multiframe_mode) {
+                               cpc_writeb(falcbase + F_REG(IMR2, ch),
+                                          cpc_readb(falcbase + F_REG(IMR2, ch)) & 
+                                          ~(IMR2_T400MS | IMR2_MFAR));
+                       } else {
+                               cpc_writeb(falcbase + F_REG(IMR2, ch),
+                                          cpc_readb(falcbase + F_REG(IMR2, ch)) | 
+                                          IMR2_T400MS | IMR2_MFAR);
+                       }
+               }
+       }
+}
+
+static void falc_open_timeslot(pc300_t * card, int ch, int timeslot)
+{
+       void __iomem *falcbase = card->hw.falcbase;
+       u8 tshf = card->chan[ch].falc.offset;
+
+       cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
+                  cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch)) & 
+                       ~(0x80 >> ((timeslot - tshf) & 0x07)));
+       cpc_writeb(falcbase + F_REG((TTR1 + timeslot / 8), ch),
+                  cpc_readb(falcbase + F_REG((TTR1 + timeslot / 8), ch)) | 
+                       (0x80 >> (timeslot & 0x07)));
+       cpc_writeb(falcbase + F_REG((RTR1 + timeslot / 8), ch),
+                  cpc_readb(falcbase + F_REG((RTR1 + timeslot / 8), ch)) | 
+                       (0x80 >> (timeslot & 0x07)));
+}
+
+static void falc_close_timeslot(pc300_t * card, int ch, int timeslot)
+{
+       void __iomem *falcbase = card->hw.falcbase;
+       u8 tshf = card->chan[ch].falc.offset;
+
+       cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch),
+                  cpc_readb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch)) | 
+                  (0x80 >> ((timeslot - tshf) & 0x07)));
+       cpc_writeb(falcbase + F_REG((TTR1 + timeslot / 8), ch),
+                  cpc_readb(falcbase + F_REG((TTR1 + timeslot / 8), ch)) & 
+                  ~(0x80 >> (timeslot & 0x07)));
+       cpc_writeb(falcbase + F_REG((RTR1 + timeslot / 8), ch),
+                  cpc_readb(falcbase + F_REG((RTR1 + timeslot / 8), ch)) & 
+                  ~(0x80 >> (timeslot & 0x07)));
+}
+
+static void falc_close_all_timeslots(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff);
+       cpc_writeb(falcbase + F_REG(TTR1, ch), 0);
+       cpc_writeb(falcbase + F_REG(RTR1, ch), 0);
+       cpc_writeb(falcbase + F_REG(ICB2, ch), 0xff);
+       cpc_writeb(falcbase + F_REG(TTR2, ch), 0);
+       cpc_writeb(falcbase + F_REG(RTR2, ch), 0);
+       cpc_writeb(falcbase + F_REG(ICB3, ch), 0xff);
+       cpc_writeb(falcbase + F_REG(TTR3, ch), 0);
+       cpc_writeb(falcbase + F_REG(RTR3, ch), 0);
+       if (conf->media == IF_IFACE_E1) {
+               cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff);
+               cpc_writeb(falcbase + F_REG(TTR4, ch), 0);
+               cpc_writeb(falcbase + F_REG(RTR4, ch), 0);
+       }
+}
+
+static void falc_open_all_timeslots(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       cpc_writeb(falcbase + F_REG(ICB1, ch), 0);
+       if (conf->fr_mode == PC300_FR_UNFRAMED) {
+               cpc_writeb(falcbase + F_REG(TTR1, ch), 0xff);
+               cpc_writeb(falcbase + F_REG(RTR1, ch), 0xff);
+       } else {
+               /* Timeslot 0 is never enabled */
+               cpc_writeb(falcbase + F_REG(TTR1, ch), 0x7f);
+               cpc_writeb(falcbase + F_REG(RTR1, ch), 0x7f);
+       }
+       cpc_writeb(falcbase + F_REG(ICB2, ch), 0);
+       cpc_writeb(falcbase + F_REG(TTR2, ch), 0xff);
+       cpc_writeb(falcbase + F_REG(RTR2, ch), 0xff);
+       cpc_writeb(falcbase + F_REG(ICB3, ch), 0);
+       cpc_writeb(falcbase + F_REG(TTR3, ch), 0xff);
+       cpc_writeb(falcbase + F_REG(RTR3, ch), 0xff);
+       if (conf->media == IF_IFACE_E1) {
+               cpc_writeb(falcbase + F_REG(ICB4, ch), 0);
+               cpc_writeb(falcbase + F_REG(TTR4, ch), 0xff);
+               cpc_writeb(falcbase + F_REG(RTR4, ch), 0xff);
+       } else {
+               cpc_writeb(falcbase + F_REG(ICB4, ch), 0xff);
+               cpc_writeb(falcbase + F_REG(TTR4, ch), 0x80);
+               cpc_writeb(falcbase + F_REG(RTR4, ch), 0x80);
+       }
+}
+
+static void falc_init_timeslot(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       int tslot;
+
+       for (tslot = 0; tslot < pfalc->num_channels; tslot++) {
+               if (conf->tslot_bitmap & (1 << tslot)) {
+                       // Channel enabled
+                       falc_open_timeslot(card, ch, tslot + 1);
+               } else {
+                       // Channel disabled
+                       falc_close_timeslot(card, ch, tslot + 1);
+               }
+       }
+}
+
+static void falc_enable_comm(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+
+       if (pfalc->full_bandwidth) {
+               falc_open_all_timeslots(card, ch);
+       } else {
+               falc_init_timeslot(card, ch);
+       }
+       // CTS/DCD ON
+       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
+                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) &
+                  ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
+}
+
+static void falc_disable_comm(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+
+       if (pfalc->loop_active != 2) {
+               falc_close_all_timeslots(card, ch);
+       }
+       // CTS/DCD OFF
+       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
+                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) |
+                  ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch)));
+}
+
+static void falc_init_t1(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+       u8 dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
+
+       /* Switch to T1 mode (PCM 24) */
+       cpc_writeb(falcbase + F_REG(FMR1, ch), FMR1_PMOD);
+
+       /* Wait 20 us for setup */
+       udelay(20);
+
+       /* Transmit Buffer Size (1 frame) */
+       cpc_writeb(falcbase + F_REG(SIC1, ch), SIC1_XBS0);
+
+       /* Clock mode */
+       if (conf->phys_settings.clock_type == CLOCK_INT) { /* Master mode */
+               cpc_writeb(falcbase + F_REG(LIM0, ch),
+                          cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS);
+       } else { /* Slave mode */
+               cpc_writeb(falcbase + F_REG(LIM0, ch),
+                          cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS);
+               cpc_writeb(falcbase + F_REG(LOOP, ch),
+                          cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_RTM);
+       }
+
+       cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI);
+       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                  cpc_readb(falcbase + F_REG(FMR0, ch)) &
+                  ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1));
+
+       switch (conf->lcode) {
+               case PC300_LC_AMI:
+                       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                                  cpc_readb(falcbase + F_REG(FMR0, ch)) |
+                                  FMR0_XC1 | FMR0_RC1);
+                       /* Clear Channel register to ON for all channels */
+                       cpc_writeb(falcbase + F_REG(CCB1, ch), 0xff);
+                       cpc_writeb(falcbase + F_REG(CCB2, ch), 0xff);
+                       cpc_writeb(falcbase + F_REG(CCB3, ch), 0xff);
+                       break;
+
+               case PC300_LC_B8ZS:
+                       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                                  cpc_readb(falcbase + F_REG(FMR0, ch)) |
+                                  FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1);
+                       break;
+
+               case PC300_LC_NRZ:
+                       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                                  cpc_readb(falcbase + F_REG(FMR0, ch)) | 0x00);
+                       break;
+       }
+
+       cpc_writeb(falcbase + F_REG(LIM0, ch),
+                  cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_ELOS);
+       cpc_writeb(falcbase + F_REG(LIM0, ch),
+                  cpc_readb(falcbase + F_REG(LIM0, ch)) & ~(LIM0_SCL1 | LIM0_SCL0));
+       /* Set interface mode to 2 MBPS */
+       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD);
+
+       switch (conf->fr_mode) {
+               case PC300_FR_ESF:
+                       pfalc->multiframe_mode = 0;
+                       cpc_writeb(falcbase + F_REG(FMR4, ch),
+                                  cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_FM1);
+                       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | 
+                                  FMR1_CRC | FMR1_EDL);
+                       cpc_writeb(falcbase + F_REG(XDL1, ch), 0);
+                       cpc_writeb(falcbase + F_REG(XDL2, ch), 0);
+                       cpc_writeb(falcbase + F_REG(XDL3, ch), 0);
+                       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                                  cpc_readb(falcbase + F_REG(FMR0, ch)) & ~FMR0_SRAF);
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2,ch)) | FMR2_MCSP | FMR2_SSP);
+                       break;
+
+               case PC300_FR_D4:
+                       pfalc->multiframe_mode = 1;
+                       cpc_writeb(falcbase + F_REG(FMR4, ch),
+                                  cpc_readb(falcbase + F_REG(FMR4, ch)) &
+                                  ~(FMR4_FM1 | FMR4_FM0));
+                       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                                  cpc_readb(falcbase + F_REG(FMR0, ch)) | FMR0_SRAF);
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_SSP);
+                       break;
+       }
+
+       /* Enable Automatic Resynchronization */
+       cpc_writeb(falcbase + F_REG(FMR4, ch),
+                  cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_AUTO);
+
+       /* Transmit Automatic Remote Alarm */
+       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA);
+
+       /* Channel translation mode 1 : one to one */
+       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_CTM);
+
+       /* No signaling */
+       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_SIGM);
+       cpc_writeb(falcbase + F_REG(FMR5, ch),
+                  cpc_readb(falcbase + F_REG(FMR5, ch)) &
+                  ~(FMR5_EIBR | FMR5_SRS));
+       cpc_writeb(falcbase + F_REG(CCR1, ch), 0);
+
+       cpc_writeb(falcbase + F_REG(LIM1, ch),
+                  cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1);
+
+       switch (conf->lbo) {
+                       /* Provides proper Line Build Out */
+               case PC300_LBO_0_DB:
+                       cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja));
+                       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x5a);
+                       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x8f);
+                       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
+                       break;
+               case PC300_LBO_7_5_DB:
+                       cpc_writeb(falcbase + F_REG(LIM2, ch), (0x40 | LIM2_LOS1 | dja));
+                       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x11);
+                       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x02);
+                       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
+                       break;
+               case PC300_LBO_15_DB:
+                       cpc_writeb(falcbase + F_REG(LIM2, ch), (0x80 | LIM2_LOS1 | dja));
+                       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x8e);
+                       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01);
+                       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
+                       break;
+               case PC300_LBO_22_5_DB:
+                       cpc_writeb(falcbase + F_REG(LIM2, ch), (0xc0 | LIM2_LOS1 | dja));
+                       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x09);
+                       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x01);
+                       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x20);
+                       break;
+       }
+
+       /* Transmit Clock-Slot Offset */
+       cpc_writeb(falcbase + F_REG(XC0, ch),
+                  cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01);
+       /* Transmit Time-slot Offset */
+       cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e);
+       /* Receive  Clock-Slot offset */
+       cpc_writeb(falcbase + F_REG(RC0, ch), 0x05);
+       /* Receive  Time-slot offset */
+       cpc_writeb(falcbase + F_REG(RC1, ch), 0x00);
+
+       /* LOS Detection after 176 consecutive 0s */
+       cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a);
+       /* LOS Recovery after 22 ones in the time window of PCD */
+       cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15);
+
+       cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f);
+
+       if (conf->fr_mode == PC300_FR_ESF_JAPAN) {
+               cpc_writeb(falcbase + F_REG(RC1, ch),
+                          cpc_readb(falcbase + F_REG(RC1, ch)) | 0x80);
+       }
+
+       falc_close_all_timeslots(card, ch);
+}
+
+static void falc_init_e1(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+       u8 dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0);
+
+       /* Switch to E1 mode (PCM 30) */
+       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_PMOD);
+
+       /* Clock mode */
+       if (conf->phys_settings.clock_type == CLOCK_INT) { /* Master mode */
+               cpc_writeb(falcbase + F_REG(LIM0, ch),
+                          cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_MAS);
+       } else { /* Slave mode */
+               cpc_writeb(falcbase + F_REG(LIM0, ch),
+                          cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_MAS);
+       }
+       cpc_writeb(falcbase + F_REG(LOOP, ch),
+                  cpc_readb(falcbase + F_REG(LOOP, ch)) & ~LOOP_SFM);
+
+       cpc_writeb(falcbase + F_REG(IPC, ch), IPC_SCI);
+       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                  cpc_readb(falcbase + F_REG(FMR0, ch)) &
+                  ~(FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1));
+
+       switch (conf->lcode) {
+               case PC300_LC_AMI:
+                       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                                  cpc_readb(falcbase + F_REG(FMR0, ch)) |
+                                  FMR0_XC1 | FMR0_RC1);
+                       break;
+
+               case PC300_LC_HDB3:
+                       cpc_writeb(falcbase + F_REG(FMR0, ch),
+                                  cpc_readb(falcbase + F_REG(FMR0, ch)) |
+                                  FMR0_XC0 | FMR0_XC1 | FMR0_RC0 | FMR0_RC1);
+                       break;
+
+               case PC300_LC_NRZ:
+                       break;
+       }
+
+       cpc_writeb(falcbase + F_REG(LIM0, ch),
+                  cpc_readb(falcbase + F_REG(LIM0, ch)) & ~(LIM0_SCL1 | LIM0_SCL0));
+       /* Set interface mode to 2 MBPS */
+       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_IMOD);
+
+       cpc_writeb(falcbase + F_REG(XPM0, ch), 0x18);
+       cpc_writeb(falcbase + F_REG(XPM1, ch), 0x03);
+       cpc_writeb(falcbase + F_REG(XPM2, ch), 0x00);
+
+       switch (conf->fr_mode) {
+               case PC300_FR_MF_CRC4:
+                       pfalc->multiframe_mode = 1;
+                       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_XFS);
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_RFS1);
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_RFS0);
+                       cpc_writeb(falcbase + F_REG(FMR3, ch),
+                                  cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_EXTIW);
+
+                       /* MultiFrame Resynchronization */
+                       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_MFCS);
+
+                       /* Automatic Loss of Multiframe > 914 CRC errors */
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_ALMF);
+
+                       /* S1 and SI1/SI2 spare Bits set to 1 */
+                       cpc_writeb(falcbase + F_REG(XSP, ch),
+                                  cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_AXS);
+                       cpc_writeb(falcbase + F_REG(XSP, ch),
+                                  cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_EBP);
+                       cpc_writeb(falcbase + F_REG(XSP, ch),
+                                  cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_XS13 | XSP_XS15);
+
+                       /* Automatic Force Resynchronization */
+                       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_AFR);
+
+                       /* Transmit Automatic Remote Alarm */
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA);
+
+                       /* Transmit Spare Bits for National Use (Y, Sn, Sa) */
+                       cpc_writeb(falcbase + F_REG(XSW, ch),
+                                  cpc_readb(falcbase + F_REG(XSW, ch)) |
+                                  XSW_XY0 | XSW_XY1 | XSW_XY2 | XSW_XY3 | XSW_XY4);
+                       break;
+
+               case PC300_FR_MF_NON_CRC4:
+               case PC300_FR_D4:
+                       pfalc->multiframe_mode = 0;
+                       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_XFS);
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & 
+                                  ~(FMR2_RFS1 | FMR2_RFS0));
+                       cpc_writeb(falcbase + F_REG(XSW, ch),
+                                  cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XSIS);
+                       cpc_writeb(falcbase + F_REG(XSP, ch),
+                                  cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_XSIF);
+
+                       /* Automatic Force Resynchronization */
+                       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                                  cpc_readb(falcbase + F_REG(FMR1, ch)) | FMR1_AFR);
+
+                       /* Transmit Automatic Remote Alarm */
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_AXRA);
+
+                       /* Transmit Spare Bits for National Use (Y, Sn, Sa) */
+                       cpc_writeb(falcbase + F_REG(XSW, ch),
+                                  cpc_readb(falcbase + F_REG(XSW, ch)) |
+                                  XSW_XY0 | XSW_XY1 | XSW_XY2 | XSW_XY3 | XSW_XY4);
+                       break;
+
+               case PC300_FR_UNFRAMED:
+                       pfalc->multiframe_mode = 0;
+                       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_XFS);
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & 
+                                  ~(FMR2_RFS1 | FMR2_RFS0));
+                       cpc_writeb(falcbase + F_REG(XSP, ch),
+                                  cpc_readb(falcbase + F_REG(XSP, ch)) | XSP_TT0);
+                       cpc_writeb(falcbase + F_REG(XSW, ch),
+                                  cpc_readb(falcbase + F_REG(XSW, ch)) & 
+                                  ~(XSW_XTM|XSW_XY0|XSW_XY1|XSW_XY2|XSW_XY3|XSW_XY4));
+                       cpc_writeb(falcbase + F_REG(TSWM, ch), 0xff);
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) |
+                                  (FMR2_RTM | FMR2_DAIS));
+                       cpc_writeb(falcbase + F_REG(FMR2, ch),
+                                  cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_AXRA);
+                       cpc_writeb(falcbase + F_REG(FMR1, ch),
+                                  cpc_readb(falcbase + F_REG(FMR1, ch)) & ~FMR1_AFR);
+                       pfalc->sync = 1;
+                       cpc_writeb(falcbase + card->hw.cpld_reg2,
+                                  cpc_readb(falcbase + card->hw.cpld_reg2) |
+                                  (CPLD_REG2_FALC_LED2 << (2 * ch)));
+                       break;
+       }
+
+       /* No signaling */
+       cpc_writeb(falcbase + F_REG(XSP, ch),
+                  cpc_readb(falcbase + F_REG(XSP, ch)) & ~XSP_CASEN);
+       cpc_writeb(falcbase + F_REG(CCR1, ch), 0);
+
+       cpc_writeb(falcbase + F_REG(LIM1, ch),
+                  cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RIL0 | LIM1_RIL1);
+       cpc_writeb(falcbase + F_REG(LIM2, ch), (LIM2_LOS1 | dja));
+
+       /* Transmit Clock-Slot Offset */
+       cpc_writeb(falcbase + F_REG(XC0, ch),
+                  cpc_readb(falcbase + F_REG(XC0, ch)) | 0x01);
+       /* Transmit Time-slot Offset */
+       cpc_writeb(falcbase + F_REG(XC1, ch), 0x3e);
+       /* Receive  Clock-Slot offset */
+       cpc_writeb(falcbase + F_REG(RC0, ch), 0x05);
+       /* Receive  Time-slot offset */
+       cpc_writeb(falcbase + F_REG(RC1, ch), 0x00);
+
+       /* LOS Detection after 176 consecutive 0s */
+       cpc_writeb(falcbase + F_REG(PCDR, ch), 0x0a);
+       /* LOS Recovery after 22 ones in the time window of PCD */
+       cpc_writeb(falcbase + F_REG(PCRR, ch), 0x15);
+
+       cpc_writeb(falcbase + F_REG(IDLE, ch), 0x7f);
+
+       falc_close_all_timeslots(card, ch);
+}
+
+static void falc_init_hdlc(pc300_t * card, int ch)
+{
+       void __iomem *falcbase = card->hw.falcbase;
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+
+       /* Enable transparent data transfer */
+       if (conf->fr_mode == PC300_FR_UNFRAMED) {
+               cpc_writeb(falcbase + F_REG(MODE, ch), 0);
+       } else {
+               cpc_writeb(falcbase + F_REG(MODE, ch),
+                          cpc_readb(falcbase + F_REG(MODE, ch)) |
+                          (MODE_HRAC | MODE_MDS2));
+               cpc_writeb(falcbase + F_REG(RAH2, ch), 0xff);
+               cpc_writeb(falcbase + F_REG(RAH1, ch), 0xff);
+               cpc_writeb(falcbase + F_REG(RAL2, ch), 0xff);
+               cpc_writeb(falcbase + F_REG(RAL1, ch), 0xff);
+       }
+
+       /* Tx/Rx reset  */
+       falc_issue_cmd(card, ch, CMDR_RRES | CMDR_XRES | CMDR_SRES);
+
+       /* Enable interrupt sources */
+       falc_intr_enable(card, ch);
+}
+
+static void te_config(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+       u8 dummy;
+       unsigned long flags;
+
+       memset(pfalc, 0, sizeof(falc_t));
+       switch (conf->media) {
+               case IF_IFACE_T1:
+                       pfalc->num_channels = NUM_OF_T1_CHANNELS;
+                       pfalc->offset = 1;
+                       break;
+               case IF_IFACE_E1:
+                       pfalc->num_channels = NUM_OF_E1_CHANNELS;
+                       pfalc->offset = 0;
+                       break;
+       }
+       if (conf->tslot_bitmap == 0xffffffffUL)
+               pfalc->full_bandwidth = 1;
+       else
+               pfalc->full_bandwidth = 0;
+
+       CPC_LOCK(card, flags);
+       /* Reset the FALC chip */
+       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
+                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) |
+                  (CPLD_REG1_FALC_RESET << (2 * ch)));
+       udelay(10000);
+       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
+                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) &
+                  ~(CPLD_REG1_FALC_RESET << (2 * ch)));
+
+       if (conf->media == IF_IFACE_T1) {
+               falc_init_t1(card, ch);
+       } else {
+               falc_init_e1(card, ch);
+       }
+       falc_init_hdlc(card, ch);
+       if (conf->rx_sens == PC300_RX_SENS_SH) {
+               cpc_writeb(falcbase + F_REG(LIM0, ch),
+                          cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_EQON);
+       } else {
+               cpc_writeb(falcbase + F_REG(LIM0, ch),
+                          cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_EQON);
+       }
+       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
+                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) |
+                  ((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK) << (2 * ch)));
+
+       /* Clear all interrupt registers */
+       dummy = cpc_readb(falcbase + F_REG(FISR0, ch)) +
+               cpc_readb(falcbase + F_REG(FISR1, ch)) +
+               cpc_readb(falcbase + F_REG(FISR2, ch)) +
+               cpc_readb(falcbase + F_REG(FISR3, ch));
+       CPC_UNLOCK(card, flags);
+}
+
+static void falc_check_status(pc300_t * card, int ch, unsigned char frs0)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       /* Verify LOS */
+       if (frs0 & FRS0_LOS) {
+               if (!pfalc->red_alarm) {
+                       pfalc->red_alarm = 1;
+                       pfalc->los++;
+                       if (!pfalc->blue_alarm) {
+                               // EVENT_FALC_ABNORMAL
+                               if (conf->media == IF_IFACE_T1) {
+                                       /* Disable this interrupt as it may otherwise interfere 
+                                        * with other working boards. */
+                                       cpc_writeb(falcbase + F_REG(IMR0, ch), 
+                                                  cpc_readb(falcbase + F_REG(IMR0, ch))
+                                                  | IMR0_PDEN);
+                               }
+                               falc_disable_comm(card, ch);
+                               // EVENT_FALC_ABNORMAL
+                       }
+               }
+       } else {
+               if (pfalc->red_alarm) {
+                       pfalc->red_alarm = 0;
+                       pfalc->losr++;
+               }
+       }
+
+       if (conf->fr_mode != PC300_FR_UNFRAMED) {
+               /* Verify AIS alarm */
+               if (frs0 & FRS0_AIS) {
+                       if (!pfalc->blue_alarm) {
+                               pfalc->blue_alarm = 1;
+                               pfalc->ais++;
+                               // EVENT_AIS
+                               if (conf->media == IF_IFACE_T1) {
+                                       /* Disable this interrupt as it may otherwise interfere with                       other working boards. */
+                                       cpc_writeb(falcbase + F_REG(IMR0, ch),
+                                                  cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
+                               }
+                               falc_disable_comm(card, ch);
+                               // EVENT_AIS
+                       }
+               } else {
+                       pfalc->blue_alarm = 0;
+               }
+
+               /* Verify LFA */
+               if (frs0 & FRS0_LFA) {
+                       if (!pfalc->loss_fa) {
+                               pfalc->loss_fa = 1;
+                               pfalc->lfa++;
+                               if (!pfalc->blue_alarm && !pfalc->red_alarm) {
+                                       // EVENT_FALC_ABNORMAL
+                                       if (conf->media == IF_IFACE_T1) {
+                                               /* Disable this interrupt as it may otherwise 
+                                                * interfere with other working boards. */
+                                               cpc_writeb(falcbase + F_REG(IMR0, ch),
+                                                          cpc_readb(falcbase + F_REG(IMR0, ch))
+                                                          | IMR0_PDEN);
+                                       }
+                                       falc_disable_comm(card, ch);
+                                       // EVENT_FALC_ABNORMAL
+                               }
+                       }
+               } else {
+                       if (pfalc->loss_fa) {
+                               pfalc->loss_fa = 0;
+                               pfalc->farec++;
+                       }
+               }
+
+               /* Verify LMFA */
+               if (pfalc->multiframe_mode && (frs0 & FRS0_LMFA)) {
+                       /* D4 or CRC4 frame mode */
+                       if (!pfalc->loss_mfa) {
+                               pfalc->loss_mfa = 1;
+                               pfalc->lmfa++;
+                               if (!pfalc->blue_alarm && !pfalc->red_alarm &&
+                                   !pfalc->loss_fa) {
+                                       // EVENT_FALC_ABNORMAL
+                                       if (conf->media == IF_IFACE_T1) {
+                                               /* Disable this interrupt as it may otherwise 
+                                                * interfere with other working boards. */
+                                               cpc_writeb(falcbase + F_REG(IMR0, ch),
+                                                          cpc_readb(falcbase + F_REG(IMR0, ch))
+                                                          | IMR0_PDEN);
+                                       }
+                                       falc_disable_comm(card, ch);
+                                       // EVENT_FALC_ABNORMAL
+                               }
+                       }
+               } else {
+                       pfalc->loss_mfa = 0;
+               }
+
+               /* Verify Remote Alarm */
+               if (frs0 & FRS0_RRA) {
+                       if (!pfalc->yellow_alarm) {
+                               pfalc->yellow_alarm = 1;
+                               pfalc->rai++;
+                               if (pfalc->sync) {
+                                       // EVENT_RAI
+                                       falc_disable_comm(card, ch);
+                                       // EVENT_RAI
+                               }
+                       }
+               } else {
+                       pfalc->yellow_alarm = 0;
+               }
+       } /* if !PC300_UNFRAMED */
+
+       if (pfalc->red_alarm || pfalc->loss_fa ||
+           pfalc->loss_mfa || pfalc->blue_alarm) {
+               if (pfalc->sync) {
+                       pfalc->sync = 0;
+                       chan->d.line_off++;
+                       cpc_writeb(falcbase + card->hw.cpld_reg2,
+                                  cpc_readb(falcbase + card->hw.cpld_reg2) &
+                                  ~(CPLD_REG2_FALC_LED2 << (2 * ch)));
+               }
+       } else {
+               if (!pfalc->sync) {
+                       pfalc->sync = 1;
+                       chan->d.line_on++;
+                       cpc_writeb(falcbase + card->hw.cpld_reg2,
+                                  cpc_readb(falcbase + card->hw.cpld_reg2) |
+                                  (CPLD_REG2_FALC_LED2 << (2 * ch)));
+               }
+       }
+
+       if (pfalc->sync && !pfalc->yellow_alarm) {
+               if (!pfalc->active) {
+                       // EVENT_FALC_NORMAL
+                       if (pfalc->loop_active) {
+                               return;
+                       }
+                       if (conf->media == IF_IFACE_T1) {
+                               cpc_writeb(falcbase + F_REG(IMR0, ch),
+                                          cpc_readb(falcbase + F_REG(IMR0, ch)) & ~IMR0_PDEN);
+                       }
+                       falc_enable_comm(card, ch);
+                       // EVENT_FALC_NORMAL
+                       pfalc->active = 1;
+               }
+       } else {
+               if (pfalc->active) {
+                       pfalc->active = 0;
+               }
+       }
+}
+
+static void falc_update_stats(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+       u16 counter;
+
+       counter = cpc_readb(falcbase + F_REG(FECL, ch));
+       counter |= cpc_readb(falcbase + F_REG(FECH, ch)) << 8;
+       pfalc->fec += counter;
+
+       counter = cpc_readb(falcbase + F_REG(CVCL, ch));
+       counter |= cpc_readb(falcbase + F_REG(CVCH, ch)) << 8;
+       pfalc->cvc += counter;
+
+       counter = cpc_readb(falcbase + F_REG(CECL, ch));
+       counter |= cpc_readb(falcbase + F_REG(CECH, ch)) << 8;
+       pfalc->cec += counter;
+
+       counter = cpc_readb(falcbase + F_REG(EBCL, ch));
+       counter |= cpc_readb(falcbase + F_REG(EBCH, ch)) << 8;
+       pfalc->ebc += counter;
+
+       if (cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) {
+               mdelay(10);
+               counter = cpc_readb(falcbase + F_REG(BECL, ch));
+               counter |= cpc_readb(falcbase + F_REG(BECH, ch)) << 8;
+               pfalc->bec += counter;
+
+               if (((conf->media == IF_IFACE_T1) &&
+                    (cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_LLBAD) &&
+                    (!(cpc_readb(falcbase + F_REG(FRS1, ch)) & FRS1_PDEN))) ||
+                   ((conf->media == IF_IFACE_E1) &&
+                    (cpc_readb(falcbase + F_REG(RSP, ch)) & RSP_LLBAD))) {
+                       pfalc->prbs = 2;
+               } else {
+                       pfalc->prbs = 1;
+               }
+       }
+}
+
+/*----------------------------------------------------------------------------
+ * falc_remote_loop
+ *----------------------------------------------------------------------------
+ * Description:        In the remote loopback mode the clock and data recovered
+ *             from the line inputs RL1/2 or RDIP/RDIN are routed back
+ *             to the line outputs XL1/2 or XDOP/XDON via the analog
+ *             transmitter. As in normal mode they are processed by
+ *             the synchronizer and then sent to the system interface.
+ *----------------------------------------------------------------------------
+ */
+static void falc_remote_loop(pc300_t * card, int ch, int loop_on)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (loop_on) {
+               // EVENT_FALC_ABNORMAL
+               if (conf->media == IF_IFACE_T1) {
+                       /* Disable this interrupt as it may otherwise interfere with 
+                        * other working boards. */
+                       cpc_writeb(falcbase + F_REG(IMR0, ch),
+                                  cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
+               }
+               falc_disable_comm(card, ch);
+               // EVENT_FALC_ABNORMAL
+               cpc_writeb(falcbase + F_REG(LIM1, ch),
+                          cpc_readb(falcbase + F_REG(LIM1, ch)) | LIM1_RL);
+               pfalc->loop_active = 1;
+       } else {
+               cpc_writeb(falcbase + F_REG(LIM1, ch),
+                          cpc_readb(falcbase + F_REG(LIM1, ch)) & ~LIM1_RL);
+               pfalc->sync = 0;
+               cpc_writeb(falcbase + card->hw.cpld_reg2,
+                          cpc_readb(falcbase + card->hw.cpld_reg2) &
+                          ~(CPLD_REG2_FALC_LED2 << (2 * ch)));
+               pfalc->active = 0;
+               falc_issue_cmd(card, ch, CMDR_XRES);
+               pfalc->loop_active = 0;
+       }
+}
+
+/*----------------------------------------------------------------------------
+ * falc_local_loop
+ *----------------------------------------------------------------------------
+ * Description: The local loopback mode disconnects the receive lines 
+ *             RL1/RL2 resp. RDIP/RDIN from the receiver. Instead of the
+ *             signals coming from the line the data provided by system
+ *             interface are routed through the analog receiver back to
+ *             the system interface. The unipolar bit stream will be
+ *             undisturbed transmitted on the line. Receiver and transmitter
+ *             coding must be identical.
+ *----------------------------------------------------------------------------
+ */
+static void falc_local_loop(pc300_t * card, int ch, int loop_on)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (loop_on) {
+               cpc_writeb(falcbase + F_REG(LIM0, ch),
+                          cpc_readb(falcbase + F_REG(LIM0, ch)) | LIM0_LL);
+               pfalc->loop_active = 1;
+       } else {
+               cpc_writeb(falcbase + F_REG(LIM0, ch),
+                          cpc_readb(falcbase + F_REG(LIM0, ch)) & ~LIM0_LL);
+               pfalc->loop_active = 0;
+       }
+}
+
+/*----------------------------------------------------------------------------
+ * falc_payload_loop
+ *----------------------------------------------------------------------------
+ * Description: This routine allows to enable/disable payload loopback.
+ *             When the payload loop is activated, the received 192 bits
+ *             of payload data will be looped back to the transmit
+ *             direction. The framing bits, CRC6 and DL bits are not 
+ *             looped. They are originated by the FALC-LH transmitter.
+ *----------------------------------------------------------------------------
+ */
+static void falc_payload_loop(pc300_t * card, int ch, int loop_on)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (loop_on) {
+               // EVENT_FALC_ABNORMAL
+               if (conf->media == IF_IFACE_T1) {
+                       /* Disable this interrupt as it may otherwise interfere with 
+                        * other working boards. */
+                       cpc_writeb(falcbase + F_REG(IMR0, ch),
+                                  cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
+               }
+               falc_disable_comm(card, ch);
+               // EVENT_FALC_ABNORMAL
+               cpc_writeb(falcbase + F_REG(FMR2, ch),
+                          cpc_readb(falcbase + F_REG(FMR2, ch)) | FMR2_PLB);
+               if (conf->media == IF_IFACE_T1) {
+                       cpc_writeb(falcbase + F_REG(FMR4, ch),
+                                  cpc_readb(falcbase + F_REG(FMR4, ch)) | FMR4_TM);
+               } else {
+                       cpc_writeb(falcbase + F_REG(FMR5, ch),
+                                  cpc_readb(falcbase + F_REG(FMR5, ch)) | XSP_TT0);
+               }
+               falc_open_all_timeslots(card, ch);
+               pfalc->loop_active = 2;
+       } else {
+               cpc_writeb(falcbase + F_REG(FMR2, ch),
+                          cpc_readb(falcbase + F_REG(FMR2, ch)) & ~FMR2_PLB);
+               if (conf->media == IF_IFACE_T1) {
+                       cpc_writeb(falcbase + F_REG(FMR4, ch),
+                                  cpc_readb(falcbase + F_REG(FMR4, ch)) & ~FMR4_TM);
+               } else {
+                       cpc_writeb(falcbase + F_REG(FMR5, ch),
+                                  cpc_readb(falcbase + F_REG(FMR5, ch)) & ~XSP_TT0);
+               }
+               pfalc->sync = 0;
+               cpc_writeb(falcbase + card->hw.cpld_reg2,
+                          cpc_readb(falcbase + card->hw.cpld_reg2) &
+                          ~(CPLD_REG2_FALC_LED2 << (2 * ch)));
+               pfalc->active = 0;
+               falc_issue_cmd(card, ch, CMDR_XRES);
+               pfalc->loop_active = 0;
+       }
+}
+
+/*----------------------------------------------------------------------------
+ * turn_off_xlu
+ *----------------------------------------------------------------------------
+ * Description:        Turns XLU bit off in the proper register
+ *----------------------------------------------------------------------------
+ */
+static void turn_off_xlu(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (conf->media == IF_IFACE_T1) {
+               cpc_writeb(falcbase + F_REG(FMR5, ch),
+                          cpc_readb(falcbase + F_REG(FMR5, ch)) & ~FMR5_XLU);
+       } else {
+               cpc_writeb(falcbase + F_REG(FMR3, ch),
+                          cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_XLU);
+       }
+}
+
+/*----------------------------------------------------------------------------
+ * turn_off_xld
+ *----------------------------------------------------------------------------
+ * Description: Turns XLD bit off in the proper register
+ *----------------------------------------------------------------------------
+ */
+static void turn_off_xld(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (conf->media == IF_IFACE_T1) {
+               cpc_writeb(falcbase + F_REG(FMR5, ch),
+                          cpc_readb(falcbase + F_REG(FMR5, ch)) & ~FMR5_XLD);
+       } else {
+               cpc_writeb(falcbase + F_REG(FMR3, ch),
+                          cpc_readb(falcbase + F_REG(FMR3, ch)) & ~FMR3_XLD);
+       }
+}
+
+/*----------------------------------------------------------------------------
+ * falc_generate_loop_up_code
+ *----------------------------------------------------------------------------
+ * Description:        This routine writes the proper FALC chip register in order
+ *             to generate a LOOP activation code over a T1/E1 line.
+ *----------------------------------------------------------------------------
+ */
+static void falc_generate_loop_up_code(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (conf->media == IF_IFACE_T1) {
+               cpc_writeb(falcbase + F_REG(FMR5, ch),
+                          cpc_readb(falcbase + F_REG(FMR5, ch)) | FMR5_XLU);
+       } else {
+               cpc_writeb(falcbase + F_REG(FMR3, ch),
+                          cpc_readb(falcbase + F_REG(FMR3, ch)) | FMR3_XLU);
+       }
+       // EVENT_FALC_ABNORMAL
+       if (conf->media == IF_IFACE_T1) {
+               /* Disable this interrupt as it may otherwise interfere with 
+                * other working boards. */
+               cpc_writeb(falcbase + F_REG(IMR0, ch),
+                          cpc_readb(falcbase + F_REG(IMR0, ch)) | IMR0_PDEN);
+       }
+       falc_disable_comm(card, ch);
+       // EVENT_FALC_ABNORMAL
+       pfalc->loop_gen = 1;
+}
+
+/*----------------------------------------------------------------------------
+ * falc_generate_loop_down_code
+ *----------------------------------------------------------------------------
+ * Description:        This routine writes the proper FALC chip register in order
+ *             to generate a LOOP deactivation code over a T1/E1 line.
+ *----------------------------------------------------------------------------
+ */
+static void falc_generate_loop_down_code(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (conf->media == IF_IFACE_T1) {
+               cpc_writeb(falcbase + F_REG(FMR5, ch),
+                          cpc_readb(falcbase + F_REG(FMR5, ch)) | FMR5_XLD);
+       } else {
+               cpc_writeb(falcbase + F_REG(FMR3, ch),
+                          cpc_readb(falcbase + F_REG(FMR3, ch)) | FMR3_XLD);
+       }
+       pfalc->sync = 0;
+       cpc_writeb(falcbase + card->hw.cpld_reg2,
+                  cpc_readb(falcbase + card->hw.cpld_reg2) &
+                  ~(CPLD_REG2_FALC_LED2 << (2 * ch)));
+       pfalc->active = 0;
+//?    falc_issue_cmd(card, ch, CMDR_XRES);
+       pfalc->loop_gen = 0;
+}
+
+/*----------------------------------------------------------------------------
+ * falc_pattern_test
+ *----------------------------------------------------------------------------
+ * Description:        This routine generates a pattern code and checks
+ *             it on the reception side.
+ *----------------------------------------------------------------------------
+ */
+static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (activate) {
+               pfalc->prbs = 1;
+               pfalc->bec = 0;
+               if (conf->media == IF_IFACE_T1) {
+                       /* Disable local loop activation/deactivation detect */
+                       cpc_writeb(falcbase + F_REG(IMR3, ch),
+                                  cpc_readb(falcbase + F_REG(IMR3, ch)) | IMR3_LLBSC);
+               } else {
+                       /* Disable local loop activation/deactivation detect */
+                       cpc_writeb(falcbase + F_REG(IMR1, ch),
+                                  cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_LLBSC);
+               }
+               /* Activates generation and monitoring of PRBS 
+                * (Pseudo Random Bit Sequence) */
+               cpc_writeb(falcbase + F_REG(LCR1, ch),
+                          cpc_readb(falcbase + F_REG(LCR1, ch)) | LCR1_EPRM | LCR1_XPRBS);
+       } else {
+               pfalc->prbs = 0;
+               /* Deactivates generation and monitoring of PRBS 
+                * (Pseudo Random Bit Sequence) */
+               cpc_writeb(falcbase + F_REG(LCR1, ch),
+                          cpc_readb(falcbase+F_REG(LCR1,ch)) & ~(LCR1_EPRM | LCR1_XPRBS));
+               if (conf->media == IF_IFACE_T1) {
+                       /* Enable local loop activation/deactivation detect */
+                       cpc_writeb(falcbase + F_REG(IMR3, ch),
+                                  cpc_readb(falcbase + F_REG(IMR3, ch)) & ~IMR3_LLBSC);
+               } else {
+                       /* Enable local loop activation/deactivation detect */
+                       cpc_writeb(falcbase + F_REG(IMR1, ch),
+                                  cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_LLBSC);
+               }
+       }
+}
+
+/*----------------------------------------------------------------------------
+ * falc_pattern_test_error
+ *----------------------------------------------------------------------------
+ * Description:        This routine returns the bit error counter value
+ *----------------------------------------------------------------------------
+ */
+static u16 falc_pattern_test_error(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+
+       return pfalc->bec;
+}
+
+/**********************************/
+/***   Net Interface Routines   ***/
+/**********************************/
+
+static void
+cpc_trace(struct net_device *dev, struct sk_buff *skb_main, char rx_tx)
+{
+       struct sk_buff *skb;
+
+       if ((skb = dev_alloc_skb(10 + skb_main->len)) == NULL) {
+               printk("%s: out of memory\n", dev->name);
+               return;
+       }
+       skb_put(skb, 10 + skb_main->len);
+
+       skb->dev = dev;
+       skb->protocol = htons(ETH_P_CUST);
+       skb_reset_mac_header(skb);
+       skb->pkt_type = PACKET_HOST;
+       skb->len = 10 + skb_main->len;
+
+       skb_copy_to_linear_data(skb, dev->name, 5);
+       skb->data[5] = '[';
+       skb->data[6] = rx_tx;
+       skb->data[7] = ']';
+       skb->data[8] = ':';
+       skb->data[9] = ' ';
+       skb_copy_from_linear_data(skb_main, &skb->data[10], skb_main->len);
+
+       netif_rx(skb);
+}
+
+static void cpc_tx_timeout(struct net_device *dev)
+{
+       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       int ch = chan->channel;
+       unsigned long flags;
+       u8 ilar;
+
+       dev->stats.tx_errors++;
+       dev->stats.tx_aborted_errors++;
+       CPC_LOCK(card, flags);
+       if ((ilar = cpc_readb(card->hw.scabase + ILAR)) != 0) {
+               printk("%s: ILAR=0x%x\n", dev->name, ilar);
+               cpc_writeb(card->hw.scabase + ILAR, ilar);
+               cpc_writeb(card->hw.scabase + DMER, 0x80);
+       }
+       if (card->hw.type == PC300_TE) {
+               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
+                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) &
+                          ~(CPLD_REG2_FALC_LED1 << (2 * ch)));
+       }
+       dev->trans_start = jiffies; /* prevent tx timeout */
+       CPC_UNLOCK(card, flags);
+       netif_wake_queue(dev);
+}
+
+static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       int ch = chan->channel;
+       unsigned long flags;
+#ifdef PC300_DEBUG_TX
+       int i;
+#endif
+
+       if (!netif_carrier_ok(dev)) {
+               /* DCD must be OFF: drop packet */
+               dev_kfree_skb(skb);
+               dev->stats.tx_errors++;
+               dev->stats.tx_carrier_errors++;
+               return 0;
+       } else if (cpc_readb(card->hw.scabase + M_REG(ST3, ch)) & ST3_DCD) {
+               printk("%s: DCD is OFF. Going administrative down.\n", dev->name);
+               dev->stats.tx_errors++;
+               dev->stats.tx_carrier_errors++;
+               dev_kfree_skb(skb);
+               netif_carrier_off(dev);
+               CPC_LOCK(card, flags);
+               cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR);
+               if (card->hw.type == PC300_TE) {
+                       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
+                                  cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & 
+                                                       ~(CPLD_REG2_FALC_LED1 << (2 * ch)));
+               }
+               CPC_UNLOCK(card, flags);
+               netif_wake_queue(dev);
+               return 0;
+       }
+
+       /* Write buffer to DMA buffers */
+       if (dma_buf_write(card, ch, (u8 *)skb->data, skb->len) != 0) {
+//             printk("%s: write error. Dropping TX packet.\n", dev->name);
+               netif_stop_queue(dev);
+               dev_kfree_skb(skb);
+               dev->stats.tx_errors++;
+               dev->stats.tx_dropped++;
+               return 0;
+       }
+#ifdef PC300_DEBUG_TX
+       printk("%s T:", dev->name);
+       for (i = 0; i < skb->len; i++)
+               printk(" %02x", *(skb->data + i));
+       printk("\n");
+#endif
+
+       if (d->trace_on) {
+               cpc_trace(dev, skb, 'T');
+       }
+
+       /* Start transmission */
+       CPC_LOCK(card, flags);
+       /* verify if it has more than one free descriptor */
+       if (card->chan[ch].nfree_tx_bd <= 1) {
+               /* don't have so stop the queue */
+               netif_stop_queue(dev);
+       }
+       cpc_writel(card->hw.scabase + DTX_REG(EDAL, ch),
+                  TX_BD_ADDR(ch, chan->tx_next_bd));
+       cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA);
+       cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE);
+       if (card->hw.type == PC300_TE) {
+               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
+                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) |
+                          (CPLD_REG2_FALC_LED1 << (2 * ch)));
+       }
+       CPC_UNLOCK(card, flags);
+       dev_kfree_skb(skb);
+
+       return 0;
+}
+
+static void cpc_net_rx(struct net_device *dev)
+{
+       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       int ch = chan->channel;
+#ifdef PC300_DEBUG_RX
+       int i;
+#endif
+       int rxb;
+       struct sk_buff *skb;
+
+       while (1) {
+               if ((rxb = dma_get_rx_frame_size(card, ch)) == -1)
+                       return;
+
+               if (!netif_carrier_ok(dev)) {
+                       /* DCD must be OFF: drop packet */
+                   printk("%s : DCD is OFF - drop %d rx bytes\n", dev->name, rxb); 
+                       skb = NULL;
+               } else {
+                       if (rxb > (dev->mtu + 40)) { /* add headers */
+                               printk("%s : MTU exceeded %d\n", dev->name, rxb); 
+                               skb = NULL;
+                       } else {
+                               skb = dev_alloc_skb(rxb);
+                               if (skb == NULL) {
+                                       printk("%s: Memory squeeze!!\n", dev->name);
+                                       return;
+                               }
+                               skb->dev = dev;
+                       }
+               }
+
+               if (((rxb = dma_buf_read(card, ch, skb)) <= 0) || (skb == NULL)) {
+#ifdef PC300_DEBUG_RX
+                       printk("%s: rxb = %x\n", dev->name, rxb);
+#endif
+                       if ((skb == NULL) && (rxb > 0)) {
+                               /* rxb > dev->mtu */
+                               dev->stats.rx_errors++;
+                               dev->stats.rx_length_errors++;
+                               continue;
+                       }
+
+                       if (rxb < 0) {  /* Invalid frame */
+                               rxb = -rxb;
+                               if (rxb & DST_OVR) {
+                                       dev->stats.rx_errors++;
+                                       dev->stats.rx_fifo_errors++;
+                               }
+                               if (rxb & DST_CRC) {
+                                       dev->stats.rx_errors++;
+                                       dev->stats.rx_crc_errors++;
+                               }
+                               if (rxb & (DST_RBIT | DST_SHRT | DST_ABT)) {
+                                       dev->stats.rx_errors++;
+                                       dev->stats.rx_frame_errors++;
+                               }
+                       }
+                       if (skb) {
+                               dev_kfree_skb_irq(skb);
+                       }
+                       continue;
+               }
+
+               dev->stats.rx_bytes += rxb;
+
+#ifdef PC300_DEBUG_RX
+               printk("%s R:", dev->name);
+               for (i = 0; i < skb->len; i++)
+                       printk(" %02x", *(skb->data + i));
+               printk("\n");
+#endif
+               if (d->trace_on) {
+                       cpc_trace(dev, skb, 'R');
+               }
+               dev->stats.rx_packets++;
+               skb->protocol = hdlc_type_trans(skb, dev);
+               netif_rx(skb);
+       }
+}
+
+/************************************/
+/***   PC300 Interrupt Routines   ***/
+/************************************/
+static void sca_tx_intr(pc300dev_t *dev)
+{
+       pc300ch_t *chan = (pc300ch_t *)dev->chan; 
+       pc300_t *card = (pc300_t *)chan->card; 
+       int ch = chan->channel; 
+       volatile pcsca_bd_t __iomem * ptdescr; 
+
+    /* Clean up descriptors from previous transmission */
+       ptdescr = (card->hw.rambase +
+                                               TX_BD_ADDR(ch,chan->tx_first_bd));
+       while ((cpc_readl(card->hw.scabase + DTX_REG(CDAL,ch)) !=
+               TX_BD_ADDR(ch,chan->tx_first_bd)) &&
+              (cpc_readb(&ptdescr->status) & DST_OSB)) {
+               dev->dev->stats.tx_packets++;
+               dev->dev->stats.tx_bytes += cpc_readw(&ptdescr->len);
+               cpc_writeb(&ptdescr->status, DST_OSB);
+               cpc_writew(&ptdescr->len, 0);
+               chan->nfree_tx_bd++;
+               chan->tx_first_bd = (chan->tx_first_bd + 1) & (N_DMA_TX_BUF - 1);
+               ptdescr = (card->hw.rambase + TX_BD_ADDR(ch,chan->tx_first_bd));
+    }
+
+#ifdef CONFIG_PC300_MLPPP
+       if (chan->conf.proto == PC300_PROTO_MLPPP) {
+                       cpc_tty_trigger_poll(dev);
+       } else {
+#endif
+       /* Tell the upper layer we are ready to transmit more packets */
+               netif_wake_queue(dev->dev);
+#ifdef CONFIG_PC300_MLPPP
+       }
+#endif
+}
+
+static void sca_intr(pc300_t * card)
+{
+       void __iomem *scabase = card->hw.scabase;
+       volatile u32 status;
+       int ch;
+       int intr_count = 0;
+       unsigned char dsr_rx;
+
+       while ((status = cpc_readl(scabase + ISR0)) != 0) {
+               for (ch = 0; ch < card->hw.nchan; ch++) {
+                       pc300ch_t *chan = &card->chan[ch];
+                       pc300dev_t *d = &chan->d;
+                       struct net_device *dev = d->dev;
+
+                       spin_lock(&card->card_lock);
+
+           /**** Reception ****/
+                       if (status & IR0_DRX((IR0_DMIA | IR0_DMIB), ch)) {
+                               u8 drx_stat = cpc_readb(scabase + DSR_RX(ch));
+
+                               /* Clear RX interrupts */
+                               cpc_writeb(scabase + DSR_RX(ch), drx_stat | DSR_DWE);
+
+#ifdef PC300_DEBUG_INTR
+                               printk ("sca_intr: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x)\n",
+                                        ch, status, drx_stat);
+#endif
+                               if (status & IR0_DRX(IR0_DMIA, ch)) {
+                                       if (drx_stat & DSR_BOF) {
+#ifdef CONFIG_PC300_MLPPP
+                                               if (chan->conf.proto == PC300_PROTO_MLPPP) {
+                                                       /* verify if driver is TTY */
+                                                       if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
+                                                               rx_dma_stop(card, ch);
+                                                       }
+                                                       cpc_tty_receive(d);
+                                                       rx_dma_start(card, ch);
+                                               } else 
+#endif
+                                               {
+                                                       if ((cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
+                                                               rx_dma_stop(card, ch);
+                                                       }
+                                                       cpc_net_rx(dev);
+                                                       /* Discard invalid frames */
+                                                       dev->stats.rx_errors++;
+                                                       dev->stats.rx_over_errors++;
+                                                       chan->rx_first_bd = 0;
+                                                       chan->rx_last_bd = N_DMA_RX_BUF - 1;
+                                                       rx_dma_start(card, ch);
+                                               }
+                                       }
+                               }
+                               if (status & IR0_DRX(IR0_DMIB, ch)) {
+                                       if (drx_stat & DSR_EOM) {
+                                               if (card->hw.type == PC300_TE) {
+                                                       cpc_writeb(card->hw.falcbase +
+                                                                  card->hw.cpld_reg2,
+                                                                  cpc_readb (card->hw.falcbase +
+                                                                       card->hw.cpld_reg2) |
+                                                                  (CPLD_REG2_FALC_LED1 << (2 * ch)));
+                                               }
+#ifdef CONFIG_PC300_MLPPP
+                                               if (chan->conf.proto == PC300_PROTO_MLPPP) {
+                                                       /* verify if driver is TTY */
+                                                       cpc_tty_receive(d);
+                                               } else {
+                                                       cpc_net_rx(dev);
+                                               }
+#else
+                                               cpc_net_rx(dev);
+#endif
+                                               if (card->hw.type == PC300_TE) {
+                                                       cpc_writeb(card->hw.falcbase +
+                                                                  card->hw.cpld_reg2,
+                                                                  cpc_readb (card->hw.falcbase +
+                                                                               card->hw.cpld_reg2) &
+                                                                  ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
+                                               }
+                                       }
+                               }
+                               if (!(dsr_rx = cpc_readb(scabase + DSR_RX(ch)) & DSR_DE)) {
+#ifdef PC300_DEBUG_INTR
+               printk("%s: RX intr chan[%d] (st=0x%08lx, dsr=0x%02x, dsr2=0x%02x)\n",
+                       dev->name, ch, status, drx_stat, dsr_rx);
+#endif
+                                       cpc_writeb(scabase + DSR_RX(ch), (dsr_rx | DSR_DE) & 0xfe);
+                               }
+                       }
+
+           /**** Transmission ****/
+                       if (status & IR0_DTX((IR0_EFT | IR0_DMIA | IR0_DMIB), ch)) {
+                               u8 dtx_stat = cpc_readb(scabase + DSR_TX(ch));
+
+                               /* Clear TX interrupts */
+                               cpc_writeb(scabase + DSR_TX(ch), dtx_stat | DSR_DWE);
+
+#ifdef PC300_DEBUG_INTR
+                               printk ("sca_intr: TX intr chan[%d] (st=0x%08lx, dsr=0x%02x)\n",
+                                        ch, status, dtx_stat);
+#endif
+                               if (status & IR0_DTX(IR0_EFT, ch)) {
+                                       if (dtx_stat & DSR_UDRF) {
+                                               if (cpc_readb (scabase + M_REG(TBN, ch)) != 0) {
+                                                       cpc_writeb(scabase + M_REG(CMD,ch), CMD_TX_BUF_CLR);
+                                               }
+                                               if (card->hw.type == PC300_TE) {
+                                                       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
+                                                                  cpc_readb (card->hw.falcbase + 
+                                                                                  card->hw.cpld_reg2) &
+                                                                  ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
+                                               }
+                                               dev->stats.tx_errors++;
+                                               dev->stats.tx_fifo_errors++;
+                                               sca_tx_intr(d);
+                                       }
+                               }
+                               if (status & IR0_DTX(IR0_DMIA, ch)) {
+                                       if (dtx_stat & DSR_BOF) {
+                                       }
+                               }
+                               if (status & IR0_DTX(IR0_DMIB, ch)) {
+                                       if (dtx_stat & DSR_EOM) {
+                                               if (card->hw.type == PC300_TE) {
+                                                       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
+                                                                  cpc_readb (card->hw.falcbase +
+                                                                                       card->hw.cpld_reg2) &
+                                                                  ~ (CPLD_REG2_FALC_LED1 << (2 * ch)));
+                                               }
+                                               sca_tx_intr(d);
+                                       }
+                               }
+                       }
+
+           /**** MSCI ****/
+                       if (status & IR0_M(IR0_RXINTA, ch)) {
+                               u8 st1 = cpc_readb(scabase + M_REG(ST1, ch));
+
+                               /* Clear MSCI interrupts */
+                               cpc_writeb(scabase + M_REG(ST1, ch), st1);
+
+#ifdef PC300_DEBUG_INTR
+                               printk("sca_intr: MSCI intr chan[%d] (st=0x%08lx, st1=0x%02x)\n",
+                                        ch, status, st1);
+#endif
+                               if (st1 & ST1_CDCD) {   /* DCD changed */
+                                       if (cpc_readb(scabase + M_REG(ST3, ch)) & ST3_DCD) {
+                                               printk ("%s: DCD is OFF. Going administrative down.\n",
+                                                        dev->name);
+#ifdef CONFIG_PC300_MLPPP
+                                               if (chan->conf.proto != PC300_PROTO_MLPPP) {
+                                                       netif_carrier_off(dev);
+                                               }
+#else
+                                               netif_carrier_off(dev);
+
+#endif
+                                               card->chan[ch].d.line_off++;
+                                       } else {        /* DCD = 1 */
+                                               printk ("%s: DCD is ON. Going administrative up.\n",
+                                                        dev->name);
+#ifdef CONFIG_PC300_MLPPP
+                                               if (chan->conf.proto != PC300_PROTO_MLPPP)
+                                                       /* verify if driver is not TTY */
+#endif
+                                                       netif_carrier_on(dev);
+                                               card->chan[ch].d.line_on++;
+                                       }
+                               }
+                       }
+                       spin_unlock(&card->card_lock);
+               }
+               if (++intr_count == 10)
+                       /* Too much work at this board. Force exit */
+                       break;
+       }
+}
+
+static void falc_t1_loop_detection(pc300_t *card, int ch, u8 frs1)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
+           !pfalc->loop_gen) {
+               if (frs1 & FRS1_LLBDD) {
+                       // A Line Loop Back Deactivation signal detected
+                       if (pfalc->loop_active) {
+                               falc_remote_loop(card, ch, 0);
+                       }
+               } else {
+                       if ((frs1 & FRS1_LLBAD) &&
+                           ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) {
+                               // A Line Loop Back Activation signal detected  
+                               if (!pfalc->loop_active) {
+                                       falc_remote_loop(card, ch, 1);
+                               }
+                       }
+               }
+       }
+}
+
+static void falc_e1_loop_detection(pc300_t *card, int ch, u8 rsp)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+
+       if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) &&
+           !pfalc->loop_gen) {
+               if (rsp & RSP_LLBDD) {
+                       // A Line Loop Back Deactivation signal detected
+                       if (pfalc->loop_active) {
+                               falc_remote_loop(card, ch, 0);
+                       }
+               } else {
+                       if ((rsp & RSP_LLBAD) &&
+                           ((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_EPRM) == 0)) {
+                               // A Line Loop Back Activation signal detected  
+                               if (!pfalc->loop_active) {
+                                       falc_remote_loop(card, ch, 1);
+                               }
+                       }
+               }
+       }
+}
+
+static void falc_t1_intr(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+       u8 isr0, isr3, gis;
+       u8 dummy;
+
+       while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) {
+               if (gis & GIS_ISR0) {
+                       isr0 = cpc_readb(falcbase + F_REG(FISR0, ch));
+                       if (isr0 & FISR0_PDEN) {
+                               /* Read the bit to clear the situation */
+                               if (cpc_readb(falcbase + F_REG(FRS1, ch)) &
+                                   FRS1_PDEN) {
+                                       pfalc->pden++;
+                               }
+                       }
+               }
+
+               if (gis & GIS_ISR1) {
+                       dummy = cpc_readb(falcbase + F_REG(FISR1, ch));
+               }
+
+               if (gis & GIS_ISR2) {
+                       dummy = cpc_readb(falcbase + F_REG(FISR2, ch));
+               }
+
+               if (gis & GIS_ISR3) {
+                       isr3 = cpc_readb(falcbase + F_REG(FISR3, ch));
+                       if (isr3 & FISR3_SEC) {
+                               pfalc->sec++;
+                               falc_update_stats(card, ch);
+                               falc_check_status(card, ch,
+                                                 cpc_readb(falcbase + F_REG(FRS0, ch)));
+                       }
+                       if (isr3 & FISR3_ES) {
+                               pfalc->es++;
+                       }
+                       if (isr3 & FISR3_LLBSC) {
+                               falc_t1_loop_detection(card, ch,
+                                                      cpc_readb(falcbase + F_REG(FRS1, ch)));
+                       }
+               }
+       }
+}
+
+static void falc_e1_intr(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = (pc300ch_t *) & card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       void __iomem *falcbase = card->hw.falcbase;
+       u8 isr1, isr2, isr3, gis, rsp;
+       u8 dummy;
+
+       while ((gis = cpc_readb(falcbase + F_REG(GIS, ch))) != 0) {
+               rsp = cpc_readb(falcbase + F_REG(RSP, ch));
+
+               if (gis & GIS_ISR0) {
+                       dummy = cpc_readb(falcbase + F_REG(FISR0, ch));
+               }
+               if (gis & GIS_ISR1) {
+                       isr1 = cpc_readb(falcbase + F_REG(FISR1, ch));
+                       if (isr1 & FISR1_XMB) {
+                               if ((pfalc->xmb_cause & 2) &&
+                                   pfalc->multiframe_mode) {
+                                       if (cpc_readb (falcbase + F_REG(FRS0, ch)) & 
+                                                                       (FRS0_LOS | FRS0_AIS | FRS0_LFA)) {
+                                               cpc_writeb(falcbase + F_REG(XSP, ch),
+                                                          cpc_readb(falcbase + F_REG(XSP, ch))
+                                                          & ~XSP_AXS);
+                                       } else {
+                                               cpc_writeb(falcbase + F_REG(XSP, ch),
+                                                          cpc_readb(falcbase + F_REG(XSP, ch))
+                                                          | XSP_AXS);
+                                       }
+                               }
+                               pfalc->xmb_cause = 0;
+                               cpc_writeb(falcbase + F_REG(IMR1, ch),
+                                          cpc_readb(falcbase + F_REG(IMR1, ch)) | IMR1_XMB);
+                       }
+                       if (isr1 & FISR1_LLBSC) {
+                               falc_e1_loop_detection(card, ch, rsp);
+                       }
+               }
+               if (gis & GIS_ISR2) {
+                       isr2 = cpc_readb(falcbase + F_REG(FISR2, ch));
+                       if (isr2 & FISR2_T400MS) {
+                               cpc_writeb(falcbase + F_REG(XSW, ch),
+                                          cpc_readb(falcbase + F_REG(XSW, ch)) | XSW_XRA);
+                       }
+                       if (isr2 & FISR2_MFAR) {
+                               cpc_writeb(falcbase + F_REG(XSW, ch),
+                                          cpc_readb(falcbase + F_REG(XSW, ch)) & ~XSW_XRA);
+                       }
+                       if (isr2 & (FISR2_FAR | FISR2_LFA | FISR2_AIS | FISR2_LOS)) {
+                               pfalc->xmb_cause |= 2;
+                               cpc_writeb(falcbase + F_REG(IMR1, ch),
+                                          cpc_readb(falcbase + F_REG(IMR1, ch)) & ~IMR1_XMB);
+                       }
+               }
+               if (gis & GIS_ISR3) {
+                       isr3 = cpc_readb(falcbase + F_REG(FISR3, ch));
+                       if (isr3 & FISR3_SEC) {
+                               pfalc->sec++;
+                               falc_update_stats(card, ch);
+                               falc_check_status(card, ch,
+                                                 cpc_readb(falcbase + F_REG(FRS0, ch)));
+                       }
+                       if (isr3 & FISR3_ES) {
+                               pfalc->es++;
+                       }
+               }
+       }
+}
+
+static void falc_intr(pc300_t * card)
+{
+       int ch;
+
+       for (ch = 0; ch < card->hw.nchan; ch++) {
+               pc300ch_t *chan = &card->chan[ch];
+               pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+
+               if (conf->media == IF_IFACE_T1) {
+                       falc_t1_intr(card, ch);
+               } else {
+                       falc_e1_intr(card, ch);
+               }
+       }
+}
+
+static irqreturn_t cpc_intr(int irq, void *dev_id)
+{
+       pc300_t *card = dev_id;
+       volatile u8 plx_status;
+
+       if (!card) {
+#ifdef PC300_DEBUG_INTR
+               printk("cpc_intr: spurious intr %d\n", irq);
+#endif
+               return IRQ_NONE;                /* spurious intr */
+       }
+
+       if (!card->hw.rambase) {
+#ifdef PC300_DEBUG_INTR
+               printk("cpc_intr: spurious intr2 %d\n", irq);
+#endif
+               return IRQ_NONE;                /* spurious intr */
+       }
+
+       switch (card->hw.type) {
+               case PC300_RSV:
+               case PC300_X21:
+                       sca_intr(card);
+                       break;
+
+               case PC300_TE:
+                       while ( (plx_status = (cpc_readb(card->hw.plxbase + card->hw.intctl_reg) &
+                                (PLX_9050_LINT1_STATUS | PLX_9050_LINT2_STATUS))) != 0) {
+                               if (plx_status & PLX_9050_LINT1_STATUS) {       /* SCA Interrupt */
+                                       sca_intr(card);
+                               }
+                               if (plx_status & PLX_9050_LINT2_STATUS) {       /* FALC Interrupt */
+                                       falc_intr(card);
+                               }
+                       }
+                       break;
+       }
+       return IRQ_HANDLED;
+}
+
+static void cpc_sca_status(pc300_t * card, int ch)
+{
+       u8 ilar;
+       void __iomem *scabase = card->hw.scabase;
+       unsigned long flags;
+
+       tx_dma_buf_check(card, ch);
+       rx_dma_buf_check(card, ch);
+       ilar = cpc_readb(scabase + ILAR);
+       printk ("ILAR=0x%02x, WCRL=0x%02x, PCR=0x%02x, BTCR=0x%02x, BOLR=0x%02x\n",
+                ilar, cpc_readb(scabase + WCRL), cpc_readb(scabase + PCR),
+                cpc_readb(scabase + BTCR), cpc_readb(scabase + BOLR));
+       printk("TX_CDA=0x%08x, TX_EDA=0x%08x\n",
+              cpc_readl(scabase + DTX_REG(CDAL, ch)),
+              cpc_readl(scabase + DTX_REG(EDAL, ch)));
+       printk("RX_CDA=0x%08x, RX_EDA=0x%08x, BFL=0x%04x\n",
+              cpc_readl(scabase + DRX_REG(CDAL, ch)),
+              cpc_readl(scabase + DRX_REG(EDAL, ch)),
+              cpc_readw(scabase + DRX_REG(BFLL, ch)));
+       printk("DMER=0x%02x, DSR_TX=0x%02x, DSR_RX=0x%02x\n",
+              cpc_readb(scabase + DMER), cpc_readb(scabase + DSR_TX(ch)),
+              cpc_readb(scabase + DSR_RX(ch)));
+       printk("DMR_TX=0x%02x, DMR_RX=0x%02x, DIR_TX=0x%02x, DIR_RX=0x%02x\n",
+              cpc_readb(scabase + DMR_TX(ch)), cpc_readb(scabase + DMR_RX(ch)),
+              cpc_readb(scabase + DIR_TX(ch)),
+              cpc_readb(scabase + DIR_RX(ch)));
+       printk("DCR_TX=0x%02x, DCR_RX=0x%02x, FCT_TX=0x%02x, FCT_RX=0x%02x\n",
+              cpc_readb(scabase + DCR_TX(ch)), cpc_readb(scabase + DCR_RX(ch)),
+              cpc_readb(scabase + FCT_TX(ch)),
+              cpc_readb(scabase + FCT_RX(ch)));
+       printk("MD0=0x%02x, MD1=0x%02x, MD2=0x%02x, MD3=0x%02x, IDL=0x%02x\n",
+              cpc_readb(scabase + M_REG(MD0, ch)),
+              cpc_readb(scabase + M_REG(MD1, ch)),
+              cpc_readb(scabase + M_REG(MD2, ch)),
+              cpc_readb(scabase + M_REG(MD3, ch)),
+              cpc_readb(scabase + M_REG(IDL, ch)));
+       printk("CMD=0x%02x, SA0=0x%02x, SA1=0x%02x, TFN=0x%02x, CTL=0x%02x\n",
+              cpc_readb(scabase + M_REG(CMD, ch)),
+              cpc_readb(scabase + M_REG(SA0, ch)),
+              cpc_readb(scabase + M_REG(SA1, ch)),
+              cpc_readb(scabase + M_REG(TFN, ch)),
+              cpc_readb(scabase + M_REG(CTL, ch)));
+       printk("ST0=0x%02x, ST1=0x%02x, ST2=0x%02x, ST3=0x%02x, ST4=0x%02x\n",
+              cpc_readb(scabase + M_REG(ST0, ch)),
+              cpc_readb(scabase + M_REG(ST1, ch)),
+              cpc_readb(scabase + M_REG(ST2, ch)),
+              cpc_readb(scabase + M_REG(ST3, ch)),
+              cpc_readb(scabase + M_REG(ST4, ch)));
+       printk ("CST0=0x%02x, CST1=0x%02x, CST2=0x%02x, CST3=0x%02x, FST=0x%02x\n",
+                cpc_readb(scabase + M_REG(CST0, ch)),
+                cpc_readb(scabase + M_REG(CST1, ch)),
+                cpc_readb(scabase + M_REG(CST2, ch)),
+                cpc_readb(scabase + M_REG(CST3, ch)),
+                cpc_readb(scabase + M_REG(FST, ch)));
+       printk("TRC0=0x%02x, TRC1=0x%02x, RRC=0x%02x, TBN=0x%02x, RBN=0x%02x\n",
+              cpc_readb(scabase + M_REG(TRC0, ch)),
+              cpc_readb(scabase + M_REG(TRC1, ch)),
+              cpc_readb(scabase + M_REG(RRC, ch)),
+              cpc_readb(scabase + M_REG(TBN, ch)),
+              cpc_readb(scabase + M_REG(RBN, ch)));
+       printk("TFS=0x%02x, TNR0=0x%02x, TNR1=0x%02x, RNR=0x%02x\n",
+              cpc_readb(scabase + M_REG(TFS, ch)),
+              cpc_readb(scabase + M_REG(TNR0, ch)),
+              cpc_readb(scabase + M_REG(TNR1, ch)),
+              cpc_readb(scabase + M_REG(RNR, ch)));
+       printk("TCR=0x%02x, RCR=0x%02x, TNR1=0x%02x, RNR=0x%02x\n",
+              cpc_readb(scabase + M_REG(TCR, ch)),
+              cpc_readb(scabase + M_REG(RCR, ch)),
+              cpc_readb(scabase + M_REG(TNR1, ch)),
+              cpc_readb(scabase + M_REG(RNR, ch)));
+       printk("TXS=0x%02x, RXS=0x%02x, EXS=0x%02x, TMCT=0x%02x, TMCR=0x%02x\n",
+              cpc_readb(scabase + M_REG(TXS, ch)),
+              cpc_readb(scabase + M_REG(RXS, ch)),
+              cpc_readb(scabase + M_REG(EXS, ch)),
+              cpc_readb(scabase + M_REG(TMCT, ch)),
+              cpc_readb(scabase + M_REG(TMCR, ch)));
+       printk("IE0=0x%02x, IE1=0x%02x, IE2=0x%02x, IE4=0x%02x, FIE=0x%02x\n",
+              cpc_readb(scabase + M_REG(IE0, ch)),
+              cpc_readb(scabase + M_REG(IE1, ch)),
+              cpc_readb(scabase + M_REG(IE2, ch)),
+              cpc_readb(scabase + M_REG(IE4, ch)),
+              cpc_readb(scabase + M_REG(FIE, ch)));
+       printk("IER0=0x%08x\n", cpc_readl(scabase + IER0));
+
+       if (ilar != 0) {
+               CPC_LOCK(card, flags);
+               cpc_writeb(scabase + ILAR, ilar);
+               cpc_writeb(scabase + DMER, 0x80);
+               CPC_UNLOCK(card, flags);
+       }
+}
+
+static void cpc_falc_status(pc300_t * card, int ch)
+{
+       pc300ch_t *chan = &card->chan[ch];
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       unsigned long flags;
+
+       CPC_LOCK(card, flags);
+       printk("CH%d:   %s %s  %d channels\n",
+              ch, (pfalc->sync ? "SYNC" : ""), (pfalc->active ? "ACTIVE" : ""),
+              pfalc->num_channels);
+
+       printk("        pden=%d,  los=%d,  losr=%d,  lfa=%d,  farec=%d\n",
+              pfalc->pden, pfalc->los, pfalc->losr, pfalc->lfa, pfalc->farec);
+       printk("        lmfa=%d,  ais=%d,  sec=%d,  es=%d,  rai=%d\n",
+              pfalc->lmfa, pfalc->ais, pfalc->sec, pfalc->es, pfalc->rai);
+       printk("        bec=%d,  fec=%d,  cvc=%d,  cec=%d,  ebc=%d\n",
+              pfalc->bec, pfalc->fec, pfalc->cvc, pfalc->cec, pfalc->ebc);
+
+       printk("\n");
+       printk("        STATUS: %s  %s  %s  %s  %s  %s\n",
+              (pfalc->red_alarm ? "RED" : ""),
+              (pfalc->blue_alarm ? "BLU" : ""),
+              (pfalc->yellow_alarm ? "YEL" : ""),
+              (pfalc->loss_fa ? "LFA" : ""),
+              (pfalc->loss_mfa ? "LMF" : ""), (pfalc->prbs ? "PRB" : ""));
+       CPC_UNLOCK(card, flags);
+}
+
+static int cpc_change_mtu(struct net_device *dev, int new_mtu)
+{
+       if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU))
+               return -EINVAL;
+       dev->mtu = new_mtu;
+       return 0;
+}
+
+static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+{
+       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       pc300conf_t conf_aux;
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       int ch = chan->channel;
+       void __user *arg = ifr->ifr_data;
+       struct if_settings *settings = &ifr->ifr_settings;
+       void __iomem *scabase = card->hw.scabase;
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EPERM;
+
+       switch (cmd) {
+               case SIOCGPC300CONF:
+#ifdef CONFIG_PC300_MLPPP
+                       if (conf->proto != PC300_PROTO_MLPPP) {
+                               conf->proto = /* FIXME hdlc->proto.id */ 0;
+                       }
+#else
+                       conf->proto = /* FIXME hdlc->proto.id */ 0;
+#endif
+                       memcpy(&conf_aux.conf, conf, sizeof(pc300chconf_t));
+                       memcpy(&conf_aux.hw, &card->hw, sizeof(pc300hw_t));
+                       if (!arg || 
+                               copy_to_user(arg, &conf_aux, sizeof(pc300conf_t))) 
+                               return -EINVAL;
+                       return 0;
+               case SIOCSPC300CONF:
+                       if (!capable(CAP_NET_ADMIN))
+                               return -EPERM;
+                       if (!arg || 
+                               copy_from_user(&conf_aux.conf, arg, sizeof(pc300chconf_t)))
+                               return -EINVAL;
+                       if (card->hw.cpld_id < 0x02 &&
+                           conf_aux.conf.fr_mode == PC300_FR_UNFRAMED) {
+                               /* CPLD_ID < 0x02 doesn't support Unframed E1 */
+                               return -EINVAL;
+                       }
+#ifdef CONFIG_PC300_MLPPP
+                       if (conf_aux.conf.proto == PC300_PROTO_MLPPP) {
+                               if (conf->proto != PC300_PROTO_MLPPP) {
+                                       memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
+                                       cpc_tty_init(d);        /* init TTY driver */
+                               }
+                       } else {
+                               if (conf_aux.conf.proto == 0xffff) {
+                                       if (conf->proto == PC300_PROTO_MLPPP){ 
+                                               /* ifdown interface */
+                                               cpc_close(dev);
+                                       }
+                               } else {
+                                       memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
+                                       /* FIXME hdlc->proto.id = conf->proto; */
+                               }
+                       }
+#else
+                       memcpy(conf, &conf_aux.conf, sizeof(pc300chconf_t));
+                       /* FIXME hdlc->proto.id = conf->proto; */
+#endif
+                       return 0;
+               case SIOCGPC300STATUS:
+                       cpc_sca_status(card, ch);
+                       return 0;
+               case SIOCGPC300FALCSTATUS:
+                       cpc_falc_status(card, ch);
+                       return 0;
+
+               case SIOCGPC300UTILSTATS:
+                       {
+                               if (!arg) {     /* clear statistics */
+                                       memset(&dev->stats, 0, sizeof(dev->stats));
+                                       if (card->hw.type == PC300_TE) {
+                                               memset(&chan->falc, 0, sizeof(falc_t));
+                                       }
+                               } else {
+                                       pc300stats_t pc300stats;
+
+                                       memset(&pc300stats, 0, sizeof(pc300stats_t));
+                                       pc300stats.hw_type = card->hw.type;
+                                       pc300stats.line_on = card->chan[ch].d.line_on;
+                                       pc300stats.line_off = card->chan[ch].d.line_off;
+                                       memcpy(&pc300stats.gen_stats, &dev->stats,
+                                              sizeof(dev->stats));
+                                       if (card->hw.type == PC300_TE)
+                                               memcpy(&pc300stats.te_stats,&chan->falc,sizeof(falc_t));
+                                       if (copy_to_user(arg, &pc300stats, sizeof(pc300stats_t)))
+                                               return -EFAULT;
+                               }
+                               return 0;
+                       }
+
+               case SIOCGPC300UTILSTATUS:
+                       {
+                               struct pc300status pc300status;
+
+                               pc300status.hw_type = card->hw.type;
+                               if (card->hw.type == PC300_TE) {
+                                       pc300status.te_status.sync = chan->falc.sync;
+                                       pc300status.te_status.red_alarm = chan->falc.red_alarm;
+                                       pc300status.te_status.blue_alarm = chan->falc.blue_alarm;
+                                       pc300status.te_status.loss_fa = chan->falc.loss_fa;
+                                       pc300status.te_status.yellow_alarm =chan->falc.yellow_alarm;
+                                       pc300status.te_status.loss_mfa = chan->falc.loss_mfa;
+                                       pc300status.te_status.prbs = chan->falc.prbs;
+                               } else {
+                                       pc300status.gen_status.dcd =
+                                               !(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_DCD);
+                                       pc300status.gen_status.cts =
+                                               !(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_CTS);
+                                       pc300status.gen_status.rts =
+                                               !(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_RTS);
+                                       pc300status.gen_status.dtr =
+                                               !(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_DTR);
+                                       /* There is no DSR in HD64572 */
+                               }
+                               if (!arg ||
+                                   copy_to_user(arg, &pc300status, sizeof(pc300status_t)))
+                                       return -EINVAL;
+                               return 0;
+                       }
+
+               case SIOCSPC300TRACE:
+                       /* Sets/resets a trace_flag for the respective device */
+                       if (!arg || copy_from_user(&d->trace_on, arg,sizeof(unsigned char)))
+                                       return -EINVAL;
+                       return 0;
+
+               case SIOCSPC300LOOPBACK:
+                       {
+                               struct pc300loopback pc300loop;
+
+                               /* TE boards only */
+                               if (card->hw.type != PC300_TE)
+                                       return -EINVAL;
+
+                               if (!arg || 
+                                       copy_from_user(&pc300loop, arg, sizeof(pc300loopback_t)))
+                                               return -EINVAL;
+                               switch (pc300loop.loop_type) {
+                                       case PC300LOCLOOP:      /* Turn the local loop on/off */
+                                               falc_local_loop(card, ch, pc300loop.loop_on);
+                                               return 0;
+
+                                       case PC300REMLOOP:      /* Turn the remote loop on/off */
+                                               falc_remote_loop(card, ch, pc300loop.loop_on);
+                                               return 0;
+
+                                       case PC300PAYLOADLOOP:  /* Turn the payload loop on/off */
+                                               falc_payload_loop(card, ch, pc300loop.loop_on);
+                                               return 0;
+
+                                       case PC300GENLOOPUP:    /* Generate loop UP */
+                                               if (pc300loop.loop_on) {
+                                                       falc_generate_loop_up_code (card, ch);
+                                               } else {
+                                                       turn_off_xlu(card, ch);
+                                               }
+                                               return 0;
+
+                                       case PC300GENLOOPDOWN:  /* Generate loop DOWN */
+                                               if (pc300loop.loop_on) {
+                                                       falc_generate_loop_down_code (card, ch);
+                                               } else {
+                                                       turn_off_xld(card, ch);
+                                               }
+                                               return 0;
+
+                                       default:
+                                               return -EINVAL;
+                               }
+                       }
+
+               case SIOCSPC300PATTERNTEST:
+                       /* Turn the pattern test on/off and show the errors counter */
+                       {
+                               struct pc300patterntst pc300patrntst;
+
+                               /* TE boards only */
+                               if (card->hw.type != PC300_TE)
+                                       return -EINVAL;
+
+                               if (card->hw.cpld_id < 0x02) {
+                                       /* CPLD_ID < 0x02 doesn't support pattern test */
+                                       return -EINVAL;
+                               }
+
+                               if (!arg || 
+                                       copy_from_user(&pc300patrntst,arg,sizeof(pc300patterntst_t)))
+                                               return -EINVAL;
+                               if (pc300patrntst.patrntst_on == 2) {
+                                       if (chan->falc.prbs == 0) {
+                                               falc_pattern_test(card, ch, 1);
+                                       }
+                                       pc300patrntst.num_errors =
+                                               falc_pattern_test_error(card, ch);
+                                       if (copy_to_user(arg, &pc300patrntst,
+                                                        sizeof(pc300patterntst_t)))
+                                                       return -EINVAL;
+                               } else {
+                                       falc_pattern_test(card, ch, pc300patrntst.patrntst_on);
+                               }
+                               return 0;
+                       }
+
+               case SIOCWANDEV:
+                       switch (ifr->ifr_settings.type) {
+                               case IF_GET_IFACE:
+                               {
+                                       const size_t size = sizeof(sync_serial_settings);
+                                       ifr->ifr_settings.type = conf->media;
+                                       if (ifr->ifr_settings.size < size) {
+                                               /* data size wanted */
+                                               ifr->ifr_settings.size = size;
+                                               return -ENOBUFS;
+                                       }
+       
+                                       if (copy_to_user(settings->ifs_ifsu.sync,
+                                                        &conf->phys_settings, size)) {
+                                               return -EFAULT;
+                                       }
+                                       return 0;
+                               }
+
+                               case IF_IFACE_V35:
+                               case IF_IFACE_V24:
+                               case IF_IFACE_X21:
+                               {
+                                       const size_t size = sizeof(sync_serial_settings);
+
+                                       if (!capable(CAP_NET_ADMIN)) {
+                                               return -EPERM;
+                                       }
+                                       /* incorrect data len? */
+                                       if (ifr->ifr_settings.size != size) {
+                                               return -ENOBUFS;
+                                       }
+
+                                       if (copy_from_user(&conf->phys_settings, 
+                                                          settings->ifs_ifsu.sync, size)) {
+                                               return -EFAULT;
+                                       }
+
+                                       if (conf->phys_settings.loopback) {
+                                               cpc_writeb(card->hw.scabase + M_REG(MD2, ch),
+                                                       cpc_readb(card->hw.scabase + M_REG(MD2, ch)) | 
+                                                       MD2_LOOP_MIR);
+                                       }
+                                       conf->media = ifr->ifr_settings.type;
+                                       return 0;
+                               }
+
+                               case IF_IFACE_T1:
+                               case IF_IFACE_E1:
+                               {
+                                       const size_t te_size = sizeof(te1_settings);
+                                       const size_t size = sizeof(sync_serial_settings);
+
+                                       if (!capable(CAP_NET_ADMIN)) {
+                                               return -EPERM;
+                                       }
+
+                                       /* incorrect data len? */
+                                       if (ifr->ifr_settings.size != te_size) {
+                                               return -ENOBUFS;
+                                       }
+
+                                       if (copy_from_user(&conf->phys_settings, 
+                                                          settings->ifs_ifsu.te1, size)) {
+                                               return -EFAULT;
+                                       }/* Ignoring HDLC slot_map for a while */
+                                       
+                                       if (conf->phys_settings.loopback) {
+                                               cpc_writeb(card->hw.scabase + M_REG(MD2, ch),
+                                                       cpc_readb(card->hw.scabase + M_REG(MD2, ch)) | 
+                                                       MD2_LOOP_MIR);
+                                       }
+                                       conf->media = ifr->ifr_settings.type;
+                                       return 0;
+                               }
+                               default:
+                                       return hdlc_ioctl(dev, ifr, cmd);
+                       }
+
+               default:
+                       return hdlc_ioctl(dev, ifr, cmd);
+       }
+}
+
+static int clock_rate_calc(u32 rate, u32 clock, int *br_io)
+{
+       int br, tc;
+       int br_pwr, error;
+
+       *br_io = 0;
+
+       if (rate == 0)
+               return 0;
+
+       for (br = 0, br_pwr = 1; br <= 9; br++, br_pwr <<= 1) {
+               if ((tc = clock / br_pwr / rate) <= 0xff) {
+                       *br_io = br;
+                       break;
+               }
+       }
+
+       if (tc <= 0xff) {
+               error = ((rate - (clock / br_pwr / rate)) / rate) * 1000;
+               /* Errors bigger than +/- 1% won't be tolerated */
+               if (error < -10 || error > 10)
+                       return -1;
+               else
+                       return tc;
+       } else {
+               return -1;
+       }
+}
+
+static int ch_config(pc300dev_t * d)
+{
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300chconf_t *conf = (pc300chconf_t *) & chan->conf;
+       pc300_t *card = (pc300_t *) chan->card;
+       void __iomem *scabase = card->hw.scabase;
+       void __iomem *plxbase = card->hw.plxbase;
+       int ch = chan->channel;
+       u32 clkrate = chan->conf.phys_settings.clock_rate;
+       u32 clktype = chan->conf.phys_settings.clock_type;
+       u16 encoding = chan->conf.proto_settings.encoding;
+       u16 parity = chan->conf.proto_settings.parity;
+       u8 md0, md2;
+
+       /* Reset the channel */
+       cpc_writeb(scabase + M_REG(CMD, ch), CMD_CH_RST);
+
+       /* Configure the SCA registers */
+       switch (parity) {
+               case PARITY_NONE:
+                       md0 = MD0_BIT_SYNC;
+                       break;
+               case PARITY_CRC16_PR0:
+                       md0 = MD0_CRC16_0|MD0_CRCC0|MD0_BIT_SYNC;
+                       break;
+               case PARITY_CRC16_PR1:
+                       md0 = MD0_CRC16_1|MD0_CRCC0|MD0_BIT_SYNC;
+                       break;
+               case PARITY_CRC32_PR1_CCITT:
+                       md0 = MD0_CRC32|MD0_CRCC0|MD0_BIT_SYNC;
+                       break;
+               case PARITY_CRC16_PR1_CCITT:
+               default:
+                       md0 = MD0_CRC_CCITT|MD0_CRCC0|MD0_BIT_SYNC;
+                       break;
+       }
+       switch (encoding) {
+               case ENCODING_NRZI:
+                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_NRZI;
+                       break;
+               case ENCODING_FM_MARK:  /* FM1 */
+                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_FM1;
+                       break;
+               case ENCODING_FM_SPACE: /* FM0 */
+                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_FM0;
+                       break;
+               case ENCODING_MANCHESTER: /* It's not working... */
+                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_FM|MD2_MANCH;
+                       break;
+               case ENCODING_NRZ:
+               default:
+                       md2 = MD2_F_DUPLEX|MD2_ADPLL_X8|MD2_NRZ;
+                       break;
+       }
+       cpc_writeb(scabase + M_REG(MD0, ch), md0);
+       cpc_writeb(scabase + M_REG(MD1, ch), 0);
+       cpc_writeb(scabase + M_REG(MD2, ch), md2);
+       cpc_writeb(scabase + M_REG(IDL, ch), 0x7e);
+       cpc_writeb(scabase + M_REG(CTL, ch), CTL_URSKP | CTL_IDLC);
+
+       /* Configure HW media */
+       switch (card->hw.type) {
+               case PC300_RSV:
+                       if (conf->media == IF_IFACE_V35) {
+                               cpc_writel((plxbase + card->hw.gpioc_reg),
+                                          cpc_readl(plxbase + card->hw.gpioc_reg) | PC300_CHMEDIA_MASK(ch));
+                       } else {
+                               cpc_writel((plxbase + card->hw.gpioc_reg),
+                                          cpc_readl(plxbase + card->hw.gpioc_reg) & ~PC300_CHMEDIA_MASK(ch));
+                       }
+                       break;
+
+               case PC300_X21:
+                       break;
+
+               case PC300_TE:
+                       te_config(card, ch);
+                       break;
+       }
+
+       switch (card->hw.type) {
+               case PC300_RSV:
+               case PC300_X21:
+                       if (clktype == CLOCK_INT || clktype == CLOCK_TXINT) {
+                               int tmc, br;
+
+                               /* Calculate the clkrate parameters */
+                               tmc = clock_rate_calc(clkrate, card->hw.clock, &br);
+                               if (tmc < 0)
+                                       return -EIO;
+                               cpc_writeb(scabase + M_REG(TMCT, ch), tmc);
+                               cpc_writeb(scabase + M_REG(TXS, ch),
+                                          (TXS_DTRXC | TXS_IBRG | br));
+                               if (clktype == CLOCK_INT) {
+                                       cpc_writeb(scabase + M_REG(TMCR, ch), tmc);
+                                       cpc_writeb(scabase + M_REG(RXS, ch), 
+                                                  (RXS_IBRG | br));
+                               } else {
+                                       cpc_writeb(scabase + M_REG(TMCR, ch), 1);
+                                       cpc_writeb(scabase + M_REG(RXS, ch), 0);
+                               }
+                               if (card->hw.type == PC300_X21) {
+                                       cpc_writeb(scabase + M_REG(GPO, ch), 1);
+                                       cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1 | EXS_RES1);
+                               } else {
+                                       cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1);
+                               }
+                       } else {
+                               cpc_writeb(scabase + M_REG(TMCT, ch), 1);
+                               if (clktype == CLOCK_EXT) {
+                                       cpc_writeb(scabase + M_REG(TXS, ch), 
+                                                  TXS_DTRXC);
+                               } else {
+                                       cpc_writeb(scabase + M_REG(TXS, ch), 
+                                                  TXS_DTRXC|TXS_RCLK);
+                               }
+                               cpc_writeb(scabase + M_REG(TMCR, ch), 1);
+                               cpc_writeb(scabase + M_REG(RXS, ch), 0);
+                               if (card->hw.type == PC300_X21) {
+                                       cpc_writeb(scabase + M_REG(GPO, ch), 0);
+                                       cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1 | EXS_RES1);
+                               } else {
+                                       cpc_writeb(scabase + M_REG(EXS, ch), EXS_TES1);
+                               }
+                       }
+                       break;
+
+               case PC300_TE:
+                       /* SCA always receives clock from the FALC chip */
+                       cpc_writeb(scabase + M_REG(TMCT, ch), 1);
+                       cpc_writeb(scabase + M_REG(TXS, ch), 0);
+                       cpc_writeb(scabase + M_REG(TMCR, ch), 1);
+                       cpc_writeb(scabase + M_REG(RXS, ch), 0);
+                       cpc_writeb(scabase + M_REG(EXS, ch), 0);
+                       break;
+       }
+
+       /* Enable Interrupts */
+       cpc_writel(scabase + IER0,
+                  cpc_readl(scabase + IER0) |
+                  IR0_M(IR0_RXINTA, ch) |
+                  IR0_DRX(IR0_EFT | IR0_DMIA | IR0_DMIB, ch) |
+                  IR0_DTX(IR0_EFT | IR0_DMIA | IR0_DMIB, ch));
+       cpc_writeb(scabase + M_REG(IE0, ch),
+                  cpc_readl(scabase + M_REG(IE0, ch)) | IE0_RXINTA);
+       cpc_writeb(scabase + M_REG(IE1, ch),
+                  cpc_readl(scabase + M_REG(IE1, ch)) | IE1_CDCD);
+
+       return 0;
+}
+
+static int rx_config(pc300dev_t * d)
+{
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       void __iomem *scabase = card->hw.scabase;
+       int ch = chan->channel;
+
+       cpc_writeb(scabase + DSR_RX(ch), 0);
+
+       /* General RX settings */
+       cpc_writeb(scabase + M_REG(RRC, ch), 0);
+       cpc_writeb(scabase + M_REG(RNR, ch), 16);
+
+       /* Enable reception */
+       cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_CRC_INIT);
+       cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_ENA);
+
+       /* Initialize DMA stuff */
+       chan->rx_first_bd = 0;
+       chan->rx_last_bd = N_DMA_RX_BUF - 1;
+       rx_dma_buf_init(card, ch);
+       cpc_writeb(scabase + DCR_RX(ch), DCR_FCT_CLR);
+       cpc_writeb(scabase + DMR_RX(ch), (DMR_TMOD | DMR_NF));
+       cpc_writeb(scabase + DIR_RX(ch), (DIR_EOM | DIR_BOF));
+
+       /* Start DMA */
+       rx_dma_start(card, ch);
+
+       return 0;
+}
+
+static int tx_config(pc300dev_t * d)
+{
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       void __iomem *scabase = card->hw.scabase;
+       int ch = chan->channel;
+
+       cpc_writeb(scabase + DSR_TX(ch), 0);
+
+       /* General TX settings */
+       cpc_writeb(scabase + M_REG(TRC0, ch), 0);
+       cpc_writeb(scabase + M_REG(TFS, ch), 32);
+       cpc_writeb(scabase + M_REG(TNR0, ch), 20);
+       cpc_writeb(scabase + M_REG(TNR1, ch), 48);
+       cpc_writeb(scabase + M_REG(TCR, ch), 8);
+
+       /* Enable transmission */
+       cpc_writeb(scabase + M_REG(CMD, ch), CMD_TX_CRC_INIT);
+
+       /* Initialize DMA stuff */
+       chan->tx_first_bd = 0;
+       chan->tx_next_bd = 0;
+       tx_dma_buf_init(card, ch);
+       cpc_writeb(scabase + DCR_TX(ch), DCR_FCT_CLR);
+       cpc_writeb(scabase + DMR_TX(ch), (DMR_TMOD | DMR_NF));
+       cpc_writeb(scabase + DIR_TX(ch), (DIR_EOM | DIR_BOF | DIR_UDRF));
+       cpc_writel(scabase + DTX_REG(CDAL, ch), TX_BD_ADDR(ch, chan->tx_first_bd));
+       cpc_writel(scabase + DTX_REG(EDAL, ch), TX_BD_ADDR(ch, chan->tx_next_bd));
+
+       return 0;
+}
+
+static int cpc_attach(struct net_device *dev, unsigned short encoding,
+                     unsigned short parity)
+{
+       pc300dev_t *d = (pc300dev_t *)dev_to_hdlc(dev)->priv;
+       pc300ch_t *chan = (pc300ch_t *)d->chan;
+       pc300_t *card = (pc300_t *)chan->card;
+       pc300chconf_t *conf = (pc300chconf_t *)&chan->conf;
+
+       if (card->hw.type == PC300_TE) {
+               if (encoding != ENCODING_NRZ && encoding != ENCODING_NRZI) {
+                       return -EINVAL;
+               }
+       } else {
+               if (encoding != ENCODING_NRZ && encoding != ENCODING_NRZI &&
+                   encoding != ENCODING_FM_MARK && encoding != ENCODING_FM_SPACE) {
+                       /* Driver doesn't support ENCODING_MANCHESTER yet */
+                       return -EINVAL;
+               }
+       }
+
+       if (parity != PARITY_NONE && parity != PARITY_CRC16_PR0 &&
+           parity != PARITY_CRC16_PR1 && parity != PARITY_CRC32_PR1_CCITT &&
+           parity != PARITY_CRC16_PR1_CCITT) {
+               return -EINVAL;
+       }
+
+       conf->proto_settings.encoding = encoding;
+       conf->proto_settings.parity = parity;
+       return 0;
+}
+
+static int cpc_opench(pc300dev_t * d)
+{
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       int ch = chan->channel, rc;
+       void __iomem *scabase = card->hw.scabase;
+
+       rc = ch_config(d);
+       if (rc)
+               return rc;
+
+       rx_config(d);
+
+       tx_config(d);
+
+       /* Assert RTS and DTR */
+       cpc_writeb(scabase + M_REG(CTL, ch),
+                  cpc_readb(scabase + M_REG(CTL, ch)) & ~(CTL_RTS | CTL_DTR));
+
+       return 0;
+}
+
+static void cpc_closech(pc300dev_t * d)
+{
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       falc_t *pfalc = (falc_t *) & chan->falc;
+       int ch = chan->channel;
+
+       cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_CH_RST);
+       rx_dma_stop(card, ch);
+       tx_dma_stop(card, ch);
+
+       if (card->hw.type == PC300_TE) {
+               memset(pfalc, 0, sizeof(falc_t));
+               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2,
+                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) &
+                          ~((CPLD_REG2_FALC_TX_CLK | CPLD_REG2_FALC_RX_CLK |
+                             CPLD_REG2_FALC_LED2) << (2 * ch)));
+               /* Reset the FALC chip */
+               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
+                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) |
+                          (CPLD_REG1_FALC_RESET << (2 * ch)));
+               udelay(10000);
+               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
+                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) &
+                          ~(CPLD_REG1_FALC_RESET << (2 * ch)));
+       }
+}
+
+int cpc_open(struct net_device *dev)
+{
+       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
+       struct ifreq ifr;
+       int result;
+
+#ifdef PC300_DEBUG_OTHER
+       printk("pc300: cpc_open");
+#endif
+
+       result = hdlc_open(dev);
+
+       if (result)
+               return result;
+
+       sprintf(ifr.ifr_name, "%s", dev->name);
+       result = cpc_opench(d);
+       if (result)
+               goto err_out;
+
+       netif_start_queue(dev);
+       return 0;
+
+err_out:
+       hdlc_close(dev);
+       return result;
+}
+
+static int cpc_close(struct net_device *dev)
+{
+       pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv;
+       pc300ch_t *chan = (pc300ch_t *) d->chan;
+       pc300_t *card = (pc300_t *) chan->card;
+       unsigned long flags;
+
+#ifdef PC300_DEBUG_OTHER
+       printk("pc300: cpc_close");
+#endif
+
+       netif_stop_queue(dev);
+
+       CPC_LOCK(card, flags);
+       cpc_closech(d);
+       CPC_UNLOCK(card, flags);
+
+       hdlc_close(dev);
+
+#ifdef CONFIG_PC300_MLPPP
+       if (chan->conf.proto == PC300_PROTO_MLPPP) {
+               cpc_tty_unregister_service(d);
+               chan->conf.proto = 0xffff;
+       }
+#endif
+
+       return 0;
+}
+
+static u32 detect_ram(pc300_t * card)
+{
+       u32 i;
+       u8 data;
+       void __iomem *rambase = card->hw.rambase;
+
+       card->hw.ramsize = PC300_RAMSIZE;
+       /* Let's find out how much RAM is present on this board */
+       for (i = 0; i < card->hw.ramsize; i++) {
+               data = (u8)(i & 0xff);
+               cpc_writeb(rambase + i, data);
+               if (cpc_readb(rambase + i) != data) {
+                       break;
+               }
+       }
+       return i;
+}
+
+static void plx_init(pc300_t * card)
+{
+       struct RUNTIME_9050 __iomem *plx_ctl = card->hw.plxbase;
+
+       /* Reset PLX */
+       cpc_writel(&plx_ctl->init_ctrl,
+                  cpc_readl(&plx_ctl->init_ctrl) | 0x40000000);
+       udelay(10000L);
+       cpc_writel(&plx_ctl->init_ctrl,
+                  cpc_readl(&plx_ctl->init_ctrl) & ~0x40000000);
+
+       /* Reload Config. Registers from EEPROM */
+       cpc_writel(&plx_ctl->init_ctrl,
+                  cpc_readl(&plx_ctl->init_ctrl) | 0x20000000);
+       udelay(10000L);
+       cpc_writel(&plx_ctl->init_ctrl,
+                  cpc_readl(&plx_ctl->init_ctrl) & ~0x20000000);
+
+}
+
+static void show_version(void)
+{
+       char *rcsvers, *rcsdate, *tmp;
+
+       rcsvers = strchr(rcsid, ' ');
+       rcsvers++;
+       tmp = strchr(rcsvers, ' ');
+       *tmp++ = '\0';
+       rcsdate = strchr(tmp, ' ');
+       rcsdate++;
+       tmp = strrchr(rcsdate, ' ');
+       *tmp = '\0';
+       pr_info("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate);
+}                              /* show_version */
+
+static const struct net_device_ops cpc_netdev_ops = {
+       .ndo_open               = cpc_open,
+       .ndo_stop               = cpc_close,
+       .ndo_tx_timeout         = cpc_tx_timeout,
+       .ndo_set_mac_address    = NULL,
+       .ndo_change_mtu         = cpc_change_mtu,
+       .ndo_do_ioctl           = cpc_ioctl,
+       .ndo_validate_addr      = eth_validate_addr,
+};
+
+static void cpc_init_card(pc300_t * card)
+{
+       int i, devcount = 0;
+       static int board_nbr = 1;
+
+       /* Enable interrupts on the PCI bridge */
+       plx_init(card);
+       cpc_writew(card->hw.plxbase + card->hw.intctl_reg,
+                  cpc_readw(card->hw.plxbase + card->hw.intctl_reg) | 0x0040);
+
+#ifdef USE_PCI_CLOCK
+       /* Set board clock to PCI clock */
+       cpc_writel(card->hw.plxbase + card->hw.gpioc_reg,
+                  cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) | 0x00000004UL);
+       card->hw.clock = PC300_PCI_CLOCK;
+#else
+       /* Set board clock to internal oscillator clock */
+       cpc_writel(card->hw.plxbase + card->hw.gpioc_reg,
+                  cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) & ~0x00000004UL);
+       card->hw.clock = PC300_OSC_CLOCK;
+#endif
+
+       /* Detect actual on-board RAM size */
+       card->hw.ramsize = detect_ram(card);
+
+       /* Set Global SCA-II registers */
+       cpc_writeb(card->hw.scabase + PCR, PCR_PR2);
+       cpc_writeb(card->hw.scabase + BTCR, 0x10);
+       cpc_writeb(card->hw.scabase + WCRL, 0);
+       cpc_writeb(card->hw.scabase + DMER, 0x80);
+
+       if (card->hw.type == PC300_TE) {
+               u8 reg1;
+
+               /* Check CPLD version */
+               reg1 = cpc_readb(card->hw.falcbase + CPLD_REG1);
+               cpc_writeb(card->hw.falcbase + CPLD_REG1, (reg1 + 0x5a));
+               if (cpc_readb(card->hw.falcbase + CPLD_REG1) == reg1) {
+                       /* New CPLD */
+                       card->hw.cpld_id = cpc_readb(card->hw.falcbase + CPLD_ID_REG);
+                       card->hw.cpld_reg1 = CPLD_V2_REG1;
+                       card->hw.cpld_reg2 = CPLD_V2_REG2;
+               } else {
+                       /* old CPLD */
+                       card->hw.cpld_id = 0;
+                       card->hw.cpld_reg1 = CPLD_REG1;
+                       card->hw.cpld_reg2 = CPLD_REG2;
+                       cpc_writeb(card->hw.falcbase + CPLD_REG1, reg1);
+               }
+
+               /* Enable the board's global clock */
+               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg1,
+                          cpc_readb(card->hw.falcbase + card->hw.cpld_reg1) |
+                          CPLD_REG1_GLOBAL_CLK);
+
+       }
+
+       for (i = 0; i < card->hw.nchan; i++) {
+               pc300ch_t *chan = &card->chan[i];
+               pc300dev_t *d = &chan->d;
+               hdlc_device *hdlc;
+               struct net_device *dev;
+
+               chan->card = card;
+               chan->channel = i;
+               chan->conf.phys_settings.clock_rate = 0;
+               chan->conf.phys_settings.clock_type = CLOCK_EXT;
+               chan->conf.proto_settings.encoding = ENCODING_NRZ;
+               chan->conf.proto_settings.parity = PARITY_CRC16_PR1_CCITT;
+               switch (card->hw.type) {
+                       case PC300_TE:
+                               chan->conf.media = IF_IFACE_T1;
+                               chan->conf.lcode = PC300_LC_B8ZS;
+                               chan->conf.fr_mode = PC300_FR_ESF;
+                               chan->conf.lbo = PC300_LBO_0_DB;
+                               chan->conf.rx_sens = PC300_RX_SENS_SH;
+                               chan->conf.tslot_bitmap = 0xffffffffUL;
+                               break;
+
+                       case PC300_X21:
+                               chan->conf.media = IF_IFACE_X21;
+                               break;
+
+                       case PC300_RSV:
+                       default:
+                               chan->conf.media = IF_IFACE_V35;
+                               break;
+               }
+               chan->conf.proto = IF_PROTO_PPP;
+               chan->tx_first_bd = 0;
+               chan->tx_next_bd = 0;
+               chan->rx_first_bd = 0;
+               chan->rx_last_bd = N_DMA_RX_BUF - 1;
+               chan->nfree_tx_bd = N_DMA_TX_BUF;
+
+               d->chan = chan;
+               d->trace_on = 0;
+               d->line_on = 0;
+               d->line_off = 0;
+
+               dev = alloc_hdlcdev(d);
+               if (dev == NULL)
+                       continue;
+
+               hdlc = dev_to_hdlc(dev);
+               hdlc->xmit = cpc_queue_xmit;
+               hdlc->attach = cpc_attach;
+               d->dev = dev;
+               dev->mem_start = card->hw.ramphys;
+               dev->mem_end = card->hw.ramphys + card->hw.ramsize - 1;
+               dev->irq = card->hw.irq;
+               dev->tx_queue_len = PC300_TX_QUEUE_LEN;
+               dev->mtu = PC300_DEF_MTU;
+
+               dev->netdev_ops = &cpc_netdev_ops;
+               dev->watchdog_timeo = PC300_TX_TIMEOUT;
+
+               if (register_hdlc_device(dev) == 0) {
+                       printk("%s: Cyclades-PC300/", dev->name);
+                       switch (card->hw.type) {
+                               case PC300_TE:
+                                       if (card->hw.bus == PC300_PMC) {
+                                               printk("TE-M");
+                                       } else {
+                                               printk("TE  ");
+                                       }
+                                       break;
+
+                               case PC300_X21:
+                                       printk("X21 ");
+                                       break;
+
+                               case PC300_RSV:
+                               default:
+                                       printk("RSV ");
+                                       break;
+                       }
+                       printk (" #%d, %dKB of RAM at 0x%08x, IRQ%d, channel %d.\n",
+                                board_nbr, card->hw.ramsize / 1024,
+                                card->hw.ramphys, card->hw.irq, i + 1);
+                       devcount++;
+               } else {
+                       printk ("Dev%d on card(0x%08x): unable to allocate i/f name.\n",
+                                i + 1, card->hw.ramphys);
+                       free_netdev(dev);
+                       continue;
+               }
+       }
+       spin_lock_init(&card->card_lock);
+
+       board_nbr++;
+}
+
+static int __devinit
+cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+       int err, eeprom_outdated = 0;
+       u16 device_id;
+       pc300_t *card;
+
+       if ((err = pci_enable_device(pdev)) < 0)
+               return err;
+
+       card = kzalloc(sizeof(pc300_t), GFP_KERNEL);
+       if (card == NULL) {
+               printk("PC300 found at RAM 0x%016llx, "
+                      "but could not allocate card structure.\n",
+                      (unsigned long long)pci_resource_start(pdev, 3));
+               err = -ENOMEM;
+               goto err_disable_dev;
+       }
+
+       err = -ENODEV;
+
+       /* read PCI configuration area */
+       device_id = ent->device;
+       card->hw.irq = pdev->irq;
+       card->hw.iophys = pci_resource_start(pdev, 1);
+       card->hw.iosize = pci_resource_len(pdev, 1);
+       card->hw.scaphys = pci_resource_start(pdev, 2);
+       card->hw.scasize = pci_resource_len(pdev, 2);
+       card->hw.ramphys = pci_resource_start(pdev, 3);
+       card->hw.alloc_ramsize = pci_resource_len(pdev, 3);
+       card->hw.falcphys = pci_resource_start(pdev, 4);
+       card->hw.falcsize = pci_resource_len(pdev, 4);
+       card->hw.plxphys = pci_resource_start(pdev, 5);
+       card->hw.plxsize = pci_resource_len(pdev, 5);
+
+       switch (device_id) {
+               case PCI_DEVICE_ID_PC300_RX_1:
+               case PCI_DEVICE_ID_PC300_TE_1:
+               case PCI_DEVICE_ID_PC300_TE_M_1:
+                       card->hw.nchan = 1;
+                       break;
+
+               case PCI_DEVICE_ID_PC300_RX_2:
+               case PCI_DEVICE_ID_PC300_TE_2:
+               case PCI_DEVICE_ID_PC300_TE_M_2:
+               default:
+                       card->hw.nchan = PC300_MAXCHAN;
+                       break;
+       }
+#ifdef PC300_DEBUG_PCI
+       printk("cpc (bus=0x0%x,pci_id=0x%x,", pdev->bus->number, pdev->devfn);
+       printk("rev_id=%d) IRQ%d\n", pdev->revision, card->hw.irq);
+       printk("cpc:found  ramaddr=0x%08lx plxaddr=0x%08lx "
+              "ctladdr=0x%08lx falcaddr=0x%08lx\n",
+              card->hw.ramphys, card->hw.plxphys, card->hw.scaphys,
+              card->hw.falcphys);
+#endif
+       /* Although we don't use this I/O region, we should
+        * request it from the kernel anyway, to avoid problems
+        * with other drivers accessing it. */
+       if (!request_region(card->hw.iophys, card->hw.iosize, "PLX Registers")) {
+               /* In case we can't allocate it, warn user */
+               printk("WARNING: couldn't allocate I/O region for PC300 board "
+                      "at 0x%08x!\n", card->hw.ramphys);
+       }
+
+       if (card->hw.plxphys) {
+               pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, card->hw.plxphys);
+       } else {
+               eeprom_outdated = 1;
+               card->hw.plxphys = pci_resource_start(pdev, 0);
+               card->hw.plxsize = pci_resource_len(pdev, 0);
+       }
+
+       if (!request_mem_region(card->hw.plxphys, card->hw.plxsize,
+                               "PLX Registers")) {
+               printk("PC300 found at RAM 0x%08x, "
+                      "but could not allocate PLX mem region.\n",
+                      card->hw.ramphys);
+               goto err_release_io;
+       }
+       if (!request_mem_region(card->hw.ramphys, card->hw.alloc_ramsize,
+                               "On-board RAM")) {
+               printk("PC300 found at RAM 0x%08x, "
+                      "but could not allocate RAM mem region.\n",
+                      card->hw.ramphys);
+               goto err_release_plx;
+       }
+       if (!request_mem_region(card->hw.scaphys, card->hw.scasize,
+                               "SCA-II Registers")) {
+               printk("PC300 found at RAM 0x%08x, "
+                      "but could not allocate SCA mem region.\n",
+                      card->hw.ramphys);
+               goto err_release_ram;
+       }
+
+       card->hw.plxbase = ioremap(card->hw.plxphys, card->hw.plxsize);
+       card->hw.rambase = ioremap(card->hw.ramphys, card->hw.alloc_ramsize);
+       card->hw.scabase = ioremap(card->hw.scaphys, card->hw.scasize);
+       switch (device_id) {
+               case PCI_DEVICE_ID_PC300_TE_1:
+               case PCI_DEVICE_ID_PC300_TE_2:
+               case PCI_DEVICE_ID_PC300_TE_M_1:
+               case PCI_DEVICE_ID_PC300_TE_M_2:
+                       request_mem_region(card->hw.falcphys, card->hw.falcsize,
+                                          "FALC Registers");
+                       card->hw.falcbase = ioremap(card->hw.falcphys, card->hw.falcsize);
+                       break;
+
+               case PCI_DEVICE_ID_PC300_RX_1:
+               case PCI_DEVICE_ID_PC300_RX_2:
+               default:
+                       card->hw.falcbase = NULL;
+                       break;
+       }
+
+#ifdef PC300_DEBUG_PCI
+       printk("cpc: relocate ramaddr=0x%08lx plxaddr=0x%08lx "
+              "ctladdr=0x%08lx falcaddr=0x%08lx\n",
+              card->hw.rambase, card->hw.plxbase, card->hw.scabase,
+              card->hw.falcbase);
+#endif
+
+       /* Set PCI drv pointer to the card structure */
+       pci_set_drvdata(pdev, card);
+
+       /* Set board type */
+       switch (device_id) {
+               case PCI_DEVICE_ID_PC300_TE_1:
+               case PCI_DEVICE_ID_PC300_TE_2:
+               case PCI_DEVICE_ID_PC300_TE_M_1:
+               case PCI_DEVICE_ID_PC300_TE_M_2:
+                       card->hw.type = PC300_TE;
+
+                       if ((device_id == PCI_DEVICE_ID_PC300_TE_M_1) ||
+                           (device_id == PCI_DEVICE_ID_PC300_TE_M_2)) {
+                               card->hw.bus = PC300_PMC;
+                               /* Set PLX register offsets */
+                               card->hw.gpioc_reg = 0x54;
+                               card->hw.intctl_reg = 0x4c;
+                       } else {
+                               card->hw.bus = PC300_PCI;
+                               /* Set PLX register offsets */
+                               card->hw.gpioc_reg = 0x50;
+                               card->hw.intctl_reg = 0x4c;
+                       }
+                       break;
+
+               case PCI_DEVICE_ID_PC300_RX_1:
+               case PCI_DEVICE_ID_PC300_RX_2:
+               default:
+                       card->hw.bus = PC300_PCI;
+                       /* Set PLX register offsets */
+                       card->hw.gpioc_reg = 0x50;
+                       card->hw.intctl_reg = 0x4c;
+
+                       if ((cpc_readl(card->hw.plxbase + card->hw.gpioc_reg) & PC300_CTYPE_MASK)) {
+                               card->hw.type = PC300_X21;
+                       } else {
+                               card->hw.type = PC300_RSV;
+                       }
+                       break;
+       }
+
+       /* Allocate IRQ */
+       if (request_irq(card->hw.irq, cpc_intr, IRQF_SHARED, "Cyclades-PC300", card)) {
+               printk ("PC300 found at RAM 0x%08x, but could not allocate IRQ%d.\n",
+                        card->hw.ramphys, card->hw.irq);
+               goto err_io_unmap;
+       }
+
+       cpc_init_card(card);
+
+       if (eeprom_outdated)
+               printk("WARNING: PC300 with outdated EEPROM.\n");
+       return 0;
+
+err_io_unmap:
+       iounmap(card->hw.plxbase);
+       iounmap(card->hw.scabase);
+       iounmap(card->hw.rambase);
+       if (card->hw.type == PC300_TE) {
+               iounmap(card->hw.falcbase);
+               release_mem_region(card->hw.falcphys, card->hw.falcsize);
+       }
+       release_mem_region(card->hw.scaphys, card->hw.scasize);
+err_release_ram:
+       release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize);
+err_release_plx:
+       release_mem_region(card->hw.plxphys, card->hw.plxsize);
+err_release_io:
+       release_region(card->hw.iophys, card->hw.iosize);
+       kfree(card);
+err_disable_dev:
+       pci_disable_device(pdev);
+       return err;
+}
+
+static void __devexit cpc_remove_one(struct pci_dev *pdev)
+{
+       pc300_t *card = pci_get_drvdata(pdev);
+
+       if (card->hw.rambase) {
+               int i;
+
+               /* Disable interrupts on the PCI bridge */
+               cpc_writew(card->hw.plxbase + card->hw.intctl_reg,
+                          cpc_readw(card->hw.plxbase + card->hw.intctl_reg) & ~(0x0040));
+
+               for (i = 0; i < card->hw.nchan; i++) {
+                       unregister_hdlc_device(card->chan[i].d.dev);
+               }
+               iounmap(card->hw.plxbase);
+               iounmap(card->hw.scabase);
+               iounmap(card->hw.rambase);
+               release_mem_region(card->hw.plxphys, card->hw.plxsize);
+               release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize);
+               release_mem_region(card->hw.scaphys, card->hw.scasize);
+               release_region(card->hw.iophys, card->hw.iosize);
+               if (card->hw.type == PC300_TE) {
+                       iounmap(card->hw.falcbase);
+                       release_mem_region(card->hw.falcphys, card->hw.falcsize);
+               }
+               for (i = 0; i < card->hw.nchan; i++)
+                       if (card->chan[i].d.dev)
+                               free_netdev(card->chan[i].d.dev);
+               if (card->hw.irq)
+                       free_irq(card->hw.irq, card);
+               kfree(card);
+               pci_disable_device(pdev);
+       }
+}
+
+static struct pci_driver cpc_driver = {
+       .name           = "pc300",
+       .id_table       = cpc_pci_dev_id,
+       .probe          = cpc_init_one,
+       .remove         = __devexit_p(cpc_remove_one),
+};
+
+static int __init cpc_init(void)
+{
+       show_version();
+       return pci_register_driver(&cpc_driver);
+}
+
+static void __exit cpc_cleanup_module(void)
+{
+       pci_unregister_driver(&cpc_driver);
+}
+
+module_init(cpc_init);
+module_exit(cpc_cleanup_module);
+
+MODULE_DESCRIPTION("Cyclades-PC300 cards driver");
+MODULE_AUTHOR(  "Author: Ivan Passos <ivan@cyclades.com>\r\n"
+                "Maintainer: PC300 Maintainer <pc300@cyclades.com");
+MODULE_LICENSE("GPL");
+
 
--- /dev/null
+/*
+ * pc300_tty.c Cyclades-PC300(tm) TTY Driver.
+ *
+ * Author:     Regina Kodato <reginak@cyclades.com>
+ *
+ * Copyright:  (c) 1999-2002 Cyclades Corp.
+ *
+ *     This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU General Public License
+ *  as published by the Free Software Foundation; either version
+ *  2 of the License, or (at your option) any later version.
+ *   
+ *  $Log: pc300_tty.c,v $
+ *  Revision 3.7  2002/03/07 14:17:09  henrique
+ *  License data fixed
+ *
+ *  Revision 3.6  2001/12/10 12:29:42  regina
+ *  Fix the MLPPP bug
+ *
+ *  Revision 3.5  2001/10/31 11:20:05  regina
+ *  automatic pppd starts
+ *
+ *  Revision 3.4  2001/08/06 12:01:51  regina
+ *  problem in DSR_DE bit
+ *
+ *  Revision 3.3  2001/07/26 22:58:41  regina
+ *  update EDA value
+ *
+ *  Revision 3.2  2001/07/12 13:11:20  regina
+ *  bug fix - DCD-OFF in pc300 tty driver
+ *
+ *     DMA transmission bug fix
+ *  
+ *  Revision 3.1  2001/06/22 13:13:02  regina
+ *  MLPPP implementation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/netdevice.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/if.h>
+#include <linux/skbuff.h>
+/* TTY includes */
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial.h>
+
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#include "pc300.h"
+
+/* defines and macros */
+/* TTY Global definitions */
+#define        CPC_TTY_NPORTS  8       /* maximum number of the sync tty connections */
+#define        CPC_TTY_MAJOR   CYCLADES_MAJOR  
+#define CPC_TTY_MINOR_START    240     /* minor of the first PC300 interface */
+
+#define CPC_TTY_MAX_MTU        2000    
+
+/* tty interface state */
+#define        CPC_TTY_ST_IDLE 0
+#define CPC_TTY_ST_INIT        1       /* configured with MLPPP and up */
+#define CPC_TTY_ST_OPEN        2       /* opened by application */
+
+#define        CPC_TTY_LOCK(card,flags)\
+       do {\
+               spin_lock_irqsave(&card->card_lock, flags);     \
+       } while (0)
+
+#define CPC_TTY_UNLOCK(card,flags)     \
+       do {\
+               spin_unlock_irqrestore(&card->card_lock, flags);        \
+       } while (0)
+
+//#define      CPC_TTY_DBG(format,a...)        printk(format,##a)
+#define        CPC_TTY_DBG(format,a...)
+
+/* data structures */
+typedef struct _st_cpc_rx_buf {
+       struct _st_cpc_rx_buf   *next;
+       int             size;
+       unsigned char   data[1];
+} st_cpc_rx_buf;
+
+struct st_cpc_rx_list {
+       st_cpc_rx_buf   *first;
+       st_cpc_rx_buf   *last;
+};
+
+typedef        struct _st_cpc_tty_area {
+       int             state;          /* state of the TTY interface */
+       int             num_open;       
+       unsigned int    tty_minor;      /* minor this interface */
+       volatile struct st_cpc_rx_list buf_rx;  /* ptr. to reception buffer */
+       unsigned char*  buf_tx;         /* ptr. to transmission buffer */
+       pc300dev_t*     pc300dev;       /* ptr. to info struct in PC300 driver */
+       unsigned char   name[20];       /* interf. name + "-tty" */
+       struct tty_struct *tty;         
+       struct work_struct tty_tx_work; /* tx work - tx interrupt */
+       struct work_struct tty_rx_work; /* rx work - rx interrupt */
+       } st_cpc_tty_area;
+
+/* TTY data structures */
+static struct tty_driver serial_drv;
+
+/* local variables */
+static st_cpc_tty_area cpc_tty_area[CPC_TTY_NPORTS];
+
+static int cpc_tty_cnt = 0;    /* number of intrfaces configured with MLPPP */
+static int cpc_tty_unreg_flag = 0;
+
+/* TTY functions prototype */
+static int cpc_tty_open(struct tty_struct *tty, struct file *flip);
+static void cpc_tty_close(struct tty_struct *tty, struct file *flip);
+static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count);
+static int cpc_tty_write_room(struct tty_struct *tty);
+static int cpc_tty_chars_in_buffer(struct tty_struct *tty);
+static void cpc_tty_flush_buffer(struct tty_struct *tty);
+static void cpc_tty_hangup(struct tty_struct *tty);
+static void cpc_tty_rx_work(struct work_struct *work);
+static void cpc_tty_tx_work(struct work_struct *work);
+static int cpc_tty_send_to_card(pc300dev_t *dev,void *buf, int len);
+static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx);
+static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
+static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
+
+static int pc300_tiocmset(struct tty_struct *, unsigned int, unsigned int);
+static int pc300_tiocmget(struct tty_struct *);
+
+/* functions called by PC300 driver */
+void cpc_tty_init(pc300dev_t *dev);
+void cpc_tty_unregister_service(pc300dev_t *pc300dev);
+void cpc_tty_receive(pc300dev_t *pc300dev);
+void cpc_tty_trigger_poll(pc300dev_t *pc300dev);
+
+/*
+ * PC300 TTY clear "signal"
+ */
+static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char signal)
+{
+       pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; 
+       pc300_t *card = (pc300_t *) pc300chan->card; 
+       int ch = pc300chan->channel; 
+       unsigned long flags; 
+
+       CPC_TTY_DBG("%s-tty: Clear signal %x\n",
+               pc300dev->dev->name, signal);
+       CPC_TTY_LOCK(card, flags); 
+       cpc_writeb(card->hw.scabase + M_REG(CTL,ch), 
+               cpc_readb(card->hw.scabase+M_REG(CTL,ch))& signal);
+       CPC_TTY_UNLOCK(card,flags); 
+}
+
+/*
+ * PC300 TTY set "signal" to ON
+ */
+static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal)
+{
+       pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; 
+       pc300_t *card = (pc300_t *) pc300chan->card; 
+       int ch = pc300chan->channel; 
+       unsigned long flags; 
+
+       CPC_TTY_DBG("%s-tty: Set signal %x\n",
+               pc300dev->dev->name, signal);
+       CPC_TTY_LOCK(card, flags); 
+       cpc_writeb(card->hw.scabase + M_REG(CTL,ch), 
+               cpc_readb(card->hw.scabase+M_REG(CTL,ch))& ~signal);
+       CPC_TTY_UNLOCK(card,flags); 
+}
+
+
+static const struct tty_operations pc300_ops = {
+       .open = cpc_tty_open,
+       .close = cpc_tty_close,
+       .write = cpc_tty_write,
+       .write_room = cpc_tty_write_room,
+       .chars_in_buffer = cpc_tty_chars_in_buffer,
+       .tiocmset = pc300_tiocmset,
+       .tiocmget = pc300_tiocmget,
+       .flush_buffer = cpc_tty_flush_buffer,
+       .hangup = cpc_tty_hangup,
+};
+
+
+/*
+ * PC300 TTY initialization routine
+ *
+ * This routine is called by the PC300 driver during board configuration 
+ * (ioctl=SIOCSP300CONF). At this point the adapter is completely
+ * initialized.
+ * o verify kernel version (only 2.4.x)
+ * o register TTY driver
+ * o init cpc_tty_area struct
+ */
+void cpc_tty_init(pc300dev_t *pc300dev)
+{
+       unsigned long port;
+       int aux;
+       st_cpc_tty_area * cpc_tty;
+
+       /* hdlcX - X=interface number */
+       port = pc300dev->dev->name[4] - '0';
+       if (port >= CPC_TTY_NPORTS) {
+               printk("%s-tty: invalid interface selected (0-%i): %li",
+                       pc300dev->dev->name,
+                       CPC_TTY_NPORTS-1,port);
+               return;
+       }
+
+       if (cpc_tty_cnt == 0) { /* first TTY connection -> register driver */
+               CPC_TTY_DBG("%s-tty: driver init, major:%i, minor range:%i=%i\n",
+                       pc300dev->dev->name,
+                       CPC_TTY_MAJOR, CPC_TTY_MINOR_START,
+                       CPC_TTY_MINOR_START+CPC_TTY_NPORTS);
+               /* initialize tty driver struct */
+               memset(&serial_drv,0,sizeof(struct tty_driver));
+               serial_drv.magic = TTY_DRIVER_MAGIC;
+               serial_drv.owner = THIS_MODULE;
+               serial_drv.driver_name = "pc300_tty";
+               serial_drv.name = "ttyCP";
+               serial_drv.major = CPC_TTY_MAJOR;
+               serial_drv.minor_start = CPC_TTY_MINOR_START;
+               serial_drv.num = CPC_TTY_NPORTS;
+               serial_drv.type = TTY_DRIVER_TYPE_SERIAL;
+               serial_drv.subtype = SERIAL_TYPE_NORMAL;
+
+               serial_drv.init_termios = tty_std_termios;
+               serial_drv.init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
+               serial_drv.flags = TTY_DRIVER_REAL_RAW;
+
+               /* interface routines from the upper tty layer to the tty driver */
+               tty_set_operations(&serial_drv, &pc300_ops);
+
+               /* register the TTY driver */
+               if (tty_register_driver(&serial_drv)) { 
+                       printk("%s-tty: Failed to register serial driver! ",
+                               pc300dev->dev->name);
+                       return;
+               } 
+
+               memset((void *)cpc_tty_area, 0,
+                                                               sizeof(st_cpc_tty_area) * CPC_TTY_NPORTS);
+       }
+
+       cpc_tty = &cpc_tty_area[port];
+       
+       if (cpc_tty->state != CPC_TTY_ST_IDLE) {
+               CPC_TTY_DBG("%s-tty: TTY port %i, already in use.\n",
+                               pc300dev->dev->name, port);
+               return;
+       }
+
+       cpc_tty_cnt++;
+       cpc_tty->state = CPC_TTY_ST_INIT; 
+       cpc_tty->num_open= 0;
+       cpc_tty->tty_minor = port + CPC_TTY_MINOR_START;
+       cpc_tty->pc300dev = pc300dev; 
+
+       INIT_WORK(&cpc_tty->tty_tx_work, cpc_tty_tx_work);
+       INIT_WORK(&cpc_tty->tty_rx_work, cpc_tty_rx_work);
+       
+       cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = NULL;
+
+       pc300dev->cpc_tty = (void *)cpc_tty; 
+       
+       aux = strlen(pc300dev->dev->name);
+       memcpy(cpc_tty->name, pc300dev->dev->name, aux);
+       memcpy(&cpc_tty->name[aux], "-tty", 5);
+       
+       cpc_open(pc300dev->dev);
+       cpc_tty_signal_off(pc300dev, CTL_DTR);
+
+       CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n",
+                       cpc_tty->name,CPC_TTY_MAJOR,cpc_tty->tty_minor); 
+       return; 
+} 
+
+/*
+ * PC300 TTY OPEN routine
+ *
+ * This routine is called by the tty driver to open the interface 
+ * o verify minor
+ * o allocate buffer to Rx and Tx
+ */
+static int cpc_tty_open(struct tty_struct *tty, struct file *flip)
+{
+       int port ;
+       st_cpc_tty_area *cpc_tty;
+
+       if (!tty) { 
+               return -ENODEV;
+       } 
+
+       port = tty->index;
+
+       if ((port < 0) || (port >= CPC_TTY_NPORTS)){ 
+               CPC_TTY_DBG("pc300_tty: open invalid port %d\n", port);
+               return -ENODEV;
+       } 
+
+       cpc_tty = &cpc_tty_area[port];
+       
+       if (cpc_tty->state == CPC_TTY_ST_IDLE){
+               CPC_TTY_DBG("%s: open - invalid interface, port=%d\n",
+                                       cpc_tty->name, tty->index);
+               return -ENODEV;
+       }
+
+       if (cpc_tty->num_open == 0) { /* first open of this tty */
+               if (!cpc_tty_area[port].buf_tx){
+                       cpc_tty_area[port].buf_tx = kmalloc(CPC_TTY_MAX_MTU,GFP_KERNEL);
+                       if (!cpc_tty_area[port].buf_tx) {
+                               CPC_TTY_DBG("%s: error in memory allocation\n",cpc_tty->name);
+                               return -ENOMEM;
+                       }
+               } 
+
+               if (cpc_tty_area[port].buf_rx.first) {
+                       unsigned char * aux;
+                       while (cpc_tty_area[port].buf_rx.first) {
+                               aux = (unsigned char *)cpc_tty_area[port].buf_rx.first;
+                               cpc_tty_area[port].buf_rx.first = cpc_tty_area[port].buf_rx.first->next;
+                               kfree(aux);
+                       }
+                       cpc_tty_area[port].buf_rx.first = NULL;
+                       cpc_tty_area[port].buf_rx.last = NULL;
+               }
+
+               cpc_tty_area[port].state = CPC_TTY_ST_OPEN;
+               cpc_tty_area[port].tty = tty;
+               tty->driver_data = &cpc_tty_area[port];
+
+               cpc_tty_signal_on(cpc_tty->pc300dev, CTL_DTR);
+       } 
+
+       cpc_tty->num_open++;
+
+       CPC_TTY_DBG("%s: opening TTY driver\n", cpc_tty->name);
+       
+       /* avisar driver PC300 */ 
+       return 0; 
+}
+
+/*
+ * PC300 TTY CLOSE routine
+ *
+ * This routine is called by the tty driver to close the interface 
+ * o call close channel in PC300 driver (cpc_closech)
+ * o free Rx and Tx buffers
+ */
+
+static void cpc_tty_close(struct tty_struct *tty, struct file *flip)
+{
+       st_cpc_tty_area    *cpc_tty;
+       unsigned long flags;
+       int res;
+
+       if (!tty || !tty->driver_data ) {
+               CPC_TTY_DBG("hdlx-tty: no TTY in close\n");
+               return;
+       }
+
+       cpc_tty = (st_cpc_tty_area *) tty->driver_data;
+
+       if ((cpc_tty->tty != tty)|| (cpc_tty->state != CPC_TTY_ST_OPEN)) {
+               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
+               return;
+       }
+       
+       if (!cpc_tty->num_open) {
+               CPC_TTY_DBG("%s: TTY is closed\n",cpc_tty->name);
+               return;
+       }
+
+       if (--cpc_tty->num_open > 0) {
+               CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name);
+               return;
+       }
+
+       cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
+
+       CPC_TTY_LOCK(cpc_tty->pc300dev->chan->card, flags);  /* lock irq */ 
+       cpc_tty->tty = NULL;
+       cpc_tty->state = CPC_TTY_ST_INIT;
+       CPC_TTY_UNLOCK(cpc_tty->pc300dev->chan->card, flags); /* unlock irq */ 
+       
+       if (cpc_tty->buf_rx.first) {
+               unsigned char * aux;
+               while (cpc_tty->buf_rx.first) {
+                       aux = (unsigned char *)cpc_tty->buf_rx.first;
+                       cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
+                       kfree(aux);
+               }
+               cpc_tty->buf_rx.first = NULL;
+               cpc_tty->buf_rx.last = NULL;
+       }
+       
+       kfree(cpc_tty->buf_tx);
+       cpc_tty->buf_tx = NULL;
+
+       CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name);
+       
+       if (!serial_drv.refcount && cpc_tty_unreg_flag) {
+               cpc_tty_unreg_flag = 0;
+               CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name);
+               if ((res=tty_unregister_driver(&serial_drv))) { 
+                       CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n",
+                                                       cpc_tty->name,res);
+               }
+       }
+       return; 
+} 
+
+/*
+ * PC300 TTY WRITE routine
+ *
+ * This routine is called by the tty driver to write a series of characters
+ * to the tty device. The characters may come from user or kernel space.
+ * o verify the DCD signal
+ * o send characters to board and start the transmission
+ */
+static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int count)
+{
+       st_cpc_tty_area    *cpc_tty; 
+       pc300ch_t *pc300chan; 
+       pc300_t *card; 
+       int ch; 
+       unsigned long flags; 
+       struct net_device_stats *stats; 
+
+       if (!tty || !tty->driver_data ) { 
+               CPC_TTY_DBG("hdlcX-tty: no TTY in write\n");
+               return -ENODEV;
+       } 
+
+       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
+
+       if ((cpc_tty->tty != tty) ||  (cpc_tty->state != CPC_TTY_ST_OPEN)) { 
+               CPC_TTY_DBG("%s: TTY is not opened\n", cpc_tty->name);
+               return -ENODEV; 
+       }
+
+       if (count > CPC_TTY_MAX_MTU) { 
+               CPC_TTY_DBG("%s: count is invalid\n",cpc_tty->name);
+               return -EINVAL;        /* frame too big */ 
+       }
+
+       CPC_TTY_DBG("%s: cpc_tty_write data len=%i\n",cpc_tty->name,count);
+       
+       pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; 
+       stats = &cpc_tty->pc300dev->dev->stats;
+       card = (pc300_t *) pc300chan->card;
+       ch = pc300chan->channel; 
+
+       /* verify DCD signal*/ 
+       if (cpc_readb(card->hw.scabase + M_REG(ST3,ch)) & ST3_DCD) { 
+               /* DCD is OFF */ 
+               CPC_TTY_DBG("%s : DCD is OFF\n", cpc_tty->name);
+               stats->tx_errors++;
+               stats->tx_carrier_errors++;
+               CPC_TTY_LOCK(card, flags); 
+               cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_BUF_CLR); 
+               
+               if (card->hw.type == PC300_TE) { 
+                       cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, 
+                               cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & 
+                               ~(CPLD_REG2_FALC_LED1 << (2 *ch))); 
+               }
+
+               CPC_TTY_UNLOCK(card, flags); 
+
+               return -EINVAL; 
+       }
+
+       if (cpc_tty_send_to_card(cpc_tty->pc300dev, (void*)buf, count)) { 
+          /* failed to send */
+          CPC_TTY_DBG("%s: trasmition error\n", cpc_tty->name);
+          return 0;
+       }
+       return count; 
+} 
+
+/*
+ * PC300 TTY Write Room routine
+ * 
+ * This routine returns the numbers of characteres the tty driver will accept
+ * for queuing to be written. 
+ * o return MTU
+ */
+static int cpc_tty_write_room(struct tty_struct *tty)
+{
+       st_cpc_tty_area    *cpc_tty; 
+
+       if (!tty || !tty->driver_data ) { 
+               CPC_TTY_DBG("hdlcX-tty: no TTY to write room\n");
+               return -ENODEV;
+       }
+
+       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
+
+       if ((cpc_tty->tty != tty) ||  (cpc_tty->state != CPC_TTY_ST_OPEN)) { 
+               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
+               return -ENODEV; 
+       }
+       
+       CPC_TTY_DBG("%s: write room\n",cpc_tty->name);
+       
+       return CPC_TTY_MAX_MTU;
+} 
+
+/*
+ * PC300 TTY chars in buffer routine
+ * 
+ * This routine returns the chars number in the transmission buffer 
+ * o returns 0
+ */
+static int cpc_tty_chars_in_buffer(struct tty_struct *tty)
+{
+       st_cpc_tty_area    *cpc_tty; 
+
+       if (!tty || !tty->driver_data ) {
+               CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n");
+               return -ENODEV; 
+       }
+
+       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
+
+       if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) { 
+               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
+               return -ENODEV; 
+       }
+   
+       return 0;
+} 
+
+static int pc300_tiocmset(struct tty_struct *tty,
+                         unsigned int set, unsigned int clear)
+{
+       st_cpc_tty_area    *cpc_tty; 
+
+       CPC_TTY_DBG("%s: set:%x clear:%x\n", __func__, set, clear);
+
+       if (!tty || !tty->driver_data ) {
+               CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n");  
+               return -ENODEV; 
+       }
+
+       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
+
+       if (set & TIOCM_RTS)
+               cpc_tty_signal_on(cpc_tty->pc300dev, CTL_RTS);
+       if (set & TIOCM_DTR)
+               cpc_tty_signal_on(cpc_tty->pc300dev, CTL_DTR);
+
+       if (clear & TIOCM_RTS)
+               cpc_tty_signal_off(cpc_tty->pc300dev, CTL_RTS);
+       if (clear & TIOCM_DTR)
+               cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
+
+       return 0;
+}
+
+static int pc300_tiocmget(struct tty_struct *tty)
+{
+       unsigned int result;
+       unsigned char status;
+       unsigned long flags;
+       st_cpc_tty_area  *cpc_tty = (st_cpc_tty_area *) tty->driver_data;
+       pc300dev_t *pc300dev = cpc_tty->pc300dev;
+       pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan;
+       pc300_t *card = (pc300_t *) pc300chan->card;
+       int ch = pc300chan->channel;
+
+       cpc_tty = (st_cpc_tty_area *) tty->driver_data;
+
+       CPC_TTY_DBG("%s-tty: tiocmget\n",
+               ((struct net_device*)(pc300dev->hdlc))->name);
+
+       CPC_TTY_LOCK(card, flags);
+       status = cpc_readb(card->hw.scabase+M_REG(CTL,ch));
+       CPC_TTY_UNLOCK(card,flags);
+
+       result = ((status & CTL_DTR) ? TIOCM_DTR : 0) |
+                ((status & CTL_RTS) ? TIOCM_RTS : 0);
+
+       return result;
+}
+
+/*
+ * PC300 TTY Flush Buffer routine
+ *
+ * This routine resets the transmission buffer 
+ */
+static void cpc_tty_flush_buffer(struct tty_struct *tty)
+{ 
+       st_cpc_tty_area    *cpc_tty; 
+       
+       if (!tty || !tty->driver_data ) {
+               CPC_TTY_DBG("hdlcX-tty: no TTY to flush buffer\n");     
+               return; 
+       }
+
+       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
+
+       if ((cpc_tty->tty != tty) ||  (cpc_tty->state != CPC_TTY_ST_OPEN)) { 
+               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
+               return; 
+       }
+
+       CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name);
+
+       tty_wakeup(tty);        
+       return; 
+} 
+
+/*
+ * PC300 TTY Hangup routine
+ *
+ * This routine is called by the tty driver to hangup the interface 
+ * o clear DTR signal
+ */
+
+static void cpc_tty_hangup(struct tty_struct *tty)
+{ 
+       st_cpc_tty_area    *cpc_tty; 
+       int res;
+
+       if (!tty || !tty->driver_data ) {
+               CPC_TTY_DBG("hdlcX-tty: no TTY to hangup\n");   
+               return ; 
+       }
+
+       cpc_tty = (st_cpc_tty_area *) tty->driver_data; 
+
+       if ((cpc_tty->tty != tty) || (cpc_tty->state != CPC_TTY_ST_OPEN)) {
+               CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name);
+               return ;
+       }
+       if (!serial_drv.refcount && cpc_tty_unreg_flag) {
+               cpc_tty_unreg_flag = 0;
+               CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name);
+               if ((res=tty_unregister_driver(&serial_drv))) { 
+                       CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n",
+                                                       cpc_tty->name,res);
+               }
+       }
+       cpc_tty_signal_off(cpc_tty->pc300dev, CTL_DTR);
+}
+
+/*
+ * PC300 TTY RX work routine
+ * This routine treats RX work
+ * o verify read buffer
+ * o call the line disc. read
+ * o free memory
+ */
+static void cpc_tty_rx_work(struct work_struct *work)
+{
+       st_cpc_tty_area *cpc_tty;
+       unsigned long port;
+       int i, j;
+       volatile st_cpc_rx_buf *buf;
+       char flags=0,flg_rx=1; 
+       struct tty_ldisc *ld;
+
+       if (cpc_tty_cnt == 0) return;
+       
+       for (i=0; (i < 4) && flg_rx ; i++) {
+               flg_rx = 0;
+
+               cpc_tty = container_of(work, st_cpc_tty_area, tty_rx_work);
+               port = cpc_tty - cpc_tty_area;
+
+               for (j=0; j < CPC_TTY_NPORTS; j++) {
+                       cpc_tty = &cpc_tty_area[port];
+               
+                       if ((buf=cpc_tty->buf_rx.first) != NULL) {
+                               if (cpc_tty->tty) {
+                                       ld = tty_ldisc_ref(cpc_tty->tty);
+                                       if (ld) {
+                                               if (ld->ops->receive_buf) {
+                                                       CPC_TTY_DBG("%s: call line disc. receive_buf\n",cpc_tty->name);
+                                                       ld->ops->receive_buf(cpc_tty->tty, (char *)(buf->data), &flags, buf->size);
+                                               }
+                                               tty_ldisc_deref(ld);
+                                       }
+                               }       
+                               cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next;
+                               kfree((void *)buf);
+                               buf = cpc_tty->buf_rx.first;
+                               flg_rx = 1;
+                       }
+                       if (++port == CPC_TTY_NPORTS) port = 0;
+               }
+       }
+} 
+
+/*
+ * PC300 TTY RX work routine
+ *
+ * This routine treats RX interrupt. 
+ * o read all frames in card
+ * o verify the frame size
+ * o read the frame in rx buffer
+ */
+static void cpc_tty_rx_disc_frame(pc300ch_t *pc300chan)
+{
+       volatile pcsca_bd_t __iomem * ptdescr; 
+       volatile unsigned char status; 
+       pc300_t *card = (pc300_t *)pc300chan->card; 
+       int ch = pc300chan->channel; 
+
+       /* dma buf read */ 
+       ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + 
+                               RX_BD_ADDR(ch, pc300chan->rx_first_bd)); 
+       while (pc300chan->rx_first_bd != pc300chan->rx_last_bd) { 
+               status = cpc_readb(&ptdescr->status); 
+               cpc_writeb(&ptdescr->status, 0); 
+               cpc_writeb(&ptdescr->len, 0); 
+               pc300chan->rx_first_bd = (pc300chan->rx_first_bd + 1) & 
+                                       (N_DMA_RX_BUF - 1); 
+               if (status & DST_EOM) { 
+                       break; /* end of message */
+               }
+               ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->next)); 
+       }
+}
+
+void cpc_tty_receive(pc300dev_t *pc300dev)
+{
+       st_cpc_tty_area *cpc_tty; 
+       pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; 
+       pc300_t *card = (pc300_t *)pc300chan->card; 
+       int ch = pc300chan->channel; 
+       volatile pcsca_bd_t  __iomem * ptdescr; 
+       struct net_device_stats *stats = &pc300dev->dev->stats;
+       int rx_len, rx_aux; 
+       volatile unsigned char status; 
+       unsigned short first_bd = pc300chan->rx_first_bd;
+       st_cpc_rx_buf *new = NULL;
+       unsigned char dsr_rx;
+
+       if (pc300dev->cpc_tty == NULL) { 
+               return; 
+       }
+
+       dsr_rx = cpc_readb(card->hw.scabase + DSR_RX(ch));
+
+       cpc_tty = pc300dev->cpc_tty;
+
+       while (1) { 
+               rx_len = 0;
+               ptdescr = (pcsca_bd_t  __iomem *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd));
+               while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
+                       rx_len += cpc_readw(&ptdescr->len);
+                       first_bd = (first_bd + 1) & (N_DMA_RX_BUF - 1);
+                       if (status & DST_EOM) {
+                               break;
+                       }
+                       ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase+cpc_readl(&ptdescr->next));
+               }
+                       
+               if (!rx_len) { 
+                       if (dsr_rx & DSR_BOF) {
+                               /* update EDA */ 
+                               cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), 
+                                               RX_BD_ADDR(ch, pc300chan->rx_last_bd)); 
+                       }
+                       kfree(new);
+                       return; 
+               }
+               
+               if (rx_len > CPC_TTY_MAX_MTU) { 
+                       /* Free RX descriptors */ 
+                       CPC_TTY_DBG("%s: frame size is invalid.\n",cpc_tty->name);
+                       stats->rx_errors++; 
+                       stats->rx_frame_errors++; 
+                       cpc_tty_rx_disc_frame(pc300chan);
+                       continue;
+               } 
+               
+               new = kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC);
+               if (!new) {
+                       cpc_tty_rx_disc_frame(pc300chan);
+                       continue;
+               }
+               
+               /* dma buf read */ 
+               ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + 
+                               RX_BD_ADDR(ch, pc300chan->rx_first_bd)); 
+
+               rx_len = 0;     /* counter frame size */
+               
+               while ((status = cpc_readb(&ptdescr->status)) & DST_OSB) {
+                       rx_aux = cpc_readw(&ptdescr->len);
+                       if ((status & (DST_OVR | DST_CRC | DST_RBIT |  DST_SHRT | DST_ABT))
+                               || (rx_aux > BD_DEF_LEN)) {
+                               CPC_TTY_DBG("%s: reception error\n", cpc_tty->name);
+                               stats->rx_errors++; 
+                               if (status & DST_OVR) { 
+                                       stats->rx_fifo_errors++; 
+                               }
+                               if (status & DST_CRC) { 
+                                       stats->rx_crc_errors++; 
+                               }
+                               if ((status & (DST_RBIT | DST_SHRT | DST_ABT)) ||
+                                       (rx_aux > BD_DEF_LEN))  { 
+                                       stats->rx_frame_errors++; 
+                               } 
+                               /* discard remainig descriptors used by the bad frame */ 
+                               CPC_TTY_DBG("%s: reception error - discard descriptors",
+                                               cpc_tty->name);
+                               cpc_tty_rx_disc_frame(pc300chan);
+                               rx_len = 0;
+                               kfree(new);
+                               new = NULL;
+                               break; /* read next frame - while(1) */
+                       }
+
+                       if (cpc_tty->state != CPC_TTY_ST_OPEN) {
+                               /* Free RX descriptors */ 
+                               cpc_tty_rx_disc_frame(pc300chan);
+                               stats->rx_dropped++; 
+                               rx_len = 0; 
+                               kfree(new);
+                               new = NULL;
+                               break; /* read next frame - while(1) */
+                       }
+
+                       /* read the segment of the frame */
+                       if (rx_aux != 0) {
+                               memcpy_fromio((new->data + rx_len), 
+                                       (void __iomem *)(card->hw.rambase + 
+                                        cpc_readl(&ptdescr->ptbuf)), rx_aux);
+                               rx_len += rx_aux; 
+                       }
+                       cpc_writeb(&ptdescr->status,0); 
+                       cpc_writeb(&ptdescr->len, 0); 
+                       pc300chan->rx_first_bd = (pc300chan->rx_first_bd + 1) & 
+                                       (N_DMA_RX_BUF -1); 
+                       if (status & DST_EOM)break;
+                       
+                       ptdescr = (pcsca_bd_t __iomem *) (card->hw.rambase + 
+                                       cpc_readl(&ptdescr->next)); 
+               }
+               /* update pointer */ 
+               pc300chan->rx_last_bd = (pc300chan->rx_first_bd - 1) & 
+                                       (N_DMA_RX_BUF - 1) ; 
+               if (!(dsr_rx & DSR_BOF)) {
+                       /* update EDA */ 
+                       cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), 
+                                       RX_BD_ADDR(ch, pc300chan->rx_last_bd)); 
+               }
+               if (rx_len != 0) { 
+                       stats->rx_bytes += rx_len; 
+               
+                       if (pc300dev->trace_on) { 
+                               cpc_tty_trace(pc300dev, new->data,rx_len, 'R'); 
+                       } 
+                       new->size = rx_len;
+                       new->next = NULL;
+                       if (cpc_tty->buf_rx.first == NULL) {
+                               cpc_tty->buf_rx.first = new;
+                               cpc_tty->buf_rx.last = new;
+                       } else {
+                               cpc_tty->buf_rx.last->next = new;
+                               cpc_tty->buf_rx.last = new;
+                       }
+                       schedule_work(&(cpc_tty->tty_rx_work));
+                       stats->rx_packets++;
+               }
+       } 
+} 
+
+/*
+ * PC300 TTY TX work routine
+ * 
+ * This routine treats TX interrupt. 
+ * o if need call line discipline wakeup
+ * o call wake_up_interruptible
+ */
+static void cpc_tty_tx_work(struct work_struct *work)
+{
+       st_cpc_tty_area *cpc_tty =
+               container_of(work, st_cpc_tty_area, tty_tx_work);
+       struct tty_struct *tty; 
+
+       CPC_TTY_DBG("%s: cpc_tty_tx_work init\n",cpc_tty->name);
+       
+       if ((tty = cpc_tty->tty) == NULL) { 
+               CPC_TTY_DBG("%s: the interface is not opened\n",cpc_tty->name);
+               return; 
+       }
+       tty_wakeup(tty);
+}
+
+/*
+ * PC300 TTY send to card routine
+ * 
+ * This routine send data to card. 
+ * o clear descriptors
+ * o write data to DMA buffers
+ * o start the transmission
+ */
+static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len)
+{
+       pc300ch_t *chan = (pc300ch_t *)dev->chan; 
+       pc300_t *card = (pc300_t *)chan->card; 
+       int ch = chan->channel; 
+       struct net_device_stats *stats = &dev->dev->stats;
+       unsigned long flags; 
+       volatile pcsca_bd_t __iomem *ptdescr; 
+       int i, nchar;
+       int tosend = len;
+       int nbuf = ((len - 1)/BD_DEF_LEN) + 1;
+       unsigned char *pdata=buf;
+
+       CPC_TTY_DBG("%s:cpc_tty_send_to_cars len=%i", 
+                       (st_cpc_tty_area *)dev->cpc_tty->name,len);     
+
+       if (nbuf >= card->chan[ch].nfree_tx_bd) {
+               return 1;
+       }
+       
+       /* write buffer to DMA buffers */ 
+       CPC_TTY_DBG("%s: call dma_buf_write\n",
+                       (st_cpc_tty_area *)dev->cpc_tty->name); 
+       for (i = 0 ; i < nbuf ; i++) {
+               ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + 
+                       TX_BD_ADDR(ch, card->chan[ch].tx_next_bd));
+               nchar = (BD_DEF_LEN > tosend) ? tosend : BD_DEF_LEN;
+               if (cpc_readb(&ptdescr->status) & DST_OSB) {
+                       memcpy_toio((void __iomem *)(card->hw.rambase + 
+                               cpc_readl(&ptdescr->ptbuf)), 
+                               &pdata[len - tosend], 
+                               nchar);
+                       card->chan[ch].nfree_tx_bd--;
+                       if ((i + 1) == nbuf) {
+                               /* This must be the last BD to be used */
+                               cpc_writeb(&ptdescr->status, DST_EOM);
+                       } else {
+                               cpc_writeb(&ptdescr->status, 0);
+                       }
+                       cpc_writew(&ptdescr->len, nchar);
+               } else {
+                       CPC_TTY_DBG("%s: error in dma_buf_write\n",
+                                       (st_cpc_tty_area *)dev->cpc_tty->name); 
+                       stats->tx_dropped++;
+                       return 1; 
+               }
+               tosend -= nchar;
+               card->chan[ch].tx_next_bd = 
+                       (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1);
+       }
+
+       if (dev->trace_on) { 
+               cpc_tty_trace(dev, buf, len,'T'); 
+       }
+
+       /* start transmission */ 
+       CPC_TTY_DBG("%s: start transmission\n",
+               (st_cpc_tty_area *)dev->cpc_tty->name); 
+       
+       CPC_TTY_LOCK(card, flags); 
+       cpc_writeb(card->hw.scabase + DTX_REG(EDAL, ch), 
+                       TX_BD_ADDR(ch, chan->tx_next_bd)); 
+       cpc_writeb(card->hw.scabase + M_REG(CMD, ch), CMD_TX_ENA); 
+       cpc_writeb(card->hw.scabase + DSR_TX(ch), DSR_DE); 
+
+       if (card->hw.type == PC300_TE) { 
+               cpc_writeb(card->hw.falcbase + card->hw.cpld_reg2, 
+                       cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) |
+                       (CPLD_REG2_FALC_LED1 << (2 * ch))); 
+       }
+       CPC_TTY_UNLOCK(card, flags); 
+       return 0; 
+} 
+
+/*
+ *     PC300 TTY trace routine
+ *
+ *  This routine send trace of connection to application. 
+ *  o clear descriptors
+ *  o write data to DMA buffers
+ *  o start the transmission
+ */
+
+static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx)
+{
+       struct sk_buff *skb; 
+
+       if ((skb = dev_alloc_skb(10 + len)) == NULL) { 
+               /* out of memory */ 
+               CPC_TTY_DBG("%s: tty_trace - out of memory\n", dev->dev->name);
+               return; 
+       }
+
+       skb_put (skb, 10 + len); 
+       skb->dev = dev->dev; 
+       skb->protocol = htons(ETH_P_CUST); 
+       skb_reset_mac_header(skb);
+       skb->pkt_type = PACKET_HOST; 
+       skb->len = 10 + len; 
+
+       skb_copy_to_linear_data(skb, dev->dev->name, 5);
+       skb->data[5] = '['; 
+       skb->data[6] = rxtx; 
+       skb->data[7] = ']'; 
+       skb->data[8] = ':'; 
+       skb->data[9] = ' '; 
+       skb_copy_to_linear_data_offset(skb, 10, buf, len);
+       netif_rx(skb); 
+}      
+
+/*
+ *     PC300 TTY unregister service routine
+ *
+ *     This routine unregister one interface. 
+ */
+void cpc_tty_unregister_service(pc300dev_t *pc300dev)
+{
+       st_cpc_tty_area *cpc_tty; 
+       ulong flags;
+       int res;
+
+       if ((cpc_tty= (st_cpc_tty_area *) pc300dev->cpc_tty) == NULL) {
+               CPC_TTY_DBG("%s: interface is not TTY\n", pc300dev->dev->name);
+               return; 
+       }
+       CPC_TTY_DBG("%s: cpc_tty_unregister_service", cpc_tty->name);
+
+       if (cpc_tty->pc300dev != pc300dev) { 
+               CPC_TTY_DBG("%s: invalid tty ptr=%s\n", 
+               pc300dev->dev->name, cpc_tty->name);
+               return; 
+       }
+
+       if (--cpc_tty_cnt == 0) { 
+               if (serial_drv.refcount) {
+                       CPC_TTY_DBG("%s: unregister is not possible, refcount=%d",
+                                                       cpc_tty->name, serial_drv.refcount);
+                       cpc_tty_cnt++;
+                       cpc_tty_unreg_flag = 1;
+                       return;
+               } else { 
+                       CPC_TTY_DBG("%s: unregister the tty driver\n", cpc_tty->name);
+                       if ((res=tty_unregister_driver(&serial_drv))) { 
+                               CPC_TTY_DBG("%s: ERROR ->unregister the tty driver error=%d\n",
+                                                               cpc_tty->name,res);
+                       }
+               }
+       }
+       CPC_TTY_LOCK(pc300dev->chan->card,flags);
+       cpc_tty->tty = NULL; 
+       CPC_TTY_UNLOCK(pc300dev->chan->card, flags);
+       cpc_tty->tty_minor = 0; 
+       cpc_tty->state = CPC_TTY_ST_IDLE; 
+} 
+
+/*
+ * PC300 TTY trigger poll routine
+ * This routine is called by pc300driver to treats Tx interrupt. 
+ */
+void cpc_tty_trigger_poll(pc300dev_t *pc300dev)
+{
+       st_cpc_tty_area *cpc_tty = (st_cpc_tty_area *)pc300dev->cpc_tty; 
+       if (!cpc_tty) {
+               return;
+       }
+       schedule_work(&(cpc_tty->tty_tx_work)); 
+}