/*
* linux/drivers/char/synclink.c
*
- * $Id: synclink.c,v 4.21 2004/03/08 15:29:22 paulkf Exp $
+ * $Id: synclink.c,v 4.28 2004/08/11 19:30:01 paulkf Exp $
*
* Device driver for Microgate SyncLink ISA and PCI
* high speed multiprotocol serial adapters.
* OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
#if defined(__i386__)
# define BREAKPOINT() asm(" int $3");
#else
#include <linux/ioport.h>
#include <linux/mm.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <linux/netdevice.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/dma.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
#include <asm/types.h>
#include <linux/termios.h>
#include <linux/workqueue.h>
+#include <linux/hdlc.h>
-#ifdef CONFIG_SYNCLINK_SYNCPPP_MODULE
-#define CONFIG_SYNCLINK_SYNCPPP 1
-#endif
-
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#include <net/syncppp.h>
+#ifdef CONFIG_HDLC_MODULE
+#define CONFIG_HDLC 1
#endif
#define GET_USER(error,value,addr) error = get_user(value,addr)
#define RCLRVALUE 0xffff
-MGSL_PARAMS default_params = {
+static MGSL_PARAMS default_params = {
MGSL_MODE_HDLC, /* unsigned long mode */
0, /* unsigned char loopback; */
HDLC_FLAG_UNDERRUN_ABORT15, /* unsigned short flags; */
*/
struct mgsl_struct {
- void *if_ptr; /* General purpose pointer (used by SPPP) */
int magic;
int flags;
int count; /* count of opens */
int line;
int hw_version;
- unsigned short close_delay;
- unsigned short closing_wait; /* time to wait before closing */
+ unsigned int close_delay;
+ unsigned int closing_wait; /* time to wait before closing */
struct mgsl_icount icount;
struct _input_signal_events input_signal_events;
- /* SPPP/Cisco HDLC device parts */
+ /* generic HDLC device parts */
int netcount;
int dosyncppp;
spinlock_t netlock;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- struct ppp_device pppdev;
- char netname[10];
+
+#ifdef CONFIG_HDLC
struct net_device *netdev;
- struct net_device_stats netstats;
#endif
};
#define usc_EnableReceiver(a,b) \
usc_OutReg( (a), RMR, (u16)((usc_InReg((a),RMR) & 0xfffc) | (b)) )
-u16 usc_InDmaReg( struct mgsl_struct *info, u16 Port );
-void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value );
-void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd );
+static u16 usc_InDmaReg( struct mgsl_struct *info, u16 Port );
+static void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value );
+static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd );
-u16 usc_InReg( struct mgsl_struct *info, u16 Port );
-void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value );
-void usc_RTCmd( struct mgsl_struct *info, u16 Cmd );
+static u16 usc_InReg( struct mgsl_struct *info, u16 Port );
+static void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value );
+static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd );
void usc_RCmd( struct mgsl_struct *info, u16 Cmd );
void usc_TCmd( struct mgsl_struct *info, u16 Cmd );
#define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1))
-void usc_process_rxoverrun_sync( struct mgsl_struct *info );
-void usc_start_receiver( struct mgsl_struct *info );
-void usc_stop_receiver( struct mgsl_struct *info );
+static void usc_process_rxoverrun_sync( struct mgsl_struct *info );
+static void usc_start_receiver( struct mgsl_struct *info );
+static void usc_stop_receiver( struct mgsl_struct *info );
-void usc_start_transmitter( struct mgsl_struct *info );
-void usc_stop_transmitter( struct mgsl_struct *info );
-void usc_set_txidle( struct mgsl_struct *info );
-void usc_load_txfifo( struct mgsl_struct *info );
+static void usc_start_transmitter( struct mgsl_struct *info );
+static void usc_stop_transmitter( struct mgsl_struct *info );
+static void usc_set_txidle( struct mgsl_struct *info );
+static void usc_load_txfifo( struct mgsl_struct *info );
-void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate );
-void usc_enable_loopback( struct mgsl_struct *info, int enable );
+static void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate );
+static void usc_enable_loopback( struct mgsl_struct *info, int enable );
-void usc_get_serial_signals( struct mgsl_struct *info );
-void usc_set_serial_signals( struct mgsl_struct *info );
+static void usc_get_serial_signals( struct mgsl_struct *info );
+static void usc_set_serial_signals( struct mgsl_struct *info );
-void usc_reset( struct mgsl_struct *info );
+static void usc_reset( struct mgsl_struct *info );
-void usc_set_sync_mode( struct mgsl_struct *info );
-void usc_set_sdlc_mode( struct mgsl_struct *info );
-void usc_set_async_mode( struct mgsl_struct *info );
-void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate );
+static void usc_set_sync_mode( struct mgsl_struct *info );
+static void usc_set_sdlc_mode( struct mgsl_struct *info );
+static void usc_set_async_mode( struct mgsl_struct *info );
+static void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate );
-void usc_loopback_frame( struct mgsl_struct *info );
+static void usc_loopback_frame( struct mgsl_struct *info );
-void mgsl_tx_timeout(unsigned long context);
+static void mgsl_tx_timeout(unsigned long context);
-void usc_loopmode_cancel_transmit( struct mgsl_struct * info );
-void usc_loopmode_insert_request( struct mgsl_struct * info );
-int usc_loopmode_active( struct mgsl_struct * info);
-void usc_loopmode_send_done( struct mgsl_struct * info );
-int usc_loopmode_send_active( struct mgsl_struct * info );
+static void usc_loopmode_cancel_transmit( struct mgsl_struct * info );
+static void usc_loopmode_insert_request( struct mgsl_struct * info );
+static int usc_loopmode_active( struct mgsl_struct * info);
+static void usc_loopmode_send_done( struct mgsl_struct * info );
-int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
+static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* SPPP/HDLC stuff */
-static void mgsl_sppp_init(struct mgsl_struct *info);
-static void mgsl_sppp_delete(struct mgsl_struct *info);
-int mgsl_sppp_open(struct net_device *d);
-int mgsl_sppp_close(struct net_device *d);
-void mgsl_sppp_tx_timeout(struct net_device *d);
-int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *d);
-void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size);
-void mgsl_sppp_tx_done(struct mgsl_struct *info);
-int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd);
-struct net_device_stats *mgsl_net_stats(struct net_device *dev);
+#ifdef CONFIG_HDLC
+#define dev_to_port(D) (dev_to_hdlc(D)->priv)
+static void hdlcdev_tx_done(struct mgsl_struct *info);
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
+static int hdlcdev_init(struct mgsl_struct *info);
+static void hdlcdev_exit(struct mgsl_struct *info);
#endif
/*
((Nrdd) << 11) + \
((Nrad) << 6) )
-void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit);
+static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit);
/*
* Adapter diagnostic routines
*/
-BOOLEAN mgsl_register_test( struct mgsl_struct *info );
-BOOLEAN mgsl_irq_test( struct mgsl_struct *info );
-BOOLEAN mgsl_dma_test( struct mgsl_struct *info );
-BOOLEAN mgsl_memory_test( struct mgsl_struct *info );
-int mgsl_adapter_test( struct mgsl_struct *info );
+static BOOLEAN mgsl_register_test( struct mgsl_struct *info );
+static BOOLEAN mgsl_irq_test( struct mgsl_struct *info );
+static BOOLEAN mgsl_dma_test( struct mgsl_struct *info );
+static BOOLEAN mgsl_memory_test( struct mgsl_struct *info );
+static int mgsl_adapter_test( struct mgsl_struct *info );
/*
* device and resource management routines
*/
-int mgsl_claim_resources(struct mgsl_struct *info);
-void mgsl_release_resources(struct mgsl_struct *info);
-void mgsl_add_device(struct mgsl_struct *info);
-struct mgsl_struct* mgsl_allocate_device(void);
-int mgsl_enum_isa_devices(void);
+static int mgsl_claim_resources(struct mgsl_struct *info);
+static void mgsl_release_resources(struct mgsl_struct *info);
+static void mgsl_add_device(struct mgsl_struct *info);
+static struct mgsl_struct* mgsl_allocate_device(void);
/*
* DMA buffer manupulation functions.
*/
-void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
-int mgsl_get_rx_frame( struct mgsl_struct *info );
-int mgsl_get_raw_rx_frame( struct mgsl_struct *info );
-void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
-void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
-int num_free_tx_dma_buffers(struct mgsl_struct *info);
-void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize);
-void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count);
+static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
+static int mgsl_get_rx_frame( struct mgsl_struct *info );
+static int mgsl_get_raw_rx_frame( struct mgsl_struct *info );
+static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
+static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
+static int num_free_tx_dma_buffers(struct mgsl_struct *info);
+static void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize);
+static void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count);
/*
* DMA and Shared Memory buffer allocation and formatting
*/
-int mgsl_allocate_dma_buffers(struct mgsl_struct *info);
-void mgsl_free_dma_buffers(struct mgsl_struct *info);
-int mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
-void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
-int mgsl_alloc_buffer_list_memory(struct mgsl_struct *info);
-void mgsl_free_buffer_list_memory(struct mgsl_struct *info);
-int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
-void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
-int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
-void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
-int load_next_tx_holding_buffer(struct mgsl_struct *info);
-int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
+static int mgsl_allocate_dma_buffers(struct mgsl_struct *info);
+static void mgsl_free_dma_buffers(struct mgsl_struct *info);
+static int mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
+static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
+static int mgsl_alloc_buffer_list_memory(struct mgsl_struct *info);
+static void mgsl_free_buffer_list_memory(struct mgsl_struct *info);
+static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
+static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
+static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
+static int load_next_tx_holding_buffer(struct mgsl_struct *info);
+static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
/*
* Bottom half interrupt handlers
*/
-void mgsl_bh_handler(void* Context);
-void mgsl_bh_receive(struct mgsl_struct *info);
-void mgsl_bh_transmit(struct mgsl_struct *info);
-void mgsl_bh_status(struct mgsl_struct *info);
+static void mgsl_bh_handler(void* Context);
+static void mgsl_bh_receive(struct mgsl_struct *info);
+static void mgsl_bh_transmit(struct mgsl_struct *info);
+static void mgsl_bh_status(struct mgsl_struct *info);
/*
* Interrupt handler routines and dispatch table.
*/
-void mgsl_isr_null( struct mgsl_struct *info );
-void mgsl_isr_transmit_data( struct mgsl_struct *info );
-void mgsl_isr_receive_data( struct mgsl_struct *info );
-void mgsl_isr_receive_status( struct mgsl_struct *info );
-void mgsl_isr_transmit_status( struct mgsl_struct *info );
-void mgsl_isr_io_pin( struct mgsl_struct *info );
-void mgsl_isr_misc( struct mgsl_struct *info );
-void mgsl_isr_receive_dma( struct mgsl_struct *info );
-void mgsl_isr_transmit_dma( struct mgsl_struct *info );
+static void mgsl_isr_null( struct mgsl_struct *info );
+static void mgsl_isr_transmit_data( struct mgsl_struct *info );
+static void mgsl_isr_receive_data( struct mgsl_struct *info );
+static void mgsl_isr_receive_status( struct mgsl_struct *info );
+static void mgsl_isr_transmit_status( struct mgsl_struct *info );
+static void mgsl_isr_io_pin( struct mgsl_struct *info );
+static void mgsl_isr_misc( struct mgsl_struct *info );
+static void mgsl_isr_receive_dma( struct mgsl_struct *info );
+static void mgsl_isr_transmit_dma( struct mgsl_struct *info );
typedef void (*isr_dispatch_func)(struct mgsl_struct *);
-isr_dispatch_func UscIsrTable[7] =
+static isr_dispatch_func UscIsrTable[7] =
{
mgsl_isr_null,
mgsl_isr_misc,
static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear);
static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount
- *user_icount);
-static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS *user_params);
-static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS *new_params);
-static int mgsl_get_txidle(struct mgsl_struct * info, int*idle_mode);
+ __user *user_icount);
+static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params);
+static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params);
+static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode);
static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode);
static int mgsl_txenable(struct mgsl_struct * info, int enable);
static int mgsl_txabort(struct mgsl_struct * info);
static int mgsl_rxenable(struct mgsl_struct * info, int enable);
-static int mgsl_wait_event(struct mgsl_struct * info, int * mask);
+static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask);
static int mgsl_loopmode_send_done( struct mgsl_struct * info );
-#define jiffies_from_ms(a) ((((a) * HZ)/1000)+1)
+/* set non-zero on successful registration with PCI subsystem */
+static int pci_registered;
/*
* Global linked list of SyncLink devices
*/
-struct mgsl_struct *mgsl_device_list;
+static struct mgsl_struct *mgsl_device_list;
static int mgsl_device_count;
/*
static int txdmabufs[MAX_TOTAL_DEVICES];
static int txholdbufs[MAX_TOTAL_DEVICES];
-MODULE_PARM(break_on_load,"i");
-MODULE_PARM(ttymajor,"i");
-MODULE_PARM(io,"1-" __MODULE_STRING(MAX_ISA_DEVICES) "i");
-MODULE_PARM(irq,"1-" __MODULE_STRING(MAX_ISA_DEVICES) "i");
-MODULE_PARM(dma,"1-" __MODULE_STRING(MAX_ISA_DEVICES) "i");
-MODULE_PARM(debug_level,"i");
-MODULE_PARM(maxframe,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
-MODULE_PARM(dosyncppp,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
-MODULE_PARM(txdmabufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
-MODULE_PARM(txholdbufs,"1-" __MODULE_STRING(MAX_TOTAL_DEVICES) "i");
+module_param(break_on_load, bool, 0);
+module_param(ttymajor, int, 0);
+module_param_array(io, int, NULL, 0);
+module_param_array(irq, int, NULL, 0);
+module_param_array(dma, int, NULL, 0);
+module_param(debug_level, int, 0);
+module_param_array(maxframe, int, NULL, 0);
+module_param_array(dosyncppp, int, NULL, 0);
+module_param_array(txdmabufs, int, NULL, 0);
+module_param_array(txholdbufs, int, NULL, 0);
static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.21 $";
+static char *driver_version = "$Revision: 4.28 $";
static int synclink_init_one (struct pci_dev *dev,
const struct pci_device_id *ent);
static void mgsl_change_params(struct mgsl_struct *info);
static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
-#ifndef MIN
-#define MIN(a,b) ((a) < (b) ? (a) : (b))
-#endif
-
/*
* 1st function defined in .text section. Calling this function in
* init_module() followed by a breakpoint allows a remote debugger
* (gdb) to get the .text address for the add-symbol-file command.
* This allows remote debugging of dynamically loadable modules.
*/
-void* mgsl_get_text_ptr(void);
-void* mgsl_get_text_ptr() {return mgsl_get_text_ptr;}
+static void* mgsl_get_text_ptr(void)
+{
+ return mgsl_get_text_ptr;
+}
/*
* tmp_buf is used as a temporary buffer by mgsl_write. We need to
return 0;
}
+/**
+ * line discipline callback wrappers
+ *
+ * The wrappers maintain line discipline references
+ * while calling into the line discipline.
+ *
+ * ldisc_receive_buf - pass receive data to line discipline
+ */
+
+static void ldisc_receive_buf(struct tty_struct *tty,
+ const __u8 *data, char *flags, int count)
+{
+ struct tty_ldisc *ld;
+ if (!tty)
+ return;
+ ld = tty_ldisc_ref(tty);
+ if (ld) {
+ if (ld->receive_buf)
+ ld->receive_buf(tty, data, flags, count);
+ tty_ldisc_deref(ld);
+ }
+}
+
/* mgsl_stop() throttle (stop) transmitter
*
* Arguments: tty pointer to tty info structure
/* mgsl_bh_action() Return next bottom half action to perform.
* Return Value: BH action code or 0 if nothing to do.
*/
-int mgsl_bh_action(struct mgsl_struct *info)
+static int mgsl_bh_action(struct mgsl_struct *info)
{
unsigned long flags;
int rc = 0;
/*
* Perform bottom half processing of work items queued by ISR.
*/
-void mgsl_bh_handler(void* Context)
+static void mgsl_bh_handler(void* Context)
{
struct mgsl_struct *info = (struct mgsl_struct*)Context;
int action;
__FILE__,__LINE__,info->device_name);
}
-void mgsl_bh_receive(struct mgsl_struct *info)
+static void mgsl_bh_receive(struct mgsl_struct *info)
{
int (*get_rx_frame)(struct mgsl_struct *info) =
(info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame);
} while(get_rx_frame(info));
}
-void mgsl_bh_transmit(struct mgsl_struct *info)
+static void mgsl_bh_transmit(struct mgsl_struct *info)
{
struct tty_struct *tty = info->tty;
unsigned long flags;
__FILE__,__LINE__,info->device_name);
if (tty) {
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup) {
- if ( debug_level >= DEBUG_LEVEL_BH )
- printk( "%s(%d):calling ldisc.write_wakeup on %s\n",
- __FILE__,__LINE__,info->device_name);
- (tty->ldisc.write_wakeup)(tty);
- }
+ tty_wakeup(tty);
wake_up_interruptible(&tty->write_wait);
}
spin_unlock_irqrestore(&info->irq_spinlock,flags);
}
-void mgsl_bh_status(struct mgsl_struct *info)
+static void mgsl_bh_status(struct mgsl_struct *info)
{
if ( debug_level >= DEBUG_LEVEL_BH )
printk( "%s(%d):mgsl_bh_status() entry on %s\n",
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_receive_status( struct mgsl_struct *info )
+static void mgsl_isr_receive_status( struct mgsl_struct *info )
{
u16 status = usc_InReg( info, RCSR );
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_transmit_status( struct mgsl_struct *info )
+static void mgsl_isr_transmit_status( struct mgsl_struct *info )
{
u16 status = usc_InReg( info, TCSR );
info->drop_rts_on_tx_done = 0;
}
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
if (info->netcount)
- mgsl_sppp_tx_done(info);
+ hdlcdev_tx_done(info);
else
#endif
{
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_io_pin( struct mgsl_struct *info )
+static void mgsl_isr_io_pin( struct mgsl_struct *info )
{
struct mgsl_icount *icount;
u16 status = usc_InReg( info, MISR );
icount->dcd++;
if (status & MISCSTATUS_DCD) {
info->input_signal_events.dcd_up++;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- if (info->netcount)
- sppp_reopen(info->netdev);
-#endif
} else
info->input_signal_events.dcd_down++;
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlc_set_carrier(status & MISCSTATUS_DCD, info->netdev);
+#endif
}
if (status & MISCSTATUS_CTS_LATCHED)
{
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_transmit_data( struct mgsl_struct *info )
+static void mgsl_isr_transmit_data( struct mgsl_struct *info )
{
if ( debug_level >= DEBUG_LEVEL_ISR )
printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n",
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_receive_data( struct mgsl_struct *info )
+static void mgsl_isr_receive_data( struct mgsl_struct *info )
{
int Fifocount;
u16 status;
* Arguments: info pointer to device extension (instance data)
* Return Value: None
*/
-void mgsl_isr_misc( struct mgsl_struct *info )
+static void mgsl_isr_misc( struct mgsl_struct *info )
{
u16 status = usc_InReg( info, MISR );
* Arguments: info pointer to device extension (instance data)
* Return Value: None
*/
-void mgsl_isr_null( struct mgsl_struct *info )
+static void mgsl_isr_null( struct mgsl_struct *info )
{
} /* end of mgsl_isr_null() */
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_receive_dma( struct mgsl_struct *info )
+static void mgsl_isr_receive_dma( struct mgsl_struct *info )
{
u16 status;
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_isr_transmit_dma( struct mgsl_struct *info )
+static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
{
u16 status;
if (info->xmit_buf) {
free_page((unsigned long) info->xmit_buf);
- info->xmit_buf = 0;
+ info->xmit_buf = NULL;
}
spin_lock_irqsave(&info->irq_spinlock,flags);
* Arguments:
*
* tty pointer to tty information structure
- * from_user flag: 1 = from user process
* buf pointer to buffer containing send data
* count size of send data in bytes
*
* Return Value: number of characters written
*/
-static int mgsl_write(struct tty_struct * tty, int from_user,
+static int mgsl_write(struct tty_struct * tty,
const unsigned char *buf, int count)
{
- int c, ret = 0, err;
+ int c, ret = 0;
struct mgsl_struct *info = (struct mgsl_struct *)tty->driver_data;
unsigned long flags;
/* queue transmit frame request */
ret = count;
- if (from_user) {
- down(&tmp_buf_sem);
- COPY_FROM_USER(err,tmp_buf, buf, count);
- if (err) {
- if ( debug_level >= DEBUG_LEVEL_INFO )
- printk( "%s(%d):mgsl_write(%s) sync user buf copy failed\n",
- __FILE__,__LINE__,info->device_name);
- ret = -EFAULT;
- } else
- save_tx_buffer_request(info,tmp_buf,count);
- up(&tmp_buf_sem);
- }
- else
- save_tx_buffer_request(info,buf,count);
+ save_tx_buffer_request(info,buf,count);
/* if we have sufficient tx dma buffers,
* load the next buffered tx request
__FILE__,__LINE__,info->device_name);
ret = count;
info->xmit_cnt = count;
- if (from_user) {
- down(&tmp_buf_sem);
- COPY_FROM_USER(err,tmp_buf, buf, count);
- if (err) {
- if ( debug_level >= DEBUG_LEVEL_INFO )
- printk( "%s(%d):mgsl_write(%s) sync user buf copy failed\n",
- __FILE__,__LINE__,info->device_name);
- ret = -EFAULT;
- } else
- mgsl_load_tx_dma_buffer(info,tmp_buf,count);
- up(&tmp_buf_sem);
- }
- else
- mgsl_load_tx_dma_buffer(info,buf,count);
+ mgsl_load_tx_dma_buffer(info,buf,count);
}
} else {
- if (from_user) {
- down(&tmp_buf_sem);
- while (1) {
- c = MIN(count,
- MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - info->xmit_head));
- if (c <= 0)
- break;
-
- COPY_FROM_USER(err,tmp_buf, buf, c);
- c -= err;
- if (!c) {
- if (!ret)
- ret = -EFAULT;
- break;
- }
- spin_lock_irqsave(&info->irq_spinlock,flags);
- c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - info->xmit_head));
- memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
- info->xmit_head = ((info->xmit_head + c) &
- (SERIAL_XMIT_SIZE-1));
- info->xmit_cnt += c;
- spin_unlock_irqrestore(&info->irq_spinlock,flags);
- buf += c;
- count -= c;
- ret += c;
- }
- up(&tmp_buf_sem);
- } else {
- while (1) {
- spin_lock_irqsave(&info->irq_spinlock,flags);
- c = MIN(count,
- MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
- SERIAL_XMIT_SIZE - info->xmit_head));
- if (c <= 0) {
- spin_unlock_irqrestore(&info->irq_spinlock,flags);
- break;
- }
- memcpy(info->xmit_buf + info->xmit_head, buf, c);
- info->xmit_head = ((info->xmit_head + c) &
- (SERIAL_XMIT_SIZE-1));
- info->xmit_cnt += c;
+ while (1) {
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+ c = min_t(int, count,
+ min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+ SERIAL_XMIT_SIZE - info->xmit_head));
+ if (c <= 0) {
spin_unlock_irqrestore(&info->irq_spinlock,flags);
- buf += c;
- count -= c;
- ret += c;
+ break;
}
+ memcpy(info->xmit_buf + info->xmit_head, buf, c);
+ info->xmit_head = ((info->xmit_head + c) &
+ (SERIAL_XMIT_SIZE-1));
+ info->xmit_cnt += c;
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ buf += c;
+ count -= c;
+ ret += c;
}
}
spin_unlock_irqrestore(&info->irq_spinlock,flags);
wake_up_interruptible(&tty->write_wait);
- if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
- tty->ldisc.write_wakeup)
- (tty->ldisc.write_wakeup)(tty);
-
-} /* end of mgsl_flush_buffer() */
+ tty_wakeup(tty);
+}
/* mgsl_send_xchar()
*
*
* Return Value: 0 if success, otherwise error code
*/
-static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount *user_icount)
+static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *user_icount)
{
int err;
*
* Return Value: 0 if success, otherwise error code
*/
-static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS *user_params)
+static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params)
{
int err;
if (debug_level >= DEBUG_LEVEL_INFO)
*
* Return Value: 0 if success, otherwise error code
*/
-static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS *new_params)
+static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params)
{
unsigned long flags;
MGSL_PARAMS tmp_params;
*
* Return Value: 0 if success, otherwise error code
*/
-static int mgsl_get_txidle(struct mgsl_struct * info, int*idle_mode)
+static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode)
{
int err;
* of events triggerred,
* otherwise error code
*/
-static int mgsl_wait_event(struct mgsl_struct * info, int * mask_ptr)
+static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr)
{
unsigned long flags;
int s;
return mgsl_ioctl_common(info, cmd, arg);
}
-int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
+static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
{
int error;
struct mgsl_icount cnow; /* kernel counter temps */
- struct serial_icounter_struct *p_cuser; /* user space */
+ void __user *argp = (void __user *)arg;
+ struct serial_icounter_struct __user *p_cuser; /* user space */
unsigned long flags;
switch (cmd) {
case MGSL_IOCGPARAMS:
- return mgsl_get_params(info,(MGSL_PARAMS *)arg);
+ return mgsl_get_params(info, argp);
case MGSL_IOCSPARAMS:
- return mgsl_set_params(info,(MGSL_PARAMS *)arg);
+ return mgsl_set_params(info, argp);
case MGSL_IOCGTXIDLE:
- return mgsl_get_txidle(info,(int*)arg);
+ return mgsl_get_txidle(info, argp);
case MGSL_IOCSTXIDLE:
return mgsl_set_txidle(info,(int)arg);
case MGSL_IOCTXENABLE:
case MGSL_IOCTXABORT:
return mgsl_txabort(info);
case MGSL_IOCGSTATS:
- return mgsl_get_stats(info,(struct mgsl_icount*)arg);
+ return mgsl_get_stats(info, argp);
case MGSL_IOCWAITEVENT:
- return mgsl_wait_event(info,(int*)arg);
+ return mgsl_wait_event(info, argp);
case MGSL_IOCLOOPTXDONE:
return mgsl_loopmode_send_done(info);
/* Wait for modem input (DCD,RI,DSR,CTS) change
spin_lock_irqsave(&info->irq_spinlock,flags);
cnow = info->icount;
spin_unlock_irqrestore(&info->irq_spinlock,flags);
- p_cuser = (struct serial_icounter_struct *) arg;
+ p_cuser = argp;
PUT_USER(error,cnow.cts, &p_cuser->cts);
if (error) return error;
PUT_USER(error,cnow.dsr, &p_cuser->dsr);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
-
- if (tty->ldisc.flush_buffer)
- tty->ldisc.flush_buffer(tty);
+
+ tty_ldisc_flush(tty);
shutdown(info);
tty->closing = 0;
- info->tty = 0;
+ info->tty = NULL;
if (info->blocked_open) {
if (info->close_delay) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(info->close_delay);
+ msleep_interruptible(jiffies_to_msecs(info->close_delay));
}
wake_up_interruptible(&info->open_wait);
}
char_time = 1;
if (timeout)
- char_time = MIN(char_time, timeout);
+ char_time = min_t(unsigned long, char_time, timeout);
if ( info->params.mode == MGSL_MODE_HDLC ||
info->params.mode == MGSL_MODE_RAW ) {
while (info->tx_active) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
+ msleep_interruptible(jiffies_to_msecs(char_time));
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
} else {
while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) &&
info->tx_enabled) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(char_time);
+ msleep_interruptible(jiffies_to_msecs(char_time));
if (signal_pending(current))
break;
if (timeout && time_after(jiffies, orig_jiffies + timeout))
info->count = 0;
info->flags &= ~ASYNC_NORMAL_ACTIVE;
- info->tty = 0;
+ info->tty = NULL;
wake_up_interruptible(&info->open_wait);
cleanup:
if (retval) {
if (tty->count == 1)
- info->tty = 0; /* tty layer will release tty struct */
+ info->tty = NULL; /* tty layer will release tty struct */
if(info->count)
info->count--;
}
*
* Return Value:
*/
-int mgsl_read_proc(char *page, char **start, off_t off, int count,
+static int mgsl_read_proc(char *page, char **start, off_t off, int count,
int *eof, void *data)
{
int len = 0, l;
* Arguments: info pointer to device instance data
* Return Value: 0 if success, otherwise error
*/
-int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
+static int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
{
unsigned short BuffersPerFrame;
* Arguments: info pointer to device instance data
* Return Value: 0 if success, otherwise error
*/
-int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
+static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
{
unsigned int i;
* the buffer list contains the information necessary to free
* the individual buffers!
*/
-void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
+static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
{
if ( info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI )
kfree(info->buffer_list);
*
* Return Value: 0 if success, otherwise -ENOMEM
*/
-int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
+static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
{
int i;
unsigned long phys_addr;
*
* Return Value: None
*/
-void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount)
+static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount)
{
int i;
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_free_dma_buffers( struct mgsl_struct *info )
+static void mgsl_free_dma_buffers( struct mgsl_struct *info )
{
mgsl_free_frame_memory( info, info->rx_buffer_list, info->rx_buffer_count );
mgsl_free_frame_memory( info, info->tx_buffer_list, info->tx_buffer_count );
*
* Return Value: 0 if success, otherwise -ENOMEM
*/
-int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
+static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
{
info->intermediate_rxbuffer = kmalloc(info->max_frame_size, GFP_KERNEL | GFP_DMA);
if ( info->intermediate_rxbuffer == NULL )
*
* Return Value: None
*/
-void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
+static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
{
if ( info->intermediate_rxbuffer )
kfree(info->intermediate_rxbuffer);
*
* Return Value: 0 if success, otherwise -ENOMEM
*/
-int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
+static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
{
int i;
*
* Return Value: None
*/
-void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
+static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
{
int i;
* into adapter's tx dma buffer,
* 0 otherwise
*/
-int load_next_tx_holding_buffer(struct mgsl_struct *info)
+static int load_next_tx_holding_buffer(struct mgsl_struct *info)
{
int ret = 0;
info->get_tx_holding_index=0;
/* restart transmit timer */
- mod_timer(&info->tx_timer, jiffies + jiffies_from_ms(5000));
+ mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000));
ret = 1;
}
*
* Return Value: 1 if able to store, 0 otherwise
*/
-int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize)
+static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize)
{
struct tx_holding_buffer *ptx;
return 1;
}
-int mgsl_claim_resources(struct mgsl_struct *info)
+static int mgsl_claim_resources(struct mgsl_struct *info)
{
if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) {
printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n",
} /* end of mgsl_claim_resources() */
-void mgsl_release_resources(struct mgsl_struct *info)
+static void mgsl_release_resources(struct mgsl_struct *info)
{
if ( debug_level >= DEBUG_LEVEL_INFO )
printk( "%s(%d):mgsl_release_resources(%s) entry\n",
}
if (info->memory_base){
iounmap(info->memory_base);
- info->memory_base = 0;
+ info->memory_base = NULL;
}
if (info->lcr_base){
iounmap(info->lcr_base - info->lcr_offset);
- info->lcr_base = 0;
+ info->lcr_base = NULL;
}
if ( debug_level >= DEBUG_LEVEL_INFO )
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_add_device( struct mgsl_struct *info )
+static void mgsl_add_device( struct mgsl_struct *info )
{
info->next_device = NULL;
info->line = mgsl_device_count;
info->max_frame_size );
}
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-#ifdef MODULE
- if (info->dosyncppp)
-#endif
- mgsl_sppp_init(info);
+#ifdef CONFIG_HDLC
+ hdlcdev_init(info);
#endif
+
} /* end of mgsl_add_device() */
/* mgsl_allocate_device()
* Arguments: none
* Return Value: pointer to mgsl_struct if success, otherwise NULL
*/
-struct mgsl_struct* mgsl_allocate_device()
+static struct mgsl_struct* mgsl_allocate_device(void)
{
struct mgsl_struct *info;
/*
* perform tty device initialization
*/
-int mgsl_init_tty(void);
-int mgsl_init_tty()
+static int mgsl_init_tty(void)
{
- serial_driver = alloc_tty_driver(mgsl_device_count);
+ int rc;
+
+ serial_driver = alloc_tty_driver(128);
if (!serial_driver)
return -ENOMEM;
B9600 | CS8 | CREAD | HUPCL | CLOCAL;
serial_driver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(serial_driver, &mgsl_ops);
- if (tty_register_driver(serial_driver) < 0)
+ if ((rc = tty_register_driver(serial_driver)) < 0) {
printk("%s(%d):Couldn't register serial driver\n",
__FILE__,__LINE__);
+ put_tty_driver(serial_driver);
+ serial_driver = NULL;
+ return rc;
+ }
printk("%s %s, tty major#%d\n",
driver_name, driver_version,
/* enumerate user specified ISA adapters
*/
-int mgsl_enum_isa_devices()
+static void mgsl_enum_isa_devices(void)
{
struct mgsl_struct *info;
int i;
mgsl_add_device( info );
}
-
- return 0;
}
-/* mgsl_init()
- *
- * Driver initialization entry point.
- *
- * Arguments: None
- * Return Value: 0 if success, otherwise error code
- */
-int __init mgsl_init(void)
-{
- int rc;
-
- printk("%s %s\n", driver_name, driver_version);
-
- mgsl_enum_isa_devices();
- pci_register_driver(&synclink_pci_driver);
-
- if ( !mgsl_device_list ) {
- printk("%s(%d):No SyncLink devices found.\n",__FILE__,__LINE__);
- return -ENODEV;
- }
- if ((rc = mgsl_init_tty()))
- return rc;
-
- return 0;
-}
-
-static int __init synclink_init(void)
-{
-/* Uncomment this to kernel debug module.
- * mgsl_get_text_ptr() leaves the .text address in eax
- * which can be used with add-symbol-file with gdb.
- */
- if (break_on_load) {
- mgsl_get_text_ptr();
- BREAKPOINT();
- }
-
- return mgsl_init();
-}
-
-static void __exit synclink_exit(void)
+static void synclink_cleanup(void)
{
int rc;
struct mgsl_struct *info;
printk("Unloading %s: %s\n", driver_name, driver_version);
- if ((rc = tty_unregister_driver(serial_driver)))
- printk("%s(%d) failed to unregister tty driver err=%d\n",
- __FILE__,__LINE__,rc);
+ if (serial_driver) {
+ if ((rc = tty_unregister_driver(serial_driver)))
+ printk("%s(%d) failed to unregister tty driver err=%d\n",
+ __FILE__,__LINE__,rc);
+ put_tty_driver(serial_driver);
+ }
- put_tty_driver(serial_driver);
info = mgsl_device_list;
while(info) {
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- if (info->dosyncppp)
- mgsl_sppp_delete(info);
+#ifdef CONFIG_HDLC
+ hdlcdev_exit(info);
#endif
mgsl_release_resources(info);
tmp = info;
tmp_buf = NULL;
}
- pci_unregister_driver(&synclink_pci_driver);
+ if (pci_registered)
+ pci_unregister_driver(&synclink_pci_driver);
+}
+
+static int __init synclink_init(void)
+{
+ int rc;
+
+ if (break_on_load) {
+ mgsl_get_text_ptr();
+ BREAKPOINT();
+ }
+
+ printk("%s %s\n", driver_name, driver_version);
+
+ mgsl_enum_isa_devices();
+ if ((rc = pci_register_driver(&synclink_pci_driver)) < 0)
+ printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
+ else
+ pci_registered = 1;
+
+ if ((rc = mgsl_init_tty()) < 0)
+ goto error;
+
+ return 0;
+
+error:
+ synclink_cleanup();
+ return rc;
+}
+
+static void __exit synclink_exit(void)
+{
+ synclink_cleanup();
}
module_init(synclink_init);
*
* None
*/
-void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
+static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
{
/* output command to CCAR in bits <15..11> */
/* preserve bits <10..7>, bits <6..0> must be zero */
*
* None
*/
-void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
+static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
{
/* write command mask to DCAR */
outw( Cmd + info->mbre_bit, info->io_base );
* None
*
*/
-void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
+static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
{
/* Note: The DCAR is located at the adapter base address */
/* Note: must preserve state of BIT8 in DCAR */
* The 16-bit value read from register
*
*/
-u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr )
+static u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr )
{
/* Note: The DCAR is located at the adapter base address */
/* Note: must preserve state of BIT8 in DCAR */
* None
*
*/
-void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
+static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
{
outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
outw( RegValue, info->io_base + CCAR );
*
* 16-bit value read from register
*/
-u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
+static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
{
outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
return inw( info->io_base + CCAR );
* Arguments: info pointer to device instance data
* Return Value: NONE
*/
-void usc_set_sdlc_mode( struct mgsl_struct *info )
+static void usc_set_sdlc_mode( struct mgsl_struct *info )
{
u16 RegValue;
int PreSL1660;
* enable 1 = enable loopback, 0 = disable
* Return Value: None
*/
-void usc_enable_loopback(struct mgsl_struct *info, int enable)
+static void usc_enable_loopback(struct mgsl_struct *info, int enable)
{
if (enable) {
/* blank external TXD output */
*
* Return Value: None
*/
-void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
+static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
{
u32 XtalSpeed;
u16 Tc;
*
* Return Value: None
*/
-void usc_process_rxoverrun_sync( struct mgsl_struct *info )
+static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
{
int start_index;
int end_index;
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_stop_receiver( struct mgsl_struct *info )
+static void usc_stop_receiver( struct mgsl_struct *info )
{
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):usc_stop_receiver(%s)\n",
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_start_receiver( struct mgsl_struct *info )
+static void usc_start_receiver( struct mgsl_struct *info )
{
u32 phys_addr;
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_start_transmitter( struct mgsl_struct *info )
+static void usc_start_transmitter( struct mgsl_struct *info )
{
u32 phys_addr;
unsigned int FrameSize;
usc_TCmd( info, TCmd_SendFrame );
- info->tx_timer.expires = jiffies + jiffies_from_ms(5000);
+ info->tx_timer.expires = jiffies + msecs_to_jiffies(5000);
add_timer(&info->tx_timer);
}
info->tx_active = 1;
* Arguments: info pointer to device isntance data
* Return Value: None
*/
-void usc_stop_transmitter( struct mgsl_struct *info )
+static void usc_stop_transmitter( struct mgsl_struct *info )
{
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):usc_stop_transmitter(%s)\n",
* Arguments: info pointer to device extension (instance data)
* Return Value: None
*/
-void usc_load_txfifo( struct mgsl_struct *info )
+static void usc_load_txfifo( struct mgsl_struct *info )
{
int Fifocount;
u8 TwoBytes[2];
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_reset( struct mgsl_struct *info )
+static void usc_reset( struct mgsl_struct *info )
{
if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
int i;
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_set_async_mode( struct mgsl_struct *info )
+static void usc_set_async_mode( struct mgsl_struct *info )
{
u16 RegValue;
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_loopback_frame( struct mgsl_struct *info )
+static void usc_loopback_frame( struct mgsl_struct *info )
{
int i;
unsigned long oldmode = info->params.mode;
* Arguments: info pointer to adapter info structure
* Return Value: None
*/
-void usc_set_sync_mode( struct mgsl_struct *info )
+static void usc_set_sync_mode( struct mgsl_struct *info )
{
usc_loopback_frame( info );
usc_set_sdlc_mode( info );
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_set_txidle( struct mgsl_struct *info )
+static void usc_set_txidle( struct mgsl_struct *info )
{
u16 usc_idle_mode = IDLEMODE_FLAGS;
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_get_serial_signals( struct mgsl_struct *info )
+static void usc_get_serial_signals( struct mgsl_struct *info )
{
u16 status;
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void usc_set_serial_signals( struct mgsl_struct *info )
+static void usc_set_serial_signals( struct mgsl_struct *info )
{
u16 Control;
unsigned char V24Out = info->serial_signals;
* 0 disables the AUX clock.
* Return Value: None
*/
-void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
+static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
{
if ( data_rate ) {
/*
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
+static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
{
unsigned int i;
* Arguments: info pointer to device instance data
* Return Value: number of free tx dma buffers
*/
-int num_free_tx_dma_buffers(struct mgsl_struct *info)
+static int num_free_tx_dma_buffers(struct mgsl_struct *info)
{
return info->tx_buffer_count - info->tx_dma_buffers_used;
}
* Arguments: info pointer to device instance data
* Return Value: None
*/
-void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
+static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
{
unsigned int i;
*
* Return Value: None
*/
-void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex )
+static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex )
{
int Done = 0;
DMABUFFERENTRY *pBufEntry;
* Arguments: info pointer to device extension
* Return Value: 1 if frame returned, otherwise 0
*/
-int mgsl_get_rx_frame(struct mgsl_struct *info)
+static int mgsl_get_rx_frame(struct mgsl_struct *info)
{
unsigned int StartIndex, EndIndex; /* index of 1st and last buffers of Rx frame */
unsigned short status;
return_frame = 1;
}
framesize = 0;
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- info->netstats.rx_errors++;
- info->netstats.rx_frame_errors++;
+#ifdef CONFIG_HDLC
+ {
+ struct net_device_stats *stats = hdlc_stats(info->netdev);
+ stats->rx_errors++;
+ stats->rx_frame_errors++;
+ }
#endif
} else
return_frame = 1;
if ( debug_level >= DEBUG_LEVEL_DATA )
mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr,
- MIN(framesize,DMABUFFERSIZE),0);
+ min_t(int, framesize, DMABUFFERSIZE),0);
if (framesize) {
if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) &&
*ptmp);
}
-#ifdef CONFIG_SYNCLINK_SYNCPPP
- if (info->netcount) {
- /* pass frame to syncppp device */
- mgsl_sppp_rx_done(info,info->intermediate_rxbuffer,framesize);
- }
+#ifdef CONFIG_HDLC
+ if (info->netcount)
+ hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
else
#endif
- {
- /* Call the line discipline receive callback directly. */
- if ( tty && tty->ldisc.receive_buf )
- tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
- }
+ ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
}
}
/* Free the buffers used by this frame. */
* Arguments: info pointer to device extension
* Return Value: 1 if frame returned, otherwise 0
*/
-int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
+static int mgsl_get_raw_rx_frame(struct mgsl_struct *info)
{
unsigned int CurrentIndex, NextIndex;
unsigned short status;
if ( debug_level >= DEBUG_LEVEL_DATA )
mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr,
- MIN(framesize,DMABUFFERSIZE),0);
+ min_t(int, framesize, DMABUFFERSIZE),0);
if (framesize) {
/* copy dma buffer(s) to contiguous intermediate buffer */
memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
info->icount.rxok++;
- /* Call the line discipline receive callback directly. */
- if ( tty && tty->ldisc.receive_buf )
- tty->ldisc.receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
+ ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
}
/* Free the buffers used by this frame. */
*
* Return Value: None
*/
-void mgsl_load_tx_dma_buffer(struct mgsl_struct *info, const char *Buffer,
- unsigned int BufferSize)
+static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
+ const char *Buffer, unsigned int BufferSize)
{
unsigned short Copycount;
unsigned int i = 0;
DMABUFFERENTRY *pBufEntry;
if ( debug_level >= DEBUG_LEVEL_DATA )
- mgsl_trace_block(info,Buffer, MIN(BufferSize,DMABUFFERSIZE), 1);
+ mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1);
if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
/* set CMR:13 to start transmit when
* Arguments: info pointer to device instance data
* Return Value: TRUE if test passed, otherwise FALSE
*/
-BOOLEAN mgsl_register_test( struct mgsl_struct *info )
+static BOOLEAN mgsl_register_test( struct mgsl_struct *info )
{
static unsigned short BitPatterns[] =
{ 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
* Arguments: info pointer to device instance data
* Return Value: TRUE if test passed, otherwise FALSE
*/
-BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
+static BOOLEAN mgsl_irq_test( struct mgsl_struct *info )
{
unsigned long EndTime;
unsigned long flags;
EndTime=100;
while( EndTime-- && !info->irq_occurred ) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(jiffies_from_ms(10));
+ msleep_interruptible(10);
}
spin_lock_irqsave(&info->irq_spinlock,flags);
* Arguments: info pointer to device instance data
* Return Value: TRUE if test passed, otherwise FALSE
*/
-BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
+static BOOLEAN mgsl_dma_test( struct mgsl_struct *info )
{
unsigned short FifoLevel;
unsigned long phys_addr;
/*************************************************************/
/* Wait 100ms for interrupt. */
- EndTime = jiffies + jiffies_from_ms(100);
+ EndTime = jiffies + msecs_to_jiffies(100);
for(;;) {
if (time_after(jiffies, EndTime)) {
/**********************************/
/* Wait 100ms */
- EndTime = jiffies + jiffies_from_ms(100);
+ EndTime = jiffies + msecs_to_jiffies(100);
for(;;) {
if (time_after(jiffies, EndTime)) {
/******************************/
/* Wait 100ms */
- EndTime = jiffies + jiffies_from_ms(100);
+ EndTime = jiffies + msecs_to_jiffies(100);
/* While timer not expired wait for transmit complete */
/* WAIT FOR RECEIVE COMPLETE */
/* Wait 100ms */
- EndTime = jiffies + jiffies_from_ms(100);
+ EndTime = jiffies + msecs_to_jiffies(100);
/* Wait for 16C32 to write receive status to buffer entry. */
status=info->rx_buffer_list[0].status;
* Arguments: info pointer to device instance data
* Return Value: 0 if success, otherwise -ENODEV
*/
-int mgsl_adapter_test( struct mgsl_struct *info )
+static int mgsl_adapter_test( struct mgsl_struct *info )
{
if ( debug_level >= DEBUG_LEVEL_INFO )
printk( "%s(%d):Testing device %s\n",
* Arguments: info pointer to device instance data
* Return Value: TRUE if test passed, otherwise FALSE
*/
-BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
+static BOOLEAN mgsl_memory_test( struct mgsl_struct *info )
{
static unsigned long BitPatterns[] = { 0x0, 0x55555555, 0xaaaaaaaa,
0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
*
* Return Value: None
*/
-void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr,
+static void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr,
unsigned short count )
{
/* 16 32-bit writes @ 60ns each = 960ns max latency on local bus */
} /* End Of mgsl_load_pci_memory() */
-void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit)
+static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit)
{
int i;
int linecount;
* Arguments: context pointer to device instance data
* Return Value: None
*/
-void mgsl_tx_timeout(unsigned long context)
+static void mgsl_tx_timeout(unsigned long context)
{
struct mgsl_struct *info = (struct mgsl_struct*)context;
unsigned long flags;
spin_unlock_irqrestore(&info->irq_spinlock,flags);
-#ifdef CONFIG_SYNCLINK_SYNCPPP
+#ifdef CONFIG_HDLC
if (info->netcount)
- mgsl_sppp_tx_done(info);
+ hdlcdev_tx_done(info);
else
#endif
mgsl_bh_transmit(info);
/* release the line by echoing RxD to TxD
* upon completion of a transmit frame
*/
-void usc_loopmode_send_done( struct mgsl_struct * info )
+static void usc_loopmode_send_done( struct mgsl_struct * info )
{
info->loopmode_send_done_requested = FALSE;
/* clear CMR:13 to 0 to start echoing RxData to TxData */
/* abort a transmit in progress while in HDLC LoopMode
*/
-void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
+static void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
{
/* reset tx dma channel and purge TxFifo */
usc_RTCmd( info, RTCmd_PurgeTxFifo );
* is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort)
* we must clear CMR:13 to begin repeating TxData to RxData
*/
-void usc_loopmode_insert_request( struct mgsl_struct * info )
+static void usc_loopmode_insert_request( struct mgsl_struct * info )
{
info->loopmode_insert_requested = TRUE;
/* return 1 if station is inserted into the loop, otherwise 0
*/
-int usc_loopmode_active( struct mgsl_struct * info)
+static int usc_loopmode_active( struct mgsl_struct * info)
{
return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ;
}
-/* return 1 if USC is in loop send mode, otherwise 0
- */
-int usc_loopmode_send_active( struct mgsl_struct * info )
-{
- return usc_InReg( info, CCSR ) & BIT6 ? 1 : 0 ;
-}
+#ifdef CONFIG_HDLC
-#ifdef CONFIG_SYNCLINK_SYNCPPP
-/* syncppp net device routines
+/**
+ * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
+ * set encoding and frame check sequence (FCS) options
+ *
+ * dev pointer to network device structure
+ * encoding serial encoding setting
+ * parity FCS setting
+ *
+ * returns 0 if success, otherwise error code
*/
-static void mgsl_setup(struct net_device *dev)
+static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
+ unsigned short parity)
{
- dev->open = mgsl_sppp_open;
- dev->stop = mgsl_sppp_close;
- dev->hard_start_xmit = mgsl_sppp_tx;
- dev->do_ioctl = mgsl_sppp_ioctl;
- dev->get_stats = mgsl_net_stats;
- dev->tx_timeout = mgsl_sppp_tx_timeout;
- dev->watchdog_timeo = 10*HZ;
-}
-
-static void mgsl_sppp_init(struct mgsl_struct *info)
-{
- struct net_device *d;
+ struct mgsl_struct *info = dev_to_port(dev);
+ unsigned char new_encoding;
+ unsigned short new_crctype;
- sprintf(info->netname,"mgsl%d",info->line);
+ /* return error if TTY interface open */
+ if (info->count)
+ return -EBUSY;
- d = alloc_netdev(0, info->netname, mgsl_setup);
- if (!d) {
- printk(KERN_WARNING "%s: alloc_netdev failed.\n",
- info->netname);
- return;
+ switch (encoding)
+ {
+ case ENCODING_NRZ: new_encoding = HDLC_ENCODING_NRZ; break;
+ case ENCODING_NRZI: new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
+ case ENCODING_FM_MARK: new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
+ case ENCODING_FM_SPACE: new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
+ case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
+ default: return -EINVAL;
}
- info->if_ptr = &info->pppdev;
- info->netdev = info->pppdev.dev = d;
-
- d->base_addr = info->io_base;
- d->irq = info->irq_level;
- d->dma = info->dma_level;
- d->priv = info;
+ switch (parity)
+ {
+ case PARITY_NONE: new_crctype = HDLC_CRC_NONE; break;
+ case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
+ case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
+ default: return -EINVAL;
+ }
- sppp_attach(&info->pppdev);
- mgsl_setup(d);
+ info->params.encoding = new_encoding;
+ info->params.crc_type = new_crctype;;
- if (register_netdev(d)) {
- printk(KERN_WARNING "%s: register_netdev failed.\n", d->name);
- sppp_detach(info->netdev);
- info->netdev = NULL;
- free_netdev(d);
- return;
- }
+ /* if network interface up, reprogram hardware */
+ if (info->netcount)
+ mgsl_program_hw(info);
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgsl_sppp_init()\n");
+ return 0;
}
-void mgsl_sppp_delete(struct mgsl_struct *info)
+/**
+ * called by generic HDLC layer to send frame
+ *
+ * skb socket buffer containing HDLC frame
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_xmit(struct sk_buff *skb, struct net_device *dev)
{
+ struct mgsl_struct *info = dev_to_port(dev);
+ struct net_device_stats *stats = hdlc_stats(dev);
+ unsigned long flags;
+
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgsl_sppp_delete(%s)\n",info->netname);
- unregister_netdev(info->netdev);
- sppp_detach(info->netdev);
- free_netdev(info->netdev);
- info->netdev = NULL;
- info->pppdev.dev = NULL;
+ printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
+
+ /* stop sending until this frame completes */
+ netif_stop_queue(dev);
+
+ /* copy data to device buffers */
+ info->xmit_cnt = skb->len;
+ mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
+
+ /* update network statistics */
+ stats->tx_packets++;
+ stats->tx_bytes += skb->len;
+
+ /* done with socket buffer, so free it */
+ dev_kfree_skb(skb);
+
+ /* save start time for transmit timeout detection */
+ dev->trans_start = jiffies;
+
+ /* start hardware transmitter if necessary */
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+ if (!info->tx_active)
+ usc_start_transmitter(info);
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
+
+ return 0;
}
-int mgsl_sppp_open(struct net_device *d)
+/**
+ * called by network layer when interface enabled
+ * claim resources and initialize hardware
+ *
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_open(struct net_device *dev)
{
- struct mgsl_struct *info = d->priv;
- int err;
+ struct mgsl_struct *info = dev_to_port(dev);
+ int rc;
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgsl_sppp_open(%s)\n",info->netname);
+ printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
+
+ /* generic HDLC layer open processing */
+ if ((rc = hdlc_open(dev)))
+ return rc;
+ /* arbitrate between network and tty opens */
spin_lock_irqsave(&info->netlock, flags);
if (info->count != 0 || info->netcount != 0) {
- printk(KERN_WARNING "%s: sppp_open returning busy\n", info->netname);
+ printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
spin_unlock_irqrestore(&info->netlock, flags);
return -EBUSY;
}
spin_unlock_irqrestore(&info->netlock, flags);
/* claim resources and init adapter */
- if ((err = startup(info)) != 0)
- goto open_fail;
-
- /* allow syncppp module to do open processing */
- if ((err = sppp_open(d)) != 0) {
- shutdown(info);
- goto open_fail;
+ if ((rc = startup(info)) != 0) {
+ spin_lock_irqsave(&info->netlock, flags);
+ info->netcount=0;
+ spin_unlock_irqrestore(&info->netlock, flags);
+ return rc;
}
+ /* assert DTR and RTS, apply hardware settings */
info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
mgsl_program_hw(info);
- d->trans_start = jiffies;
- netif_start_queue(d);
- return 0;
+ /* enable network layer transmit */
+ dev->trans_start = jiffies;
+ netif_start_queue(dev);
-open_fail:
- spin_lock_irqsave(&info->netlock, flags);
- info->netcount=0;
- spin_unlock_irqrestore(&info->netlock, flags);
- return err;
+ /* inform generic HDLC layer of current DCD status */
+ spin_lock_irqsave(&info->irq_spinlock, flags);
+ usc_get_serial_signals(info);
+ spin_unlock_irqrestore(&info->irq_spinlock, flags);
+ hdlc_set_carrier(info->serial_signals & SerialSignal_DCD, dev);
+
+ return 0;
}
-void mgsl_sppp_tx_timeout(struct net_device *dev)
+/**
+ * called by network layer when interface is disabled
+ * shutdown hardware and release resources
+ *
+ * dev pointer to network device structure
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_close(struct net_device *dev)
{
- struct mgsl_struct *info = dev->priv;
+ struct mgsl_struct *info = dev_to_port(dev);
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgsl_sppp_tx_timeout(%s)\n",info->netname);
+ printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
- info->netstats.tx_errors++;
- info->netstats.tx_aborted_errors++;
+ netif_stop_queue(dev);
- spin_lock_irqsave(&info->irq_spinlock,flags);
- usc_stop_transmitter(info);
- spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ /* shutdown adapter and release resources */
+ shutdown(info);
- netif_wake_queue(dev);
+ hdlc_close(dev);
+
+ spin_lock_irqsave(&info->netlock, flags);
+ info->netcount=0;
+ spin_unlock_irqrestore(&info->netlock, flags);
+
+ return 0;
}
-int mgsl_sppp_tx(struct sk_buff *skb, struct net_device *dev)
+/**
+ * called by network layer to process IOCTL call to network device
+ *
+ * dev pointer to network device structure
+ * ifr pointer to network interface request structure
+ * cmd IOCTL command code
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- struct mgsl_struct *info = dev->priv;
- unsigned long flags;
+ const size_t size = sizeof(sync_serial_settings);
+ sync_serial_settings new_line;
+ sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
+ struct mgsl_struct *info = dev_to_port(dev);
+ unsigned int flags;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgsl_sppp_tx(%s)\n",info->netname);
+ printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
- netif_stop_queue(dev);
+ /* return error if TTY interface open */
+ if (info->count)
+ return -EBUSY;
- info->xmit_cnt = skb->len;
- mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
- info->netstats.tx_packets++;
- info->netstats.tx_bytes += skb->len;
- dev_kfree_skb(skb);
+ if (cmd != SIOCWANDEV)
+ return hdlc_ioctl(dev, ifr, cmd);
- dev->trans_start = jiffies;
+ switch(ifr->ifr_settings.type) {
+ case IF_GET_IFACE: /* return current sync_serial_settings */
- spin_lock_irqsave(&info->irq_spinlock,flags);
- if (!info->tx_active)
- usc_start_transmitter(info);
- spin_unlock_irqrestore(&info->irq_spinlock,flags);
+ ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+ if (ifr->ifr_settings.size < size) {
+ ifr->ifr_settings.size = size; /* data size wanted */
+ return -ENOBUFS;
+ }
- return 0;
+ flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
+
+ switch (flags){
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
+ case (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_INT; break;
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG): new_line.clock_type = CLOCK_TXINT; break;
+ case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
+ default: new_line.clock_type = CLOCK_DEFAULT;
+ }
+
+ new_line.clock_rate = info->params.clock_speed;
+ new_line.loopback = info->params.loopback ? 1:0;
+
+ if (copy_to_user(line, &new_line, size))
+ return -EFAULT;
+ return 0;
+
+ case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
+
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+ if (copy_from_user(&new_line, line, size))
+ return -EFAULT;
+
+ switch (new_line.clock_type)
+ {
+ case CLOCK_EXT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
+ case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
+ case CLOCK_INT: flags = HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG; break;
+ case CLOCK_TXINT: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG; break;
+ case CLOCK_DEFAULT: flags = info->params.flags &
+ (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN); break;
+ default: return -EINVAL;
+ }
+
+ if (new_line.loopback != 0 && new_line.loopback != 1)
+ return -EINVAL;
+
+ info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
+ HDLC_FLAG_RXC_BRG | HDLC_FLAG_RXC_TXCPIN |
+ HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
+ HDLC_FLAG_TXC_BRG | HDLC_FLAG_TXC_RXCPIN);
+ info->params.flags |= flags;
+
+ info->params.loopback = new_line.loopback;
+
+ if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
+ info->params.clock_speed = new_line.clock_rate;
+ else
+ info->params.clock_speed = 0;
+
+ /* if network interface up, reprogram hardware */
+ if (info->netcount)
+ mgsl_program_hw(info);
+ return 0;
+
+ default:
+ return hdlc_ioctl(dev, ifr, cmd);
+ }
}
-int mgsl_sppp_close(struct net_device *d)
+/**
+ * called by network layer when transmit timeout is detected
+ *
+ * dev pointer to network device structure
+ */
+static void hdlcdev_tx_timeout(struct net_device *dev)
{
- struct mgsl_struct *info = d->priv;
+ struct mgsl_struct *info = dev_to_port(dev);
+ struct net_device_stats *stats = hdlc_stats(dev);
unsigned long flags;
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgsl_sppp_close(%s)\n",info->netname);
+ printk("hdlcdev_tx_timeout(%s)\n",dev->name);
- /* shutdown adapter and release resources */
- shutdown(info);
+ stats->tx_errors++;
+ stats->tx_aborted_errors++;
- /* allow syncppp to do close processing */
- sppp_close(d);
- netif_stop_queue(d);
+ spin_lock_irqsave(&info->irq_spinlock,flags);
+ usc_stop_transmitter(info);
+ spin_unlock_irqrestore(&info->irq_spinlock,flags);
- spin_lock_irqsave(&info->netlock, flags);
- info->netcount=0;
- spin_unlock_irqrestore(&info->netlock, flags);
- return 0;
+ netif_wake_queue(dev);
+}
+
+/**
+ * called by device driver when transmit completes
+ * reenable network layer transmit if stopped
+ *
+ * info pointer to device instance information
+ */
+static void hdlcdev_tx_done(struct mgsl_struct *info)
+{
+ if (netif_queue_stopped(info->netdev))
+ netif_wake_queue(info->netdev);
}
-void mgsl_sppp_rx_done(struct mgsl_struct *info, char *buf, int size)
+/**
+ * called by device driver when frame received
+ * pass frame to network layer
+ *
+ * info pointer to device instance information
+ * buf pointer to buffer contianing frame data
+ * size count of data bytes in buf
+ */
+static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
{
struct sk_buff *skb = dev_alloc_skb(size);
+ struct net_device *dev = info->netdev;
+ struct net_device_stats *stats = hdlc_stats(dev);
+
if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgsl_sppp_rx_done(%s)\n",info->netname);
+ printk("hdlcdev_rx(%s)\n",dev->name);
+
if (skb == NULL) {
- printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
- info->netname);
- info->netstats.rx_dropped++;
+ printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n", dev->name);
+ stats->rx_dropped++;
return;
}
memcpy(skb_put(skb, size),buf,size);
- skb->protocol = htons(ETH_P_WAN_PPP);
- skb->dev = info->netdev;
- skb->mac.raw = skb->data;
- info->netstats.rx_packets++;
- info->netstats.rx_bytes += size;
+ skb->protocol = hdlc_type_trans(skb, info->netdev);
+
+ stats->rx_packets++;
+ stats->rx_bytes += size;
+
netif_rx(skb);
- info->netdev->trans_start = jiffies;
-}
-void mgsl_sppp_tx_done(struct mgsl_struct *info)
-{
- if (netif_queue_stopped(info->netdev))
- netif_wake_queue(info->netdev);
+ info->netdev->last_rx = jiffies;
}
-struct net_device_stats *mgsl_net_stats(struct net_device *dev)
+/**
+ * called by device driver when adding device instance
+ * do generic HDLC initialization
+ *
+ * info pointer to device instance information
+ *
+ * returns 0 if success, otherwise error code
+ */
+static int hdlcdev_init(struct mgsl_struct *info)
{
- struct mgsl_struct *info = dev->priv;
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("mgsl_net_stats(%s)\n",info->netname);
- return &info->netstats;
+ int rc;
+ struct net_device *dev;
+ hdlc_device *hdlc;
+
+ /* allocate and initialize network and HDLC layer objects */
+
+ if (!(dev = alloc_hdlcdev(info))) {
+ printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
+ return -ENOMEM;
+ }
+
+ /* for network layer reporting purposes only */
+ dev->base_addr = info->io_base;
+ dev->irq = info->irq_level;
+ dev->dma = info->dma_level;
+
+ /* network layer callbacks and settings */
+ dev->do_ioctl = hdlcdev_ioctl;
+ dev->open = hdlcdev_open;
+ dev->stop = hdlcdev_close;
+ dev->tx_timeout = hdlcdev_tx_timeout;
+ dev->watchdog_timeo = 10*HZ;
+ dev->tx_queue_len = 50;
+
+ /* generic HDLC layer callbacks and settings */
+ hdlc = dev_to_hdlc(dev);
+ hdlc->attach = hdlcdev_attach;
+ hdlc->xmit = hdlcdev_xmit;
+
+ /* register objects with HDLC layer */
+ if ((rc = register_hdlc_device(dev))) {
+ printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
+ free_netdev(dev);
+ return rc;
+ }
+
+ info->netdev = dev;
+ return 0;
}
-int mgsl_sppp_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
+/**
+ * called by device driver when removing device instance
+ * do generic HDLC cleanup
+ *
+ * info pointer to device instance information
+ */
+static void hdlcdev_exit(struct mgsl_struct *info)
{
- struct mgsl_struct *info = dev->priv;
- if (debug_level >= DEBUG_LEVEL_INFO)
- printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
- info->netname, cmd );
- return sppp_do_ioctl(dev, ifr, cmd);
+ unregister_hdlc_device(info->netdev);
+ free_netdev(info->netdev);
+ info->netdev = NULL;
}
-#endif /* ifdef CONFIG_SYNCLINK_SYNCPPP */
+#endif /* CONFIG_HDLC */
+
static int __devinit synclink_init_one (struct pci_dev *dev,
const struct pci_device_id *ent)