lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Sun, 29 Jan 2012 19:01:57 -0800 From: Andrea Shepard <andrea@...sephoneslair.org> To: linux-kernel@...r.kernel.org, netdev@...r.kernel.org Cc: khc@...waw.pl, davem@...emloft.net, mmarek@...e.cz, jkosina@...e.cz, joe@...ches.com, justinmattock@...il.com, gregkh@...e.de, alan@...ux.intel.com, jdmason@...zu.us Subject: [22/22] Cyclades PC300 driver: omnibus patch from merge up to final version (patches 01 through 20 inclusive) This is an omnibus patch including patches 01 through 20 of this series; one may readily verify that it passes checkpatch.pl style conformance and that it builds cleanly. The resulting driver is known to function reliably and achieve near theoretical maximum performance with a full T1 circuit and a single-port PC-300 T1/E1 card on a Sun Ultra 10. Signed-off-by: Andrea Shepard <andrea@...sephoneslair.org> diff --git a/drivers/net/wan/Kconfig b/drivers/net/wan/Kconfig index 423eb26..36a439a 100644 --- a/drivers/net/wan/Kconfig +++ b/drivers/net/wan/Kconfig @@ -205,10 +205,8 @@ config WANXL_BUILD_FIRMWARE config PC300 tristate "Cyclades-PC300 support (RS-232/V.35, X.21, T1/E1 boards)" - depends on HDLC && PCI && BROKEN + depends on HDLC && PCI ---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 @@ -217,6 +215,10 @@ config PC300 option later and read the file README.mlppp provided by PC300 package. + Due to changes in certain ioctls necessary for portability, this + version requires a new version of pc300utils, which may be found + at: http://charon.persephoneslair.org/~andrea/software/pc300utils/ + To compile this as a module, choose M here: the module will be called pc300. @@ -228,11 +230,8 @@ config PC300_MLPPP 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) + depends on HDLC && PC300 && (PPP=n || !PPP_MULTILINK || PPP_SYNC_TTY=n || !HDLC_PPP) && PC300_MLPPP config PC300TOO tristate "Cyclades PC300 RSV/X21 alternative support" diff --git a/drivers/net/wan/hd64572.h b/drivers/net/wan/hd64572.h index 96567c2..2626fea 100644 --- a/drivers/net/wan/hd64572.h +++ b/drivers/net/wan/hd64572.h @@ -4,7 +4,7 @@ * * Author: Ivan Passos <ivan@...lades.com> * - * Copyright: (c) 2000-2001 Cyclades Corp. + * Copyright: (c) 2000-2004 Cyclades Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -172,11 +172,11 @@ /* Block Descriptor Structure */ typedef struct { - unsigned long next; /* pointer to next block descriptor */ - unsigned long ptbuf; /* buffer pointer */ - unsigned short len; /* data length */ - unsigned char status; /* status */ - unsigned char filler[5]; /* alignment filler (16 bytes) */ + u32 next; /* pointer to next block descriptor */ + u32 ptbuf; /* buffer pointer */ + u16 len; /* data length */ + u8 status; /* status */ + u8 filler[5]; /* alignment filler (16 bytes) */ } pcsca_bd_t; /* Block Descriptor Structure */ diff --git a/drivers/net/wan/pc300-falc-lh.h b/drivers/net/wan/pc300-falc-lh.h index 01ed23c..514000a 100644 --- a/drivers/net/wan/pc300-falc-lh.h +++ b/drivers/net/wan/pc300-falc-lh.h @@ -3,7 +3,7 @@ * * Author: Ivan Passos <ivan@...lades.com> * - * Copyright: (c) 2000-2001 Cyclades Corp. + * Copyright: (c) 2000-2004 Cyclades Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License diff --git a/drivers/net/wan/pc300.h b/drivers/net/wan/pc300.h index 2e4f84f..b0f3601 100644 --- a/drivers/net/wan/pc300.h +++ b/drivers/net/wan/pc300.h @@ -3,7 +3,7 @@ * * Author: Ivan Passos <ivan@...lades.com> * - * Copyright: (c) 1999-2002 Cyclades Corp. + * Copyright: (c) 1999-2004 Cyclades Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -105,9 +105,16 @@ #define PC300_PROTO_MLPPP 1 + +#define PC300_DEVNAME "hdlc" /* Dev. name base (for hdlc0, hdlc1, etc.) */ +#define PC300_MAXINDEX 100 /* Max dev. name index (the '0' in hdlc0) */ + +#define PC300_MAXCARDS 4 /* Max number of cards per system */ #define PC300_MAXCHAN 2 /* Number of channels per card */ +#define PC300_PLX_WIN 0x80 /* PLX control window size (128b) */ #define PC300_RAMSIZE 0x40000 /* RAM window size (256Kb) */ +#define PC300_SCASIZE 0x400 /* SCA window size (1Kb) */ #define PC300_FALCSIZE 0x400 /* FALC window size (1Kb) */ #define PC300_OSC_CLOCK 24576000 @@ -143,13 +150,28 @@ * 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();} +#ifdef __KERNEL__ +#define cpc_writeb(port, val) {writeb((u8)(val), \ + (void __iomem *)(port)); mb(); } +#define cpc_writew(port, val) {writew((u16)(val), \ + (void __iomem *)(port)); mb(); } +#define cpc_writel(port, val) {writel((u32)(val), \ + (void __iomem *)(port)); mb(); } + +#define cpc_readb(port) readb((void __iomem *)(port)) +#define cpc_readw(port) readw((void __iomem *)(port)) +#define cpc_readl(port) readl((void __iomem *)(port)) -#define cpc_readb(port) readb(port) -#define cpc_readw(port) readw(port) -#define cpc_readl(port) readl(port) +#else /* __KERNEL__ */ +#define cpc_writeb(port, val) (*((u8 *)(port)) = (u8)(val)) +#define cpc_writew(port, val) (*((u16 *)(port)) = (u16)(val)) +#define cpc_writel(port, val) (*((u32 *)(port)) = (u32)(val)) + +#define cpc_readb(port) (*((u8 *)(port))) +#define cpc_readw(port) (*((u16 *)(port))) +#define cpc_readl(port) (*((u32 *)(port))) + +#endif /* __KERNEL__ */ /****** Data Structures *****************************************************/ @@ -267,11 +289,47 @@ typedef struct rsv_x21_status { u8 dtr; } rsv_x21_status_t; +struct pc300_net_stats { + u64 rx_packets; + u64 tx_packets; + u64 rx_bytes; + u64 tx_bytes; + u64 rx_errors; + u64 tx_errors; + u64 rx_dropped; + u64 tx_dropped; + u64 multicast; + u64 collisions; + + /* detailed rx_errors: */ + u64 rx_length_errors; + u64 rx_over_errors; + u64 rx_crc_errors; + u64 rx_frame_errors; + u64 rx_fifo_errors; + u64 rx_missed_errors; + + /* detailed tx_errors */ + u64 tx_aborted_errors; + u64 tx_carrier_errors; + u64 tx_fifo_errors; + u64 tx_heartbeat_errors; + u64 tx_window_errors; + + u64 rx_compressed; + u64 tx_compressed; +}; + typedef struct pc300stats { int hw_type; u32 line_on; u32 line_off; - struct net_device_stats gen_stats; + /* Use this instead of net_device_stats, since passing + * net_device_stats breaks 32-bit user processes on 64-bit kernels, + * and rtnetlink is unreasonably complicated just to get + * some statistics. + */ + struct pc300_net_stats net_stats; falc_t te_stats; } pc300stats_t; @@ -291,16 +349,31 @@ typedef struct pc300patterntst { u16 num_errors; } pc300patterntst_t; +#ifdef __KERNEL__ + typedef struct pc300dev { struct pc300ch *chan; u8 trace_on; u32 line_on; /* DCD(X.21, RSV) / sync(TE) change counters */ u32 line_off; +#ifdef __KERNEL__ char name[16]; - struct net_device *dev; + hdlc_device *hdlc; + struct net_device *netdev; + + void *private; + struct sk_buff *tx_skb; + + enum { + CPC_DMA_FULL, + CPC_DMA_ERROR, + TRANSMISSION_ACTIVE, + CHANNEL_CLOSED + } reason_stopped; #ifdef CONFIG_PC300_MLPPP void *cpc_tty; /* information to PC300 TTY driver */ #endif +#endif /* __KERNEL__ */ }pc300dev_t; typedef struct pc300hw { @@ -314,29 +387,60 @@ typedef struct pc300hw { 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 */ + phys_addr_t 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) */ + phys_addr_t 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) */ + phys_addr_t 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) */ + phys_addr_t 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) */ + phys_addr_t falcphys; /* FALC registers MMIO base (physical) */ + void __iomem *falcbase;/* FALC registers MMIO base (virtual) */ u32 falcsize; /* FALC registers MMIO size */ } pc300hw_t; +#endif /* __KERNEL__ */ + +/* + * It's problematic to pass the addresses out to userland, since their sizes + * are so platform-dependent. The userland pc300cfg program might be 32-bit + * even on a 64-bit kernel, and in any case it can't see phys_addr_t. Since + * this information isn't even very interesting and in any case is visible in + * from the printk() calls when we init, just leave it out when responding to + * SIOCGPC300CONF. + */ + +struct pc300hw_user { + 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 iosize; /* PLX registers I/O size */ + u32 plxsize; /* PLX registers MMIO size */ + u32 scasize; /* SCA registers MMIO size */ + u32 alloc_ramsize; /* RAM MMIO size allocated by the PCI bridge */ + u32 ramsize; /* On-board RAM MMIO size */ + u32 falcsize; /* FALC registers MMIO size */ +}; + 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.) */ + u8 monitor; /* Monitor mode (0 = off, !0 = on) */ /* TE-specific parameters */ u8 lcode; /* Line Code (AMI, B8ZS, etc.) */ @@ -346,6 +450,8 @@ typedef struct pc300chconf { u32 tslot_bitmap; /* bit[i]=1 => timeslot _i_ is active */ } pc300chconf_t; +#ifdef __KERNEL__ + typedef struct pc300ch { struct pc300 *card; int channel; @@ -365,8 +471,10 @@ typedef struct pc300 { spinlock_t card_lock; } pc300_t; +#endif /* __KERNEL__ */ + typedef struct pc300conf { - pc300hw_t hw; + struct pc300hw_user hw; pc300chconf_t conf; } pc300conf_t; @@ -430,7 +538,19 @@ enum pc300_loopback_cmds { #define PC300_TX_QUEUE_LEN 100 #define PC300_DEF_MTU 1600 -/* Function Prototypes */ -int cpc_open(struct net_device *dev); +#ifdef __KERNEL__ + +int cpc_open(struct net_device *); + +#ifdef CONFIG_PC300_MLPPP +void cpc_tty_init(pc300dev_t *); +void cpc_tty_unregister_service(pc300dev_t *); +void cpc_tty_receive(pc300dev_t *); +void cpc_tty_trigger_poll(pc300dev_t *); +void cpc_tty_reset_var(void); +#endif /* CONFIG_PC300_MLPP */ + +#endif /* __KERNEL__ */ #endif /* _PC300_H */ + diff --git a/drivers/net/wan/pc300_drv.c b/drivers/net/wan/pc300_drv.c index 1eeedd6..bcdf53a 100644 --- a/drivers/net/wan/pc300_drv.c +++ b/drivers/net/wan/pc300_drv.c @@ -1,6 +1,6 @@ #define USE_PCI_CLOCK static const char rcsid[] = -"Revision: 3.4.5 Date: 2002/03/07 "; +"Revision: 4.1.0 Date: 2004/02/20 "; /* * pc300.c Cyclades-PC300(tm) Driver. @@ -8,7 +8,7 @@ static const char rcsid[] = * Author: Ivan Passos <ivan@...lades.com> * Maintainer: PC300 Maintainer <pc300@...lades.com> * - * Copyright: (c) 1999-2003 Cyclades Corp. + * Copyright: (c) 1999-2004 Cyclades Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -16,6 +16,13 @@ static const char rcsid[] = * 2 of the License, or (at your option) any later version. * * Using tabstop = 4. + * + * Cyclades version 4.1.0 merged in, with new portability fixes, + * and ported to recent kernels by Andrea Shepard <andrea@...sephoneslair.org> + * + * Due to changes in certain ioctls necessary for portability, this + * version requires a new version of pc300utils, which may be found + * at: http://charon.persephoneslair.org/~andrea/software/pc300utils/ * * $Log: pc300_drv.c,v $ * Revision 3.23 2002/03/20 13:58:40 henrique @@ -219,6 +226,7 @@ static const char rcsid[] = #include <linux/mm.h> #include <linux/ioport.h> #include <linux/pci.h> +#include <linux/interrupt.h> #include <linux/errno.h> #include <linux/string.h> #include <linux/init.h> @@ -238,21 +246,22 @@ static const char rcsid[] = #include "pc300.h" -#define CPC_LOCK(card,flags) \ - do { \ - spin_lock_irqsave(&card->card_lock, flags); \ - } while (0) +#define CPC_LOCK(card, flags) \ + { \ + spin_lock_irqsave(&((card)->card_lock), (flags)); \ + } -#define CPC_UNLOCK(card,flags) \ - do { \ - spin_unlock_irqrestore(&card->card_lock, flags); \ - } while (0) +#define CPC_UNLOCK(card, flags) \ + { \ + spin_unlock_irqrestore(&((card)->card_lock), (flags)); \ + } #undef PC300_DEBUG_PCI #undef PC300_DEBUG_INTR #undef PC300_DEBUG_TX #undef PC300_DEBUG_RX #undef PC300_DEBUG_OTHER +#undef PC300_DEBUG_QUEUE static DEFINE_PCI_DEVICE_TABLE(cpc_pci_dev_id) = { /* PC300/RSV or PC300/X21, 2 chan */ @@ -279,53 +288,128 @@ MODULE_DEVICE_TABLE(pci, cpc_pci_dev_id); #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); +/* DMA routines */ +static int dma_buf_read(pc300_t *, int, struct sk_buff *); +static int dma_buf_write(pc300_t *, int, u8 *, int); +static int dma_get_rx_frame_size(pc300_t *, int); +static void rx_dma_buf_check(pc300_t *, int); static void rx_dma_buf_init(pc300_t *, int); +static void rx_dma_buf_pt_init(pc300_t *, int); +static void rx_dma_start(pc300_t *, int); +static void rx_dma_stop(pc300_t *, int); +#ifdef PC300_DEBUG_OTHER +static void tx1_dma_buf_check(pc300_t *, int); +#endif 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 void tx_dma_buf_init(pc300_t *, int); +static void tx_dma_buf_pt_init(pc300_t *, int); +static void tx_dma_stop(pc300_t *, int); + +/* FALC routines */ +static void falc_check_status(pc300_t *, int, unsigned char); +static void falc_close_all_timeslots(pc300_t *, int); +static void falc_close_timeslot(pc300_t *, int, int); +static void falc_disable_comm(pc300_t *, int); +static void falc_e1_intr(pc300_t *, int); +static void falc_e1_loop_detection(pc300_t *, int, u8); +static void falc_enable_comm(pc300_t *, int); +static void falc_generate_loop_down_code(pc300_t *, int); +static void falc_generate_loop_up_code(pc300_t *, int); +static void falc_init_e1(pc300_t *, int); +static void falc_init_hdlc(pc300_t *, int); +static void falc_init_t1(pc300_t *, int); +static void falc_init_timeslot(pc300_t *, int); +static void falc_intr_enable(pc300_t *, int); +static void falc_intr(pc300_t *); +static void falc_issue_cmd(pc300_t *, int, u8); +static void falc_local_loop(pc300_t *, int, int); +static void falc_open_all_timeslots(pc300_t *, int); +static void falc_open_timeslot(pc300_t *, int, int); +static u16 falc_pattern_test_error(pc300_t *, int); +static void falc_pattern_test(pc300_t *, int, unsigned int); +static void falc_payload_loop(pc300_t *, int, int); +static void falc_remote_loop(pc300_t *, int, int); +static void falc_t1_intr(pc300_t *, int); +static void falc_t1_loop_detection(pc300_t *, int, u8); +static void falc_update_stats(pc300_t *, int); +static void te_config(pc300_t *, int); +static void turn_off_xld(pc300_t *, int); +static void turn_off_xlu(pc300_t *, int); + +static void sca_intr(pc300_t *); +static void sca_tx_intr(pc300dev_t *); + +static int ch_config(pc300dev_t *); 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); +static int rx_config(pc300dev_t *); +static inline void show_version(void); +static int tx_config(pc300dev_t *); -#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); -void cpc_tty_reset_var(void); -#endif +static int cpc_attach(struct net_device *, unsigned short, unsigned short); +static int cpc_change_mtu(struct net_device *, int); +static void __exit cpc_cleanup_module(void); +static void cpc_closech(pc300dev_t *); +static int cpc_close(struct net_device *); +static void cpc_falc_status(pc300_t *, int); +static struct net_device_stats *cpc_get_stats(struct net_device *); +static void cpc_hw_info_to_user(const pc300hw_t *, struct pc300hw_user *); +static void cpc_init_card(pc300_t *); +static int __devinit cpc_init_one(struct pci_dev *, + const struct pci_device_id *); +static int __init cpc_init(void); +static irqreturn_t cpc_intr(int, void *); +static int cpc_ioctl(struct net_device *, struct ifreq *, int); +static void cpc_net_rx(struct net_device *); +static void cpc_net_stats_to_user(const struct net_device_stats *, + struct pc300_net_stats *); +static int cpc_opench(pc300dev_t *); +static int cpc_queue_xmit(struct sk_buff *, struct net_device *); +static void __devexit cpc_remove_one(struct pci_dev *); +static void cpc_sca_status(pc300_t *, int); +static void cpc_trace(struct net_device *, struct sk_buff *, char); +static void cpc_tx_timeout(struct net_device *); + +static const struct net_device_ops pc300_netdev_ops = { + .ndo_change_mtu = cpc_change_mtu, + .ndo_do_ioctl = cpc_ioctl, + .ndo_get_stats = cpc_get_stats, + .ndo_open = cpc_open, + .ndo_set_mac_address = NULL, + .ndo_start_xmit = cpc_queue_xmit, + .ndo_stop = cpc_close, + .ndo_tx_timeout = cpc_tx_timeout, + .ndo_validate_addr = NULL +}; /************************/ /*** DMA Routines ***/ /************************/ -static void tx_dma_buf_pt_init(pc300_t * card, int ch) +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)); + 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))); + (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)); + (u32)(DMA_TX_BASE + + (ch_factor + i) * BD_DEF_LEN)); } } -static void tx_dma_buf_init(pc300_t * card, int ch) +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)); + 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)); @@ -335,27 +419,30 @@ static void tx_dma_buf_init(pc300_t * card, int ch) tx_dma_buf_pt_init(card, ch); } -static void rx_dma_buf_pt_init(pc300_t * card, int 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)); + 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))); + (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)); + (u32)(DMA_RX_BASE + + (ch_factor + i) * BD_DEF_LEN)); } } -static void rx_dma_buf_init(pc300_t * card, int ch) +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)); + 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)); @@ -365,88 +452,129 @@ static void rx_dma_buf_init(pc300_t * card, int ch) rx_dma_buf_pt_init(card, ch); } -static void tx_dma_buf_check(pc300_t * card, int ch) +static void tx_dma_buf_check(pc300_t *card, int ch) { - volatile pcsca_bd_t __iomem *ptdescr; + 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(KERN_DEBUG "#CH%d: f_bd = %d(0x%08x), n_bd = %d(0x%08x)\n", ch, + first_bd, (u32)TX_BD_ADDR(ch, first_bd), + next_bd, (u32)TX_BD_ADDR(ch, next_bd)); + for ( + i = first_bd, + ptdescr = (pcsca_bd_t *) + (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 = (pcsca_bd_t *) + (card->hw.rambase + TX_BD_ADDR(ch, i)) + ) { + printk(KERN_DEBUG + "\n CH%d TX%d: next=0x%08x, ptbuf=0x%08x, ST=0x%2x, len=%d", + ch, i, (u32) cpc_readl(&ptdescr->next), + (u32) cpc_readl(&ptdescr->ptbuf), + cpc_readb(&ptdescr->status), cpc_readw(&ptdescr->len)); } - printk("\n"); + printk(KERN_DEBUG "\n"); } #ifdef PC300_DEBUG_OTHER /* Show all TX buffer descriptors */ -static void tx1_dma_buf_check(pc300_t * card, int ch) +static void tx1_dma_buf_check(pc300_t *card, int ch) { - volatile pcsca_bd_t __iomem *ptdescr; + 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))); + uintptr_t scabase = (uintptr_t)(card->hw.scabase); + + printk(KERN_DEBUG + "\nnfree_tx_bd = %d\n", card->chan[ch].nfree_tx_bd); + printk(KERN_DEBUG + "#CH%d: f_bd = %d(0x%08x), n_bd = %d(0x%08x)\n", ch, + first_bd, (u32)TX_BD_ADDR(ch, first_bd), + next_bd, (u32)TX_BD_ADDR(ch, next_bd)); + printk(KERN_DEBUG + "TX_CDA=0x%08x, TX_EDA=0x%08x\n", + (u32)(cpc_readl(scabase + DTX_REG(CDAL, ch))), + (u32)(cpc_readl(scabase + DTX_REG(EDAL, ch)))); + printk(KERN_DEBUG + "TX_CDA(BH/B/H/L) = %02x %02x %02x %02x\n", + (u8) cpc_readb(scabase + DTX_REG(CDABH, ch)), + (u8) cpc_readb(scabase + DTX_REG(CDAB, ch)), + (u8) cpc_readb(scabase + DTX_REG(CDAH, ch)), + (u8) cpc_readb(scabase + DTX_REG(CDAL, ch))); + printk(KERN_DEBUG + "TX_EDA(BH/B/H/L) = %02x %02x %02x %02x\n", + (u8) cpc_readb(scabase + DTX_REG(EDABH, ch)), + (u8) cpc_readb(scabase + DTX_REG(EDAB, ch)), + (u8) cpc_readb(scabase + DTX_REG(EDAH, ch)), + (u8) cpc_readb(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(KERN_DEBUG + "\n CH%d TX%d: next=0x%x, ptbuf=0x%x, ST=0x%x, len=%d", + ch, i, (u32) cpc_readl(&ptdescr->next), + (u32) cpc_readl(&ptdescr->ptbuf), + cpc_readb(&ptdescr->status), + cpc_readw(&ptdescr->len)); + printk(KERN_DEBUG + "\n CH%d TX%d: next=0x%02x%02x%02x%02x (endianess-correct)", + ch, i, + cpc_readb((unsigned char *)(&(ptdescr->next))+0x3), + cpc_readb((unsigned char *)(&(ptdescr->next))+0x2), + cpc_readb((unsigned char *)(&(ptdescr->next))+0x1), + cpc_readb((unsigned char *)(&(ptdescr->next))+0x0)); } - printk("\n"); + printk(KERN_DEBUG "\n"); } #endif -static void rx_dma_buf_check(pc300_t * card, int ch) +static void rx_dma_buf_check(pc300_t *card, int ch) { - volatile pcsca_bd_t __iomem *ptdescr; + 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++) { + printk(KERN_DEBUG + "#CH%d: f_bd = %d, l_bd = %d\n", ch, first_bd, last_bd); + for ( + i = 0, + ptdescr = (pcsca_bd_t *) + (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(KERN_DEBUG + "\n CH%d RX%d: next=0x%08x, ptbuf=0x%08x, ST=0x%2x, len=%d", + ch, i, (u32) cpc_readl(&ptdescr->next), + (u32) cpc_readl(&ptdescr->ptbuf), + cpc_readb(&ptdescr->status), + cpc_readw(&ptdescr->len)); } - printk("\n"); + printk(KERN_DEBUG "\n"); } -static int dma_get_rx_frame_size(pc300_t * card, int ch) +static int dma_get_rx_frame_size(pc300_t *card, int ch) { - volatile pcsca_bd_t __iomem *ptdescr; + pcsca_bd_t __iomem *ptdescr; u16 first_bd = card->chan[ch].rx_first_bd; int rcvd = 0; - volatile u8 status; + u8 status; - ptdescr = (card->hw.rambase + RX_BD_ADDR(ch, first_bd)); + ptdescr = (pcsca_bd_t *)(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); @@ -455,8 +583,11 @@ static int dma_get_rx_frame_size(pc300_t * card, int ch) * (dma_buf_read will clean the buffer descriptors in this case). */ return rcvd; } - ptdescr = (card->hw.rambase + cpc_readl(&ptdescr->next)); + ptdescr = (pcsca_bd_t *) + (card->hw.rambase + + cpc_readl(&ptdescr->next)); } + return -1; } @@ -467,7 +598,7 @@ static int dma_get_rx_frame_size(pc300_t * card, int ch) static int dma_buf_write(pc300_t *card, int ch, u8 *ptdata, int len) { int i, nchar; - volatile pcsca_bd_t __iomem *ptdescr; + pcsca_bd_t __iomem *ptdescr; int tosend = len; u8 nbuf = ((len - 1) / BD_DEF_LEN) + 1; @@ -476,11 +607,12 @@ static int dma_buf_write(pc300_t *card, int ch, u8 *ptdata, int len) } for (i = 0; i < nbuf; i++) { - ptdescr = (card->hw.rambase + + ptdescr = (pcsca_bd_t *) (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)), + memcpy_toio((card->hw.rambase + + cpc_readl(&ptdescr->ptbuf)), &ptdata[len - tosend], nchar); cpc_writew(&ptdescr->len, nchar); card->chan[ch].nfree_tx_bd--; @@ -495,7 +627,8 @@ static int dma_buf_write(pc300_t *card, int ch, u8 *ptdata, int len) } tosend -= nchar; card->chan[ch].tx_next_bd = - (card->chan[ch].tx_next_bd + 1) & (N_DMA_TX_BUF - 1); + (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; @@ -505,20 +638,22 @@ static int dma_buf_write(pc300_t *card, int ch, u8 *ptdata, int len) * 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) +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; + pcsca_bd_t __iomem *ptdescr; int rcvd = 0; - volatile u8 status; + u8 status; - ptdescr = (card->hw.rambase + + ptdescr = (pcsca_bd_t *)(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 ((status & + (DST_OVR | DST_CRC | DST_RBIT | + DST_SHRT | DST_ABT)) + || (nchar > BD_DEF_LEN)) { if (nchar > BD_DEF_LEN) status |= DST_RBIT; @@ -529,7 +664,7 @@ static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) chan->rx_first_bd = (chan->rx_first_bd+1) & (N_DMA_RX_BUF-1); if (status & DST_EOM) break; - ptdescr = (card->hw.rambase + + ptdescr = (pcsca_bd_t *) (card->hw.rambase + cpc_readl(&ptdescr->next)); status = cpc_readb(&ptdescr->status); } @@ -538,23 +673,29 @@ static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) if (nchar != 0) { if (skb) { memcpy_fromio(skb_put(skb, nchar), - (card->hw.rambase+cpc_readl(&ptdescr->ptbuf)),nchar); + (void *)(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); + 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)); + ptdescr = (pcsca_bd_t *) + (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); + 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)); @@ -562,9 +703,9 @@ static int dma_buf_read(pc300_t * card, int ch, struct sk_buff *skb) return rcvd; } -static void tx_dma_stop(pc300_t * card, int ch) +static void tx_dma_stop(pc300_t *card, int ch) { - void __iomem *scabase = card->hw.scabase; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); u8 drr_ena_bit = 1 << (5 + 2 * ch); u8 drr_rst_bit = 1 << (1 + 2 * ch); @@ -573,9 +714,9 @@ static void tx_dma_stop(pc300_t * card, int ch) cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit); } -static void rx_dma_stop(pc300_t * card, int ch) +static void rx_dma_stop(pc300_t *card, int ch) { - void __iomem *scabase = card->hw.scabase; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); u8 drr_ena_bit = 1 << (4 + 2 * ch); u8 drr_rst_bit = 1 << (2 * ch); @@ -584,9 +725,9 @@ static void rx_dma_stop(pc300_t * card, int ch) cpc_writeb(scabase + DRR, drr_rst_bit & ~drr_ena_bit); } -static void rx_dma_start(pc300_t * card, int ch) +static void rx_dma_start(pc300_t *card, int ch) { - void __iomem *scabase = card->hw.scabase; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; /* Start DMA */ @@ -602,7 +743,7 @@ static void rx_dma_start(pc300_t * card, int ch) 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); + cpc_writeb(scabase + DSR_RX(ch), DSR_DE); } } @@ -611,25 +752,26 @@ static void rx_dma_start(pc300_t * card, int ch) /*************************/ static void falc_issue_cmd(pc300_t *card, int ch, u8 cmd) { - void __iomem *falcbase = card->hw.falcbase; + uintptr_t falcbase = (uintptr_t)(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); + printk(KERN_ERR + "%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) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); /* Interrupt pins are open-drain */ cpc_writeb(falcbase + F_REG(IPC, ch), @@ -674,9 +816,9 @@ static void falc_intr_enable(pc300_t * card, int ch) } } -static void falc_open_timeslot(pc300_t * card, int ch, int timeslot) +static void falc_open_timeslot(pc300_t *card, int ch, int timeslot) { - void __iomem *falcbase = card->hw.falcbase; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); u8 tshf = card->chan[ch].falc.offset; cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch), @@ -690,9 +832,9 @@ static void falc_open_timeslot(pc300_t * card, int ch, int timeslot) (0x80 >> (timeslot & 0x07))); } -static void falc_close_timeslot(pc300_t * card, int ch, int timeslot) +static void falc_close_timeslot(pc300_t *card, int ch, int timeslot) { - void __iomem *falcbase = card->hw.falcbase; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); u8 tshf = card->chan[ch].falc.offset; cpc_writeb(falcbase + F_REG((ICB1 + (timeslot - tshf) / 8), ch), @@ -706,11 +848,11 @@ static void falc_close_timeslot(pc300_t * card, int ch, int timeslot) ~(0x80 >> (timeslot & 0x07))); } -static void falc_close_all_timeslots(pc300_t * card, int ch) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); cpc_writeb(falcbase + F_REG(ICB1, ch), 0xff); cpc_writeb(falcbase + F_REG(TTR1, ch), 0); @@ -728,11 +870,11 @@ static void falc_close_all_timeslots(pc300_t * card, int ch) } } -static void falc_open_all_timeslots(pc300_t * card, int ch) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); cpc_writeb(falcbase + F_REG(ICB1, ch), 0); if (conf->fr_mode == PC300_FR_UNFRAMED) { @@ -760,7 +902,7 @@ static void falc_open_all_timeslots(pc300_t * card, int ch) } } -static void falc_init_timeslot(pc300_t * card, int ch) +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; @@ -778,7 +920,7 @@ static void falc_init_timeslot(pc300_t * card, int ch) } } -static void falc_enable_comm(pc300_t * card, int ch) +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; @@ -794,7 +936,7 @@ static void falc_enable_comm(pc300_t * card, int ch) ~((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch))); } -static void falc_disable_comm(pc300_t * card, int 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; @@ -808,12 +950,12 @@ static void falc_disable_comm(pc300_t * card, int ch) ((CPLD_REG1_FALC_DCD | CPLD_REG1_FALC_CTS) << (2 * ch))); } -static void falc_init_t1(pc300_t * card, int 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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); u8 dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0); /* Switch to T1 mode (PCM 24) */ @@ -977,12 +1119,12 @@ static void falc_init_t1(pc300_t * card, int ch) falc_close_all_timeslots(card, ch); } -static void falc_init_e1(pc300_t * card, int 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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); u8 dja = (ch ? (LIM2_DJA2 | LIM2_DJA1) : 0); /* Switch to E1 mode (PCM 30) */ @@ -1157,9 +1299,9 @@ static void falc_init_e1(pc300_t * card, int ch) falc_close_all_timeslots(card, ch); } -static void falc_init_hdlc(pc300_t * card, int ch) +static void falc_init_hdlc(pc300_t *card, int ch) { - void __iomem *falcbase = card->hw.falcbase; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); pc300ch_t *chan = (pc300ch_t *) & card->chan[ch]; pc300chconf_t *conf = (pc300chconf_t *) & chan->conf; @@ -1183,12 +1325,12 @@ static void falc_init_hdlc(pc300_t * card, int ch) falc_intr_enable(card, ch); } -static void te_config(pc300_t * card, int 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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); u8 dummy; unsigned long flags; @@ -1243,12 +1385,12 @@ static void te_config(pc300_t * card, int ch) CPC_UNLOCK(card, flags); } -static void falc_check_status(pc300_t * card, int ch, unsigned char frs0) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); /* Verify LOS */ if (frs0 & FRS0_LOS) { @@ -1399,12 +1541,12 @@ static void falc_check_status(pc300_t * card, int ch, unsigned char frs0) } } -static void falc_update_stats(pc300_t * card, int ch) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); u16 counter; counter = cpc_readb(falcbase + F_REG(FECL, ch)); @@ -1451,12 +1593,12 @@ static void falc_update_stats(pc300_t * card, int ch) * the synchronizer and then sent to the system interface. *---------------------------------------------------------------------------- */ -static void falc_remote_loop(pc300_t * card, int ch, int loop_on) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (loop_on) { // EVENT_FALC_ABNORMAL @@ -1496,11 +1638,11 @@ static void falc_remote_loop(pc300_t * card, int ch, int loop_on) * coding must be identical. *---------------------------------------------------------------------------- */ -static void falc_local_loop(pc300_t * card, int ch, int loop_on) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (loop_on) { cpc_writeb(falcbase + F_REG(LIM0, ch), @@ -1523,12 +1665,12 @@ static void falc_local_loop(pc300_t * card, int ch, int loop_on) * looped. They are originated by the FALC-LH transmitter. *---------------------------------------------------------------------------- */ -static void falc_payload_loop(pc300_t * card, int ch, int loop_on) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (loop_on) { // EVENT_FALC_ABNORMAL @@ -1577,11 +1719,11 @@ static void falc_payload_loop(pc300_t * card, int ch, int loop_on) * Description: Turns XLU bit off in the proper register *---------------------------------------------------------------------------- */ -static void turn_off_xlu(pc300_t * card, int ch) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), @@ -1598,11 +1740,11 @@ static void turn_off_xlu(pc300_t * card, int ch) * Description: Turns XLD bit off in the proper register *---------------------------------------------------------------------------- */ -static void turn_off_xld(pc300_t * card, int ch) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), @@ -1620,12 +1762,12 @@ static void turn_off_xld(pc300_t * card, int ch) * to generate a LOOP activation code over a T1/E1 line. *---------------------------------------------------------------------------- */ -static void falc_generate_loop_up_code(pc300_t * card, int ch) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), @@ -1653,12 +1795,12 @@ static void falc_generate_loop_up_code(pc300_t * card, int ch) * to generate a LOOP deactivation code over a T1/E1 line. *---------------------------------------------------------------------------- */ -static void falc_generate_loop_down_code(pc300_t * card, int ch) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (conf->media == IF_IFACE_T1) { cpc_writeb(falcbase + F_REG(FMR5, ch), @@ -1683,12 +1825,12 @@ static void falc_generate_loop_down_code(pc300_t * card, int ch) * it on the reception side. *---------------------------------------------------------------------------- */ -static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (activate) { pfalc->prbs = 1; @@ -1730,7 +1872,7 @@ static void falc_pattern_test(pc300_t * card, int ch, unsigned int activate) * Description: This routine returns the bit error counter value *---------------------------------------------------------------------------- */ -static u16 falc_pattern_test_error(pc300_t * card, int ch) +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; @@ -1748,7 +1890,9 @@ 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); + printk(KERN_ERR + "%s: out of memory\n", + dev->name); return; } skb_put(skb, 10 + skb_main->len); @@ -1775,15 +1919,24 @@ 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; + struct net_device_stats *stats = &(dev->stats); int ch = chan->channel; unsigned long flags; u8 ilar; - dev->stats.tx_errors++; - dev->stats.tx_aborted_errors++; +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG "cpc_tx_timeout()\n"); + cpc_sca_status(card, ch); +#endif + stats->tx_errors++; + 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); +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "%s: ILAR=0x%x\n", + dev->name, ilar); +#endif cpc_writeb(card->hw.scabase + ILAR, ilar); cpc_writeb(card->hw.scabase + DMER, 0x80); } @@ -1792,8 +1945,13 @@ static void cpc_tx_timeout(struct net_device *dev) cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) & ~(CPLD_REG2_FALC_LED1 << (2 * ch))); } - dev->trans_start = jiffies; /* prevent tx timeout */ + dev->trans_start = jiffies; CPC_UNLOCK(card, flags); +#ifdef PC300_DEBUG_QUEUE + printk(KERN_DEBUG + "%s: waking queue, finished cpc_tx_timeout()\n", + dev->name); +#endif netif_wake_queue(dev); } @@ -1802,22 +1960,83 @@ 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; + struct net_device_stats *stats = &(dev->stats); int ch = chan->channel; unsigned long flags; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); #ifdef PC300_DEBUG_TX int i; #endif - if (!netif_carrier_ok(dev)) { +#ifdef PC300_DEBUG_TX + printk(KERN_DEBUG + "%s: cpc_queue_xmit called wih %d bytes\n", + dev->name, skb->len); +#endif + if (cpc_readb(scabase + M_REG(ST3, ch)) & ST3_DCD) { + if (netif_carrier_ok(dev)) { + printk(KERN_INFO + "%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 */ + if (!netif_carrier_ok(dev)) { + printk(KERN_INFO + "%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 */ + netif_carrier_on(dev); + } +#else + netif_carrier_on(dev); +#endif + card->chan[ch].d.line_on++; + } + } + + if (chan->conf.monitor) { + /* In monitor mode no Tx is done: ignore packet */ + dev_kfree_skb(skb); +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "%s: dropping TX packet because in monitor mode\n", + dev->name); +#endif + return 0; + } else if (!netif_carrier_ok(dev)) { /* DCD must be OFF: drop packet */ dev_kfree_skb(skb); - dev->stats.tx_errors++; - dev->stats.tx_carrier_errors++; + stats->tx_errors++; + stats->tx_carrier_errors++; +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "%s: TX carrier error; dropping silently\n", + dev->name); +#endif 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++; + } else if ( + cpc_readb(card->hw.scabase + + M_REG(ST3, ch)) & + ST3_DCD) { + printk(KERN_INFO + "%s: DCD is OFF. Going administrative down.\n", + dev->name); + stats->tx_errors++; + stats->tx_carrier_errors++; +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "%s: TX carrier error; dropping silently\n", + dev->name); +#endif dev_kfree_skb(skb); netif_carrier_off(dev); CPC_LOCK(card, flags); @@ -1828,24 +2047,43 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev) ~(CPLD_REG2_FALC_LED1 << (2 * ch))); } CPC_UNLOCK(card, flags); +#ifdef PC300_DEBUG_QUEUE + printk(KERN_DEBUG + "%s: waking queue after TX carrier error\n", + dev->name); +#endif netif_wake_queue(dev); return 0; } + CPC_LOCK(card, flags); /* 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); + if (dma_buf_write( + card, ch, + (u8 *) skb->data, + skb->len) != 0) { + CPC_UNLOCK(card, flags); + printk(KERN_ERR + "%s: write error. Dropping TX packet.\n", + dev->name); +#ifdef PC300_DEBUG_QUEUE + printk(KERN_DEBUG + "%s: stopping queue due to DMA error\n", + dev->name); +#endif + d->reason_stopped = CPC_DMA_ERROR; netif_stop_queue(dev); dev_kfree_skb(skb); - dev->stats.tx_errors++; - dev->stats.tx_dropped++; + stats->tx_errors++; + stats->tx_dropped++; return 0; - } + } else + CPC_UNLOCK(card, flags); #ifdef PC300_DEBUG_TX - printk("%s T:", dev->name); + printk(KERN_DEBUG "%s T:", dev->name); for (i = 0; i < skb->len; i++) - printk(" %02x", *(skb->data + i)); - printk("\n"); + printk(KERN_DEBUG " %02x", *(skb->data + i)); + printk(KERN_DEBUG "\n"); #endif if (d->trace_on) { @@ -1854,11 +2092,12 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev) /* 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); - } +#ifdef PC300_DEBUG_QUEUE + printk(KERN_DEBUG + "%s: stopping queue for transmission\n", + dev->name); +#endif + 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); @@ -1868,9 +2107,24 @@ static int cpc_queue_xmit(struct sk_buff *skb, struct net_device *dev) cpc_readb(card->hw.falcbase + card->hw.cpld_reg2) | (CPLD_REG2_FALC_LED1 << (2 * ch))); } + /* verify if it has more than one free descriptor */ + if (card->chan[ch].nfree_tx_bd > 1) { +#ifdef PC300_DEBUG_QUEUE + printk(KERN_DEBUG + "%s: restarting queue\n", + dev->name); +#endif + netif_wake_queue(dev); + } CPC_UNLOCK(card, flags); dev_kfree_skb(skb); +#ifdef PC300_DEBUG_TX + printk(KERN_DEBUG + "%s: cpc_queue_xmit returning normally\n", + dev->name); +#endif + return 0; } @@ -1879,29 +2133,45 @@ 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; + struct net_device_stats *stats = &(dev->stats); int ch = chan->channel; #ifdef PC300_DEBUG_RX int i; #endif int rxb; struct sk_buff *skb; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); while (1) { if ((rxb = dma_get_rx_frame_size(card, ch)) == -1) return; if (!netif_carrier_ok(dev)) { + if (!(cpc_readb(scabase + M_REG(ST3, ch)) & ST3_DCD)) { + printk(KERN_INFO + "%s: DCD ON - going up\n", + dev->name); + netif_carrier_on(dev); + } + } + if (!netif_carrier_ok(dev)) { /* DCD must be OFF: drop packet */ - printk("%s : DCD is OFF - drop %d rx bytes\n", dev->name, rxb); + printk(KERN_INFO + "%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); + printk(KERN_ERR + "%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); + printk(KERN_ERR + "%s: Memory squeeze!!\n", + dev->name); return; } skb->dev = dev; @@ -1910,28 +2180,30 @@ static void cpc_net_rx(struct net_device *dev) if (((rxb = dma_buf_read(card, ch, skb)) <= 0) || (skb == NULL)) { #ifdef PC300_DEBUG_RX - printk("%s: rxb = %x\n", dev->name, rxb); + printk(KERN_DEBUG + "%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++; + stats->rx_errors++; + 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++; + stats->rx_errors++; + stats->rx_fifo_errors++; } if (rxb & DST_CRC) { - dev->stats.rx_errors++; - dev->stats.rx_crc_errors++; + stats->rx_errors++; + stats->rx_crc_errors++; } if (rxb & (DST_RBIT | DST_SHRT | DST_ABT)) { - dev->stats.rx_errors++; - dev->stats.rx_frame_errors++; + stats->rx_errors++; + stats->rx_frame_errors++; } } if (skb) { @@ -1940,18 +2212,19 @@ static void cpc_net_rx(struct net_device *dev) continue; } - dev->stats.rx_bytes += rxb; + stats->rx_bytes += rxb; #ifdef PC300_DEBUG_RX - printk("%s R:", dev->name); + printk(KERN_DEBUG "%s R:", dev->name); for (i = 0; i < skb->len; i++) - printk(" %02x", *(skb->data + i)); - printk("\n"); + printk(KERN_DEBUG " %02x", *(skb->data + i)); + printk(KERN_DEBUG "\n"); #endif if (d->trace_on) { cpc_trace(dev, skb, 'R'); } - dev->stats.rx_packets++; + stats->rx_packets++; + skb_reset_mac_header(skb); skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); } @@ -1964,23 +2237,28 @@ 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; + int ch = chan->channel; + pcsca_bd_t *ptdescr; + struct net_device_stats *stats = &(dev->netdev->stats); /* 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); + ptdescr = (pcsca_bd_t *) + (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) + ) { + stats->tx_packets++; + 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)); - } + ptdescr = (pcsca_bd_t *)(card->hw.rambase + + TX_BD_ADDR(ch, chan->tx_first_bd)); + } #ifdef CONFIG_PC300_MLPPP if (chan->conf.proto == PC300_PROTO_MLPPP) { @@ -1988,38 +2266,48 @@ static void sca_tx_intr(pc300dev_t *dev) } else { #endif /* Tell the upper layer we are ready to transmit more packets */ - netif_wake_queue(dev->dev); +#ifdef PC300_DEBUG_QUEUE + printk(KERN_DEBUG "Waking queue on TX interrupt\n"); +#endif + if (chan->nfree_tx_bd > 1 && + netif_queue_stopped(dev->netdev)) + netif_wake_queue(dev->netdev); #ifdef CONFIG_PC300_MLPPP } #endif } -static void sca_intr(pc300_t * card) +static void sca_intr(pc300_t *card) { - void __iomem *scabase = card->hw.scabase; - volatile u32 status; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); + u32 status; int ch; int intr_count = 0; unsigned char dsr_rx; while ((status = cpc_readl(scabase + ISR0)) != 0) { +#ifdef PC300_DEBUG_INTR + printk(KERN_DEBUG "sca_intr(): status = %08x\n", + status); +#endif 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; + struct net_device *dev = d->netdev; spin_lock(&card->card_lock); /**** Reception ****/ if (status & IR0_DRX((IR0_DMIA | IR0_DMIB), ch)) { - u8 drx_stat = cpc_readb(scabase + DSR_RX(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); + printk(KERN_DEBUG "sca_intr: RX intr chan[%d] (st=0x%08x, dsr=0x%02x)\n", + ch, status, drx_stat); #endif if (status & IR0_DRX(IR0_DMIA, ch)) { if (drx_stat & DSR_BOF) { @@ -2039,10 +2327,15 @@ static void sca_intr(pc300_t * card) } 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; + ++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); } } @@ -2077,8 +2370,10 @@ static void sca_intr(pc300_t * card) } 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); + printk(KERN_DEBUG + "%s: RX intr chan[%d] (st=0x%08x, 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); } @@ -2086,14 +2381,15 @@ static void sca_intr(pc300_t * card) /**** Transmission ****/ if (status & IR0_DTX((IR0_EFT | IR0_DMIA | IR0_DMIB), ch)) { - u8 dtx_stat = cpc_readb(scabase + DSR_TX(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); + printk(KERN_DEBUG "sca_intr: TX intr chan[%d] (st=0x%08x, dsr=0x%02x)\n", + ch, status, dtx_stat); #endif if (status & IR0_DTX(IR0_EFT, ch)) { if (dtx_stat & DSR_UDRF) { @@ -2108,8 +2404,17 @@ static void sca_intr(pc300_t * card) } dev->stats.tx_errors++; dev->stats.tx_fifo_errors++; - sca_tx_intr(d); +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "sca_intr(): TX underflow! Dump follows:\n"); + printk(KERN_DEBUG + "DSR_TX was 0x%02x\n", + dtx_stat); + cpc_sca_status(card, ch); +#endif + } + sca_tx_intr(d); } if (status & IR0_DTX(IR0_DMIA, ch)) { if (dtx_stat & DSR_BOF) { @@ -2123,26 +2428,28 @@ static void sca_intr(pc300_t * card) card->hw.cpld_reg2) & ~ (CPLD_REG2_FALC_LED1 << (2 * ch))); } - sca_tx_intr(d); } + sca_tx_intr(d); } } /**** MSCI ****/ if (status & IR0_M(IR0_RXINTA, ch)) { - u8 st1 = cpc_readb(scabase + M_REG(ST1, 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); + printk(KERN_DEBUG "sca_intr: MSCI intr chan[%d] (st=0x%08x, 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); + printk(KERN_INFO + "%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); @@ -2153,8 +2460,9 @@ static void sca_intr(pc300_t * card) #endif card->chan[ch].d.line_off++; } else { /* DCD = 1 */ - printk ("%s: DCD is ON. Going administrative up.\n", - dev->name); + printk(KERN_INFO + "%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 */ @@ -2176,7 +2484,7 @@ 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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && !pfalc->loop_gen) { @@ -2201,7 +2509,7 @@ 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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); if (((cpc_readb(falcbase + F_REG(LCR1, ch)) & LCR1_XPRBS) == 0) && !pfalc->loop_gen) { @@ -2222,11 +2530,11 @@ static void falc_e1_loop_detection(pc300_t *card, int ch, u8 rsp) } } -static void falc_t1_intr(pc300_t * card, int ch) +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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); u8 isr0, isr3, gis; u8 dummy; @@ -2269,11 +2577,11 @@ static void falc_t1_intr(pc300_t * card, int ch) } } -static void falc_e1_intr(pc300_t * card, int 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; + uintptr_t falcbase = (uintptr_t)(card->hw.falcbase); u8 isr1, isr2, isr3, gis, rsp; u8 dummy; @@ -2286,8 +2594,8 @@ static void falc_e1_intr(pc300_t * card, int 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 ((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), @@ -2338,7 +2646,7 @@ static void falc_e1_intr(pc300_t * card, int ch) } } -static void falc_intr(pc300_t * card) +static void falc_intr(pc300_t *card) { int ch; @@ -2356,19 +2664,24 @@ static void falc_intr(pc300_t * card) static irqreturn_t cpc_intr(int irq, void *dev_id) { - pc300_t *card = dev_id; - volatile u8 plx_status; + pc300_t *card; + u8 plx_status; - if (!card) { + card = (pc300_t *)dev_id; + if (card == 0) { #ifdef PC300_DEBUG_INTR - printk("cpc_intr: spurious intr %d\n", irq); + printk(KERN_DEBUG + "cpc_intr: spurious intr %d\n", + irq); #endif return IRQ_NONE; /* spurious intr */ } - if (!card->hw.rambase) { + if (card->hw.rambase == 0) { #ifdef PC300_DEBUG_INTR - printk("cpc_intr: spurious intr2 %d\n", irq); + printk(KERN_DEBUG + "cpc_intr: spurious intr2 %d\n", + irq); #endif return IRQ_NONE; /* spurious intr */ } @@ -2394,89 +2707,137 @@ static irqreturn_t cpc_intr(int irq, void *dev_id) return IRQ_HANDLED; } -static void cpc_sca_status(pc300_t * card, int ch) +static void cpc_sca_status(pc300_t *card, int ch) { u8 ilar; - void __iomem *scabase = card->hw.scabase; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); unsigned long flags; + char *reason; + printk(KERN_DEBUG "tx_dma_buf_check():\n"); tx_dma_buf_check(card, ch); +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG "tx1_dma_buf_check():\n"); + tx1_dma_buf_check(card, ch); +#endif + printk(KERN_DEBUG "rx_dma_buf_check():\n"); 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)); + printk(KERN_DEBUG + "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(KERN_DEBUG + "TX_CDA=0x%08x, TX_EDA=0x%08x\n", + (u32) cpc_readl(scabase + DTX_REG(CDAL, ch)), + (u32) cpc_readl(scabase + DTX_REG(EDAL, ch))); + printk(KERN_DEBUG + "RX_CDA=0x%08x, RX_EDA=0x%08x, BFL=0x%04x\n", + (u32) cpc_readl(scabase + DRX_REG(CDAL, ch)), + (u32) cpc_readl(scabase + DRX_REG(EDAL, ch)), + cpc_readw(scabase + DRX_REG(BFLL, ch))); + printk(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "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(KERN_DEBUG + "IER0=0x%08x\n", + (u32) cpc_readl(scabase + IER0)); + switch (card->chan[ch].d.reason_stopped) { + case CPC_DMA_FULL: + reason = "CPC_DMA_FULL"; + break; + case CPC_DMA_ERROR: + reason = "CPC_DMA_ERROR"; + break; + case TRANSMISSION_ACTIVE: + reason = "TRANSMISSION_ACTIVE"; + break; + case CHANNEL_CLOSED: + reason = "CHANNEL_CLOSED"; + break; + default: + reason = "unknown"; + break; + } + printk(KERN_DEBUG "reason_stopped = %s\n", reason); if (ilar != 0) { CPC_LOCK(card, flags); @@ -2486,73 +2847,157 @@ static void cpc_sca_status(pc300_t * card, int ch) } } -static void cpc_falc_status(pc300_t * card, int ch) +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" : "")); + printk(KERN_DEBUG + "CH%d: %s %s %d channels\n", + ch, + (pfalc->sync ? "SYNC" : ""), + (pfalc->active ? "ACTIVE" : ""), + pfalc->num_channels); + + printk(KERN_DEBUG + " pden=%d, los=%d, losr=%d, lfa=%d, farec=%d\n", + pfalc->pden, pfalc->los, + pfalc->losr, pfalc->lfa, + pfalc->farec); + printk(KERN_DEBUG + " lmfa=%d, ais=%d, sec=%d, es=%d, rai=%d\n", + pfalc->lmfa, pfalc->ais, + pfalc->sec, pfalc->es, + pfalc->rai); + printk(KERN_DEBUG + " bec=%d, fec=%d, cvc=%d, cec=%d, ebc=%d\n", + pfalc->bec, pfalc->fec, + pfalc->cvc, pfalc->cec, + pfalc->ebc); + + printk(KERN_DEBUG "\n"); + printk(KERN_DEBUG + " 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) { +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG "%s: change MTU to %d\n", dev->name, new_mtu); +#endif if ((new_mtu < 128) || (new_mtu > PC300_DEF_MTU)) return -EINVAL; dev->mtu = new_mtu; return 0; } +/* Helper function to produce userland version of network stats */ +static void cpc_net_stats_to_user(const struct net_device_stats *stats, + struct pc300_net_stats *user_stats) +{ + user_stats->rx_packets = stats->rx_packets; + user_stats->tx_packets = stats->tx_packets; + user_stats->rx_bytes = stats->rx_bytes; + user_stats->tx_bytes = stats->tx_bytes; + user_stats->rx_errors = stats->rx_errors; + user_stats->tx_errors = stats->tx_errors; + user_stats->rx_dropped = stats->rx_dropped; + user_stats->tx_dropped = stats->tx_dropped; + user_stats->multicast = stats->multicast; + user_stats->collisions = stats->collisions; + user_stats->rx_length_errors = stats->rx_length_errors; + user_stats->rx_over_errors = stats->rx_over_errors; + user_stats->rx_crc_errors = stats->rx_crc_errors; + user_stats->rx_frame_errors = stats->rx_frame_errors; + user_stats->rx_fifo_errors = stats->rx_fifo_errors; + user_stats->rx_missed_errors = stats->rx_missed_errors; + user_stats->tx_aborted_errors = stats->tx_aborted_errors; + user_stats->tx_carrier_errors = stats->tx_carrier_errors; + user_stats->tx_fifo_errors = stats->tx_fifo_errors; + user_stats->tx_heartbeat_errors = stats->tx_heartbeat_errors; + user_stats->tx_window_errors = stats->tx_window_errors; + user_stats->rx_compressed = stats->rx_compressed; + user_stats->tx_compressed = stats->tx_compressed; +} + +/* Helper function to produce userland version of pc300hw struct */ +static void cpc_hw_info_to_user(const pc300hw_t *hw, + struct pc300hw_user *user_hw) +{ + memset(user_hw, 0, sizeof(*user_hw)); + user_hw->type = hw->type; + user_hw->bus = hw->bus; + user_hw->nchan = hw->nchan; + user_hw->irq = hw->irq; + user_hw->clock = hw->clock; + user_hw->cpld_id = hw->cpld_id; + user_hw->cpld_reg1 = hw->cpld_reg1; + user_hw->cpld_reg2 = hw->cpld_reg2; + user_hw->gpioc_reg = hw->gpioc_reg; + user_hw->intctl_reg = hw->intctl_reg; + user_hw->iosize = hw->iosize; + user_hw->plxsize = hw->plxsize; + user_hw->scasize = hw->scasize; + user_hw->alloc_ramsize = hw->alloc_ramsize; + user_hw->ramsize = hw->ramsize; + user_hw->falcsize = hw->falcsize; +} + static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) { - pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv; + 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; + void *arg = (void *) ifr->ifr_data; struct if_settings *settings = &ifr->ifr_settings; - void __iomem *scabase = card->hw.scabase; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); if (!capable(CAP_NET_ADMIN)) return -EPERM; switch (cmd) { case SIOCGPC300CONF: +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "%s: SIOCGPC300CONF called, with conf->monitor = %d\n", + dev->name, conf->monitor); +#endif #ifdef CONFIG_PC300_MLPPP if (conf->proto != PC300_PROTO_MLPPP) { - conf->proto = /* FIXME hdlc->proto.id */ 0; + conf->proto = 0; } #else - conf->proto = /* FIXME hdlc->proto.id */ 0; + conf->proto = 0; #endif memcpy(&conf_aux.conf, conf, sizeof(pc300chconf_t)); - memcpy(&conf_aux.hw, &card->hw, sizeof(pc300hw_t)); + cpc_hw_info_to_user(&card->hw, &conf_aux.hw); if (!arg || copy_to_user(arg, &conf_aux, sizeof(pc300conf_t))) return -EINVAL; +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "%s: SIOCGPC300CONF returning, with conf->monitor = %d\n", + dev->name, conf->monitor); +#endif return 0; case SIOCSPC300CONF: +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "%s: SIOCSPC300CONF called, with conf->monitor = %d\n", + dev->name, conf->monitor); +#endif if (!capable(CAP_NET_ADMIN)) return -EPERM; if (!arg || @@ -2577,12 +3022,15 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } } 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 +#ifdef PC300_DEBUG_OTHER + printk(KERN_DEBUG + "%s: SIOCSPC300CONF returning, with conf->monitor = %d\n", + dev->name, conf->monitor); #endif return 0; case SIOCGPC300STATUS: @@ -2593,28 +3041,45 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 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; + 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; + /* + * Do this instead of passing dev->stats + * out so 32-bit userland on 64-bit + * kernel works. + */ + cpc_net_stats_to_user( + &(dev->stats), + &(pc300stats.net_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; } + return 0; case SIOCGPC300UTILSTATUS: { @@ -2622,27 +3087,52 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) 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; + 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); + !(cpc_readb( + scabase + + M_REG(ST3, ch)) & + ST3_DCD); pc300status.gen_status.cts = - !(cpc_readb (scabase + M_REG(ST3, ch)) & ST3_CTS); + !(cpc_readb( + scabase + + M_REG(ST3, ch)) & + ST3_CTS); pc300status.gen_status.rts = - !(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_RTS); + !(cpc_readb( + scabase + + M_REG(CTL, ch)) & + CTL_RTS); pc300status.gen_status.dtr = - !(cpc_readb (scabase + M_REG(CTL, ch)) & CTL_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))) + copy_to_user( + arg, + &pc300status, + sizeof(pc300status_t) + ) + ) { return -EINVAL; + } return 0; } @@ -2661,8 +3151,11 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) return -EINVAL; if (!arg || - copy_from_user(&pc300loop, arg, sizeof(pc300loopback_t))) + 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); @@ -2712,19 +3205,39 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } if (!arg || - copy_from_user(&pc300patrntst,arg,sizeof(pc300patterntst_t))) + copy_from_user( + &pc300patrntst, + arg, + sizeof( + pc300patrntst + ) + ) + ) { 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; + if (!arg || + copy_to_user( + arg, + &pc300patrntst, + sizeof( + pc300patrntst + ) + )) { + return -EINVAL; + } } else { - falc_pattern_test(card, ch, pc300patrntst.patrntst_on); + falc_pattern_test( + card, + ch, + pc300patrntst. + patrntst_on + ); } return 0; } @@ -2813,6 +3326,16 @@ static int cpc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) } } +static struct net_device_stats *cpc_get_stats(struct net_device *dev) +{ + pc300dev_t *d = (pc300dev_t *) (dev_to_hdlc(dev))->priv; + + if (d) + return &(dev->stats); + else + return NULL; +} + static int clock_rate_calc(u32 rate, u32 clock, int *br_io) { int br, tc; @@ -2842,13 +3365,13 @@ static int clock_rate_calc(u32 rate, u32 clock, int *br_io) } } -static int ch_config(pc300dev_t * d) +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; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); + uintptr_t plxbase = (uintptr_t)(card->hw.plxbase); int ch = chan->channel; u32 clkrate = chan->conf.phys_settings.clock_rate; u32 clktype = chan->conf.phys_settings.clock_type; @@ -2987,24 +3510,27 @@ static int ch_config(pc300dev_t * d) 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); + + /* Was cpc_readl(), changed for unaligned access */ cpc_writeb(scabase + M_REG(IE1, ch), - cpc_readl(scabase + M_REG(IE1, ch)) | IE1_CDCD); + cpc_readb(scabase + M_REG(IE1, ch)) | IE1_CDCD); return 0; } -static int rx_config(pc300dev_t * d) +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; + uintptr_t scabase = (uintptr_t)(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); + cpc_writeb(scabase + M_REG(RNR, ch), 8); + cpc_writeb(scabase + M_REG(RCR, ch), 16); /* Enable reception */ cpc_writeb(scabase + M_REG(CMD, ch), CMD_RX_CRC_INIT); @@ -3024,21 +3550,21 @@ static int rx_config(pc300dev_t * d) return 0; } -static int tx_config(pc300dev_t * d) +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; + uintptr_t scabase = (uintptr_t)(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); + cpc_writeb(scabase + M_REG(TFS, ch), 0x3c); + cpc_writeb(scabase + M_REG(TNR0, ch), 0x38); + cpc_writeb(scabase + M_REG(TNR1, ch), 0x3f); + cpc_writeb(scabase + M_REG(TCR, ch), 0x38); /* Enable transmission */ cpc_writeb(scabase + M_REG(CMD, ch), CMD_TX_CRC_INIT); @@ -3056,9 +3582,11 @@ static int tx_config(pc300dev_t * d) return 0; } -static int cpc_attach(struct net_device *dev, unsigned short encoding, - unsigned short parity) -{ +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; @@ -3087,12 +3615,12 @@ static int cpc_attach(struct net_device *dev, unsigned short encoding, return 0; } -static int cpc_opench(pc300dev_t * d) +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; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); rc = ch_config(d); if (rc) @@ -3109,7 +3637,7 @@ static int cpc_opench(pc300dev_t * d) return 0; } -static void cpc_closech(pc300dev_t * d) +static void cpc_closech(pc300dev_t *d) { pc300ch_t *chan = (pc300ch_t *) d->chan; pc300_t *card = (pc300_t *) chan->card; @@ -3140,15 +3668,18 @@ static void cpc_closech(pc300dev_t * d) int cpc_open(struct net_device *dev) { pc300dev_t *d = (pc300dev_t *) dev_to_hdlc(dev)->priv; + pc300ch_t *chan = (pc300ch_t *) d->chan; + int ch = chan->channel; + pc300_t *card = (pc300_t *) chan->card; struct ifreq ifr; int result; + uintptr_t scabase = (uintptr_t)(card->hw.scabase); #ifdef PC300_DEBUG_OTHER - printk("pc300: cpc_open"); + printk(KERN_DEBUG "pc300: cpc_open\n"); #endif result = hdlc_open(dev); - if (result) return result; @@ -3157,7 +3688,15 @@ int cpc_open(struct net_device *dev) if (result) goto err_out; +#ifdef PC300_DEBUG_QUEUE + printk(KERN_DEBUG "%s: starting queue for open\n", dev->name); +#endif netif_start_queue(dev); + if (cpc_readb(scabase + M_REG(ST3, ch)) & ST3_DCD) + netif_carrier_off(dev); + else + netif_carrier_on(dev); + return 0; err_out: @@ -3173,9 +3712,13 @@ static int cpc_close(struct net_device *dev) unsigned long flags; #ifdef PC300_DEBUG_OTHER - printk("pc300: cpc_close"); + printk(KERN_DEBUG "pc300: cpc_close\n"); +#endif +#ifdef PC300_DEBUG_QUEUE + printk(KERN_DEBUG "%s: stopping queue\n", dev->name); #endif + d->reason_stopped = CHANNEL_CLOSED; netif_stop_queue(dev); CPC_LOCK(card, flags); @@ -3183,7 +3726,6 @@ static int cpc_close(struct net_device *dev) CPC_UNLOCK(card, flags); hdlc_close(dev); - #ifdef CONFIG_PC300_MLPPP if (chan->conf.proto == PC300_PROTO_MLPPP) { cpc_tty_unregister_service(d); @@ -3194,11 +3736,11 @@ static int cpc_close(struct net_device *dev) return 0; } -static u32 detect_ram(pc300_t * card) +static u32 detect_ram(pc300_t *card) { u32 i; u8 data; - void __iomem *rambase = card->hw.rambase; + uintptr_t rambase = (uintptr_t)(card->hw.rambase); card->hw.ramsize = PC300_RAMSIZE; /* Let's find out how much RAM is present on this board */ @@ -3212,9 +3754,10 @@ static u32 detect_ram(pc300_t * card) return i; } -static void plx_init(pc300_t * card) +static void plx_init(pc300_t *card) { - struct RUNTIME_9050 __iomem *plx_ctl = card->hw.plxbase; + struct RUNTIME_9050 __iomem *plx_ctl = + (struct RUNTIME_9050 __iomem *) card->hw.plxbase; /* Reset PLX */ cpc_writel(&plx_ctl->init_ctrl, @@ -3244,20 +3787,11 @@ static inline void show_version(void) rcsdate++; tmp = strrchr(rcsdate, ' '); *tmp = '\0'; - pr_info("Cyclades-PC300 driver %s %s\n", rcsvers, rcsdate); + printk(KERN_INFO "Cyclades-PC300 driver %s %s (built %s %s)\n", + rcsvers, rcsdate, __DATE__, __TIME__); } /* 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) +static void cpc_init_card(pc300_t *card) { int i, devcount = 0; static int board_nbr = 1; @@ -3346,6 +3880,7 @@ static void cpc_init_card(pc300_t * card) break; } chan->conf.proto = IF_PROTO_PPP; + chan->conf.monitor = 0; chan->tx_first_bd = 0; chan->tx_next_bd = 0; chan->rx_first_bd = 0; @@ -3353,6 +3888,7 @@ static void cpc_init_card(pc300_t * card) chan->nfree_tx_bd = N_DMA_TX_BUF; d->chan = chan; + d->tx_skb = NULL; d->trace_on = 0; d->line_on = 0; d->line_off = 0; @@ -3361,47 +3897,67 @@ static void cpc_init_card(pc300_t * card) 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->netdev_ops = &pc300_netdev_ops; dev->watchdog_timeo = PC300_TX_TIMEOUT; + hdlc = dev_to_hdlc(dev); + hdlc->xmit = cpc_queue_xmit; + hdlc->attach = cpc_attach; + d->hdlc = hdlc; + + d->netdev = dev; + d->reason_stopped = CHANNEL_CLOSED; + if (register_hdlc_device(dev) == 0) { - printk("%s: Cyclades-PC300/", dev->name); + printk(KERN_INFO + "%s: Cyclades-PC300/", + dev->name); switch (card->hw.type) { case PC300_TE: if (card->hw.bus == PC300_PMC) { - printk("TE-M"); + printk(KERN_INFO "TE-M"); } else { - printk("TE "); + printk(KERN_INFO "TE "); } break; case PC300_X21: - printk("X21 "); + printk(KERN_INFO "X21 "); break; case PC300_RSV: default: - printk("RSV "); + printk(KERN_INFO "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); +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_INFO " #%d, %dKB of RAM at 0x%016lx, IRQ %d, channel %d.\n", + board_nbr, card->hw.ramsize / 1024, + (unsigned long)(card->hw.ramphys), + card->hw.irq, i + 1); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_INFO " #%d, %dKB of RAM at 0x%08x, IRQ %d, channel %d.\n", + board_nbr, card->hw.ramsize / 1024, + (unsigned int)(card->hw.ramphys), + card->hw.irq, i + 1); +#endif /* CONFIG_PHYS_ADDR_T_64BIT */ + devcount++; } else { - printk ("Dev%d on card(0x%08x): unable to allocate i/f name.\n", - i + 1, card->hw.ramphys); - free_netdev(dev); +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_ERR "Dev %d on card(0x%016lx): unable to allocate i/f name.\n", + i + 1, (unsigned long)(card->hw.ramphys)); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_ERR "Dev %d on card(0x%08x): unable to allocate i/f name.\n", + i + 1, (unsigned int)(card->hw.ramphys)); +#endif /* CONFIG_PHYS_ADDR_T_64BIT */ + *(dev->name) = 0; + kfree(d->hdlc); continue; } } @@ -3414,7 +3970,10 @@ static int __devinit cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { static int first_time = 1; - int err, eeprom_outdated = 0; +#ifdef PC300_DEBUG_PCI + u8 cpc_rev_id; +#endif + int err = 0, eeprom_outdated = 0; u16 device_id; pc300_t *card; @@ -3426,20 +3985,18 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) #endif } - 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; +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_ERR "PC300 found at RAM 0x%016lx, but could not allocate card structure.\n", + (unsigned long)(pci_resource_start(pdev, 3))); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_ERR "PC300 found at RAM 0x%08x, but could not allocate card structure.\n", + (unsigned int)(pci_resource_start(pdev, 3))); +#endif /* CONFIG_PHYS_ADDR_T_64BIT */ + return -ENOMEM; } - err = -ENODEV; - /* read PCI configuration area */ device_id = ent->device; card->hw.irq = pdev->irq; @@ -3453,6 +4010,9 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) card->hw.falcsize = pci_resource_len(pdev, 4); card->hw.plxphys = pci_resource_start(pdev, 5); card->hw.plxsize = pci_resource_len(pdev, 5); +#ifdef PC300_DEBUG_PCI + pci_read_config_byte(pdev, PCI_REVISION_ID, &cpc_rev_id); +#endif switch (device_id) { case PCI_DEVICE_ID_PC300_RX_1: @@ -3469,20 +4029,46 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 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); + printk(KERN_DEBUG + "cpc (bus=0x0%x,pci_id=0x%x,", + pdev->bus->number, pdev->devfn); + printk(KERN_DEBUG + "rev_id=%d) IRQ%d\n", + pdev->revision, card->hw.irq); +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_INFO + "cpc:found ramaddr=0x%016lx plxaddr=0x%016lx " + "ctladdr=0x%016lx falcaddr=0x%016lx\n", + (unsigned long)(card->hw.ramphys), + (unsigned long)(card->hw.plxphys), + (unsigned long)(card->hw.scaphys), + (unsigned long)(card->hw.falcphys)); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_INFO + "cpc:found ramaddr=0x%08x plxaddr=0x%08x " + "ctladdr=0x%08x falcaddr=0x%08x\n", + (unsigned int)(card->hw.ramphys), + (unsigned int)(card->hw.plxphys), + (unsigned int)(card->hw.scaphys), + (unsigned int)(card->hw.falcphys)); +#endif /* CONFIG_PHYS_ADDR_T_64BIT */ #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); +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_ERR + "WARNING: couldn't allocate I/O region for PC300 board " + "at 0x%016lx!\n", + (unsigned long)(card->hw.ramphys)); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_ERR + "WARNING: couldn't allocate I/O region for PC300 board " + "at 0x%08x!\n", + (unsigned int)(card->hw.ramphys)); +#endif } if (card->hw.plxphys) { @@ -3495,29 +4081,63 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (!request_mem_region(card->hw.plxphys, card->hw.plxsize, "PLX Registers")) { - printk("PC300 found at RAM 0x%08x, " +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_ERR + "PC300 found at RAM 0x%016lx, " "but could not allocate PLX mem region.\n", - card->hw.ramphys); + (unsigned long)(card->hw.ramphys)); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_ERR + "PC300 found at RAM 0x%08x, " + "but could not allocate PLX mem region.\n", + (unsigned int)(card->hw.ramphys)); +#endif /* CONFIG_PHYS_ADDR_T_64BIT */ + err = -ENODEV; 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); +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_ERR + "PC300 found at RAM 0x%016lx, " + "but could not allocate SCA mem region.\n", + (unsigned long)(card->hw.ramphys)); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_ERR + "PC300 found at RAM 0x%08x, " + "but could not allocate RAM mem region.\n", + (unsigned int)(card->hw.ramphys)); +#endif /* CONFIG_PHYS_ADDR_T_64BIT */ + err = -ENODEV; goto err_release_plx; } if (!request_mem_region(card->hw.scaphys, card->hw.scasize, "SCA-II Registers")) { - printk("PC300 found at RAM 0x%08x, " +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_ERR + "PC300 found at RAM 0x%016lx, " + "but could not allocate SCA mem region.\n", + (unsigned long)(card->hw.ramphys)); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_ERR + "PC300 found at RAM 0x%08x, " "but could not allocate SCA mem region.\n", - card->hw.ramphys); + (unsigned int)(card->hw.ramphys)); +#endif /* CONFIG_PHYS_ADDR_T_64BIT */ + err = -ENODEV; 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); + err = pci_enable_device(pdev); + if (err != 0) + goto err_release_sca; + + card->hw.plxbase = + (void __iomem *) ioremap(card->hw.plxphys, card->hw.plxsize); + card->hw.rambase = (void __iomem *) ioremap(card->hw.ramphys, + card->hw.alloc_ramsize); + card->hw.scabase = + (void __iomem *) ioremap(card->hw.scaphys, card->hw.scasize); switch (device_id) { case PCI_DEVICE_ID_PC300_TE_1: case PCI_DEVICE_ID_PC300_TE_2: @@ -3525,7 +4145,9 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) 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); + card->hw.falcbase = + (void __iomem *) ioremap(card->hw.falcphys, + card->hw.falcsize); break; case PCI_DEVICE_ID_PC300_RX_1: @@ -3536,10 +4158,23 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } #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); +#ifdef CONFIG_64BIT + printk(KERN_DEBUG + "cpc: relocate ramaddr=0x%016lx plxaddr=0x%016lx " + "ctladdr=0x%016lx falcaddr=0x%016lx\n", + (unsigned long)(card->hw.rambase), + (unsigned long)(card->hw.plxbase), + (unsigned long)(card->hw.scabase), + (unsigned long)(card->hw.falcbase)); +#else /* !CONFIG_64BIT */ + printk(KERN_DEBUG + "cpc: relocate ramaddr=0x%08x plxaddr=0x%08x " + "ctladdr=0x%08x falcaddr=0x%08x\n", + (unsigned int)(card->hw.rambase), + (unsigned int)(card->hw.plxbase), + (unsigned int)(card->hw.scabase), + (unsigned int)(card->hw.falcbase)); +#endif /* CONFIG_64BIT */ #endif /* Set PCI drv pointer to the card structure */ @@ -3584,16 +4219,36 @@ cpc_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) } /* 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); + if ( + request_irq( + card->hw.irq, + cpc_intr, + IRQF_SHARED, + "Cyclades-PC300", + card) + ) { +#ifdef CONFIG_PHYS_ADDR_T_64BIT + printk(KERN_ERR + "PC300 found at RAM 0x%016lx, but could not allocate " + "IRQ%d.\n", (unsigned long)(card->hw.ramphys), + card->hw.irq); +#else /* !CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_ERR + "PC300 found at RAM 0x%08x, but could not allocate " + "IRQ%d.\n", (unsigned int)(card->hw.ramphys), + card->hw.irq); +#endif /* CONFIG_PHYS_ADDR_T_64BIT */ + printk(KERN_ERR + "PC300 found at RAM 0x%08lx, 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"); + printk(KERN_WARNING "WARNING: PC300 with outdated EEPROM.\n"); + return 0; err_io_unmap: @@ -3604,6 +4259,7 @@ err_io_unmap: iounmap(card->hw.falcbase); release_mem_region(card->hw.falcphys, card->hw.falcsize); } +err_release_sca: release_mem_region(card->hw.scaphys, card->hw.scasize); err_release_ram: release_mem_region(card->hw.ramphys, card->hw.alloc_ramsize); @@ -3612,16 +4268,14 @@ err_release_plx: err_release_io: release_region(card->hw.iophys, card->hw.iosize); kfree(card); -err_disable_dev: - pci_disable_device(pdev); - return err; + return -ENODEV; } static void __devexit cpc_remove_one(struct pci_dev *pdev) { pc300_t *card = pci_get_drvdata(pdev); - if (card->hw.rambase) { + if (card->hw.rambase != 0) { int i; /* Disable interrupts on the PCI bridge */ @@ -3629,7 +4283,8 @@ static void __devexit cpc_remove_one(struct pci_dev *pdev) 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); + unregister_hdlc_device(card->chan[i].d.netdev); + free_netdev(card->chan[i].d.netdev); } iounmap(card->hw.plxbase); iounmap(card->hw.scabase); @@ -3642,13 +4297,9 @@ static void __devexit cpc_remove_one(struct pci_dev *pdev) 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); } } diff --git a/drivers/net/wan/pc300_tty.c b/drivers/net/wan/pc300_tty.c index d47d2cd..56a7161 100644 --- a/drivers/net/wan/pc300_tty.c +++ b/drivers/net/wan/pc300_tty.c @@ -3,7 +3,7 @@ * * Author: Regina Kodato <reginak@...lades.com> * - * Copyright: (c) 1999-2002 Cyclades Corp. + * Copyright: (c) 1999-2004 Cyclades Corp. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -50,6 +50,7 @@ #include <linux/tty.h> #include <linux/tty_flip.h> #include <linux/serial.h> +#include <linux/workqueue.h> #include <asm/io.h> #include <asm/uaccess.h> @@ -79,7 +80,7 @@ spin_unlock_irqrestore(&card->card_lock, flags); \ } while (0) -//#define CPC_TTY_DBG(format,a...) printk(format,##a) +/* #define CPC_TTY_DBG(format,a...) printk(KERN_DEBUG format,##a) */ #define CPC_TTY_DBG(format,a...) /* data structures */ @@ -113,13 +114,16 @@ 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; +static int cpc_tty_cnt; /* number of intrfaces configured with MLPPP */ +static int cpc_tty_unreg_flag; /* 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( + 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); @@ -152,11 +156,16 @@ static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char signal) 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); + pc300dev->netdev->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); } /* @@ -170,7 +179,8 @@ static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char signal) unsigned long flags; CPC_TTY_DBG("%s-tty: Set signal %x\n", - pc300dev->dev->name, signal); + pc300dev->netdev->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); @@ -203,22 +213,24 @@ static const struct tty_operations pc300_ops = { */ void cpc_tty_init(pc300dev_t *pc300dev) { - unsigned long port; int aux; - st_cpc_tty_area * cpc_tty; + long port; + st_cpc_tty_area *cpc_tty; /* hdlcX - X=interface number */ - port = pc300dev->dev->name[4] - '0'; + port = pc300dev->netdev->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); + printk(KERN_ERR + "%s-tty: invalid interface selected (0-%i): %li", + pc300dev->netdev->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, + pc300dev->netdev->name, CPC_TTY_MAJOR, CPC_TTY_MINOR_START, CPC_TTY_MINOR_START+CPC_TTY_NPORTS); /* initialize tty driver struct */ @@ -241,11 +253,12 @@ void cpc_tty_init(pc300dev_t *pc300dev) 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); + if (tty_register_driver(&serial_drv)) { + printk(KERN_ERR + "%s-tty: Failed to register serial driver! ", + pc300dev->netdev->name); return; - } + } memset((void *)cpc_tty_area, 0, sizeof(st_cpc_tty_area) * CPC_TTY_NPORTS); @@ -254,8 +267,10 @@ void cpc_tty_init(pc300dev_t *pc300dev) 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); + CPC_TTY_DBG( + "%s-tty: TTY port %i, already in use.\n", + pc300dev->netdev->name, + port); return; } @@ -268,15 +283,15 @@ void cpc_tty_init(pc300dev_t *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; + cpc_tty->buf_rx.first = cpc_tty->buf_rx.last = 0; pc300dev->cpc_tty = (void *)cpc_tty; - aux = strlen(pc300dev->dev->name); - memcpy(cpc_tty->name, pc300dev->dev->name, aux); + aux = strlen(pc300dev->netdev->name); + memcpy(cpc_tty->name, pc300dev->netdev->name, aux); memcpy(&cpc_tty->name[aux], "-tty", 5); - cpc_open(pc300dev->dev); + cpc_open(pc300dev->netdev); cpc_tty_signal_off(pc300dev, CTL_DTR); CPC_TTY_DBG("%s: Initializing TTY Sync Driver, tty major#%d minor#%i\n", @@ -316,9 +331,9 @@ static int cpc_tty_open(struct tty_struct *tty, struct file *flip) } if (cpc_tty->num_open == 0) { /* first open of this tty */ - if (!cpc_tty_area[port].buf_tx){ + if (cpc_tty_area[port].buf_tx == 0) { cpc_tty_area[port].buf_tx = kmalloc(CPC_TTY_MAX_MTU,GFP_KERNEL); - if (!cpc_tty_area[port].buf_tx) { + if (cpc_tty_area[port].buf_tx == 0) { CPC_TTY_DBG("%s: error in memory allocation\n",cpc_tty->name); return -ENOMEM; } @@ -360,7 +375,7 @@ static int cpc_tty_open(struct tty_struct *tty, struct file *flip) static void cpc_tty_close(struct tty_struct *tty, struct file *flip) { - st_cpc_tty_area *cpc_tty; + st_cpc_tty_area *cpc_tty; unsigned long flags; int res; @@ -407,9 +422,9 @@ static void cpc_tty_close(struct tty_struct *tty, struct file *flip) kfree(cpc_tty->buf_tx); cpc_tty->buf_tx = NULL; - CPC_TTY_DBG("%s: TTY closed\n",cpc_tty->name); + CPC_TTY_DBG("%s: TTY closed\n", cpc_tty->name); - if (!serial_drv.refcount && cpc_tty_unreg_flag) { + if (!cpc_tty_cnt && 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))) { @@ -428,14 +443,16 @@ static void cpc_tty_close(struct tty_struct *tty, struct file *flip) * 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) +static int cpc_tty_write(struct tty_struct *tty, + const unsigned char *buf, int count) { - st_cpc_tty_area *cpc_tty; + st_cpc_tty_area *cpc_tty; pc300ch_t *pc300chan; pc300_t *card; int ch; unsigned long flags; struct net_device_stats *stats; + int from_user = 1; if (!tty || !tty->driver_data ) { CPC_TTY_DBG("hdlcX-tty: no TTY in write\n"); @@ -454,10 +471,14 @@ static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int c return -EINVAL; /* frame too big */ } - CPC_TTY_DBG("%s: cpc_tty_write data len=%i\n",cpc_tty->name,count); + CPC_TTY_DBG( + "%s: cpc_tty_write %s data len=%i\n", + cpc_tty->name, + (from_user) ? "from user" : "from kernel", + count); pc300chan = (pc300ch_t *)((pc300dev_t*)cpc_tty->pc300dev)->chan; - stats = &cpc_tty->pc300dev->dev->stats; + stats = &(cpc_tty->pc300dev->netdev->stats); card = (pc300_t *) pc300chan->card; ch = pc300chan->channel; @@ -481,11 +502,35 @@ static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int c 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; + if (from_user) { + unsigned char *buf_tmp; + + buf_tmp = cpc_tty->buf_tx; + if (copy_from_user(buf_tmp, buf, count)) { + /* failed to copy from user */ + CPC_TTY_DBG("%s: error in copy from user\n", + cpc_tty->name); + return -EINVAL; + } + + if (cpc_tty_send_to_card(cpc_tty->pc300dev, + (void *)buf_tmp, count)) { + /* failed to send */ + CPC_TTY_DBG("%s: transmission error\n", cpc_tty->name); + return 0; + } + } else { + if ( + cpc_tty_send_to_card(cpc_tty->pc300dev, + (void *)buf, + count) + ) { + /* failed to send */ + CPC_TTY_DBG("%s: transmission error\n", cpc_tty->name); + return 0; + } } + return count; } @@ -498,7 +543,7 @@ static int cpc_tty_write(struct tty_struct *tty, const unsigned char *buf, int c */ static int cpc_tty_write_room(struct tty_struct *tty) { - st_cpc_tty_area *cpc_tty; + st_cpc_tty_area *cpc_tty; if (!tty || !tty->driver_data ) { CPC_TTY_DBG("hdlcX-tty: no TTY to write room\n"); @@ -525,7 +570,7 @@ static int cpc_tty_write_room(struct tty_struct *tty) */ static int cpc_tty_chars_in_buffer(struct tty_struct *tty) { - st_cpc_tty_area *cpc_tty; + st_cpc_tty_area *cpc_tty; if (!tty || !tty->driver_data ) { CPC_TTY_DBG("hdlcX-tty: no TTY to chars in buffer\n"); @@ -542,10 +587,12 @@ static int cpc_tty_chars_in_buffer(struct tty_struct *tty) return 0; } -static int pc300_tiocmset(struct tty_struct *tty, - unsigned int set, unsigned int clear) +static int pc300_tiocmset( + struct tty_struct *tty, + unsigned int set, + unsigned int clear) { - st_cpc_tty_area *cpc_tty; + st_cpc_tty_area *cpc_tty; CPC_TTY_DBG("%s: set:%x clear:%x\n", __func__, set, clear); @@ -582,8 +629,9 @@ static int pc300_tiocmget(struct tty_struct *tty) cpc_tty = (st_cpc_tty_area *) tty->driver_data; - CPC_TTY_DBG("%s-tty: tiocmget\n", - ((struct net_device*)(pc300dev->hdlc))->name); + CPC_TTY_DBG( + "%s-tty: tiocmget\n", + pc300dev->netdev->name); CPC_TTY_LOCK(card, flags); status = cpc_readb(card->hw.scabase+M_REG(CTL,ch)); @@ -602,7 +650,7 @@ static int pc300_tiocmget(struct tty_struct *tty) */ static void cpc_tty_flush_buffer(struct tty_struct *tty) { - st_cpc_tty_area *cpc_tty; + st_cpc_tty_area *cpc_tty; if (!tty || !tty->driver_data ) { CPC_TTY_DBG("hdlcX-tty: no TTY to flush buffer\n"); @@ -618,9 +666,18 @@ static void cpc_tty_flush_buffer(struct tty_struct *tty) CPC_TTY_DBG("%s: call wake_up_interruptible\n",cpc_tty->name); - tty_wakeup(tty); - return; -} + wake_up_interruptible(&tty->write_wait); + + if ( + (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc && + tty->ldisc->ops && tty->ldisc->ops->write_wakeup + ) { + CPC_TTY_DBG("%s: call line disc. wake up\n", + cpc_tty->name); + tty->ldisc->ops->write_wakeup(tty); + } +} /* * PC300 TTY Hangup routine @@ -631,7 +688,7 @@ static void cpc_tty_flush_buffer(struct tty_struct *tty) static void cpc_tty_hangup(struct tty_struct *tty) { - st_cpc_tty_area *cpc_tty; + st_cpc_tty_area *cpc_tty; int res; if (!tty || !tty->driver_data ) { @@ -645,7 +702,7 @@ static void cpc_tty_hangup(struct tty_struct *tty) CPC_TTY_DBG("%s: TTY is not opened\n",cpc_tty->name); return ; } - if (!serial_drv.refcount && cpc_tty_unreg_flag) { + if (!cpc_tty_cnt && 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))) { @@ -665,35 +722,35 @@ static void cpc_tty_hangup(struct tty_struct *tty) */ 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; + unsigned long port; + st_cpc_tty_area *cpc_tty; + st_cpc_rx_buf *buf; + char flags = 0, flg_rx = 1; if (cpc_tty_cnt == 0) return; - - for (i=0; (i < 4) && flg_rx ; i++) { - flg_rx = 0; + 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++) { + 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); - } - } + buf = cpc_tty->buf_rx.first; + if (buf != NULL) { + if (cpc_tty->tty && cpc_tty->tty->ldisc && + cpc_tty->tty->ldisc->ops && + cpc_tty->tty->ldisc->ops->receive_buf) { + CPC_TTY_DBG( + "%s: call line disc. receive_buf\n", + cpc_tty->name); + cpc_tty->tty-> + ldisc->ops-> + receive_buf(cpc_tty->tty, + (char *)(buf->data), + &flags, buf->size); + } cpc_tty->buf_rx.first = cpc_tty->buf_rx.first->next; kfree((void *)buf); buf = cpc_tty->buf_rx.first; @@ -714,13 +771,13 @@ static void cpc_tty_rx_work(struct work_struct *work) */ 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; + pcsca_bd_t *ptdescr; + 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 + + 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); @@ -731,22 +788,23 @@ static void cpc_tty_rx_disc_frame(pc300ch_t *pc300chan) if (status & DST_EOM) { break; /* end of message */ } - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->next)); + 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; + st_cpc_tty_area *cpc_tty; + pc300ch_t *pc300chan = (pc300ch_t *)pc300dev->chan; + pc300_t *card = (pc300_t *)pc300chan->card; + int ch = pc300chan->channel; + pcsca_bd_t __iomem *ptdescr; + struct net_device_stats *stats = &pc300dev->netdev->stats; + int rx_len, rx_aux; + unsigned char status; unsigned short first_bd = pc300chan->rx_first_bd; - st_cpc_rx_buf *new = NULL; + st_cpc_rx_buf *new; unsigned char dsr_rx; if (pc300dev->cpc_tty == NULL) { @@ -759,14 +817,16 @@ void cpc_tty_receive(pc300dev_t *pc300dev) while (1) { rx_len = 0; - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + RX_BD_ADDR(ch, first_bd)); + 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)); + ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + + cpc_readl(&ptdescr->next)); } if (!rx_len) { @@ -775,7 +835,6 @@ void cpc_tty_receive(pc300dev_t *pc300dev) cpc_writel(card->hw.scabase + DRX_REG(EDAL, ch), RX_BD_ADDR(ch, pc300chan->rx_last_bd)); } - kfree(new); return; } @@ -789,13 +848,13 @@ void cpc_tty_receive(pc300dev_t *pc300dev) } new = kmalloc(rx_len + sizeof(st_cpc_rx_buf), GFP_ATOMIC); - if (!new) { + if (new == 0) { cpc_tty_rx_disc_frame(pc300chan); continue; } /* dma buf read */ - ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + + ptdescr = (pcsca_bd_t __iomem *)(card->hw.rambase + RX_BD_ADDR(ch, pc300chan->rx_first_bd)); rx_len = 0; /* counter frame size */ @@ -821,8 +880,7 @@ void cpc_tty_receive(pc300dev_t *pc300dev) cpc_tty->name); cpc_tty_rx_disc_frame(pc300chan); rx_len = 0; - kfree(new); - new = NULL; + kfree((unsigned char *)new); break; /* read next frame - while(1) */ } @@ -831,15 +889,14 @@ void cpc_tty_receive(pc300dev_t *pc300dev) cpc_tty_rx_disc_frame(pc300chan); stats->rx_dropped++; rx_len = 0; - kfree(new); - new = NULL; + kfree((unsigned char *)new); 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 + + (void __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)), rx_aux); rx_len += rx_aux; } @@ -847,9 +904,10 @@ void cpc_tty_receive(pc300dev_t *pc300dev) cpc_writeb(&ptdescr->len, 0); pc300chan->rx_first_bd = (pc300chan->rx_first_bd + 1) & (N_DMA_RX_BUF -1); - if (status & DST_EOM)break; + if (status & DST_EOM) + break; - ptdescr = (pcsca_bd_t __iomem *) (card->hw.rambase + + ptdescr = (pcsca_bd_t __iomem *) (card->hw.rambase + cpc_readl(&ptdescr->next)); } /* update pointer */ @@ -867,8 +925,8 @@ void cpc_tty_receive(pc300dev_t *pc300dev) cpc_tty_trace(pc300dev, new->data,rx_len, 'R'); } new->size = rx_len; - new->next = NULL; - if (cpc_tty->buf_rx.first == NULL) { + new->next = 0; + if (cpc_tty->buf_rx.first == 0) { cpc_tty->buf_rx.first = new; cpc_tty->buf_rx.last = new; } else { @@ -892,15 +950,29 @@ 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; + 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); + tty = cpc_tty->tty; + if (tty == 0) { + CPC_TTY_DBG("%s: the interface is not opened\n", + cpc_tty->name); return; } - tty_wakeup(tty); + + if ( + (tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && + tty->ldisc && + tty->ldisc->ops && + tty->ldisc->ops->write_wakeup + ) { + CPC_TTY_DBG("%s:call line disc. wakeup\n", + cpc_tty->name); + tty->ldisc->ops->write_wakeup(tty); + } + + wake_up_interruptible(&tty->write_wait); } /* @@ -911,21 +983,23 @@ static void cpc_tty_tx_work(struct work_struct *work) * o write data to DMA buffers * o start the transmission */ -static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len) +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; + struct net_device_stats *stats = &dev->netdev->stats; unsigned long flags; - volatile pcsca_bd_t __iomem *ptdescr; + 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); + CPC_TTY_DBG( + "%s:cpc_tty_send_to_card len=%i", + (st_cpc_tty_area *)dev->cpc_tty->name, + len); if (nbuf >= card->chan[ch].nfree_tx_bd) { return 1; @@ -935,11 +1009,11 @@ static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len) 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 + + 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 + + memcpy_toio((void __iomem *)(card->hw.rambase + cpc_readl(&ptdescr->ptbuf)), &pdata[len - tosend], nchar); @@ -955,7 +1029,7 @@ static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len) CPC_TTY_DBG("%s: error in dma_buf_write\n", (st_cpc_tty_area *)dev->cpc_tty->name); stats->tx_dropped++; - return 1; + return 1; } tosend -= nchar; card->chan[ch].tx_next_bd = @@ -982,7 +1056,7 @@ static int cpc_tty_send_to_card(pc300dev_t *dev,void* buf, int len) (CPLD_REG2_FALC_LED1 << (2 * ch))); } CPC_TTY_UNLOCK(card, flags); - return 0; + return 0; } /* @@ -1000,26 +1074,28 @@ static void cpc_tty_trace(pc300dev_t *dev, char* buf, int len, char rxtx) if ((skb = dev_alloc_skb(10 + len)) == NULL) { /* out of memory */ - CPC_TTY_DBG("%s: tty_trace - out of memory\n", dev->dev->name); + CPC_TTY_DBG( + "%s: tty_trace - out of memory\n", + dev->netdev->name); return; } skb_put (skb, 10 + len); - skb->dev = dev->dev; - skb->protocol = htons(ETH_P_CUST); + skb->dev = dev->netdev; + 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->pkt_type = PACKET_HOST; + skb->len = 10 + len; + + skb_copy_to_linear_data(skb, dev->netdev->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); -} + netif_rx(skb); +} /* * PC300 TTY unregister service routine @@ -1032,38 +1108,40 @@ void cpc_tty_unregister_service(pc300dev_t *pc300dev) 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); + cpc_tty = (st_cpc_tty_area *) pc300dev->cpc_tty; + if (cpc_tty == 0) { + CPC_TTY_DBG( + "%s: interface is not TTY\n", + pc300dev->netdev->name); return; } - CPC_TTY_DBG("%s: cpc_tty_unregister_service", cpc_tty->name); + 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); + CPC_TTY_DBG( + "%s: invalid tty ptr=%s\n", + pc300dev->netdev->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_DBG("%s: unregister the tty driver\n", + cpc_tty->name); + res = tty_unregister_driver(&serial_drv); + if (res) { + 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->tty = NULL; CPC_TTY_UNLOCK(pc300dev->chan->card, flags); - cpc_tty->tty_minor = 0; - cpc_tty->state = CPC_TTY_ST_IDLE; + cpc_tty->tty_minor = 0; + cpc_tty->state = CPC_TTY_ST_IDLE; } /* @@ -1092,6 +1170,7 @@ void cpc_tty_reset_var(void) /* reset the tty_driver structure - serial_drv */ memset(&serial_drv, 0, sizeof(struct tty_driver)); for (i=0; i < CPC_TTY_NPORTS; i++){ - memset(&cpc_tty_area[i],0, sizeof(st_cpc_tty_area)); + memset(&cpc_tty_area[i], 0, + sizeof(st_cpc_tty_area)); } } -- To unsubscribe from this list: send the line "unsubscribe netdev" in the body of a message to majordomo@...r.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Powered by blists - more mailing lists